Skip to content

Commit dda8cbf

Browse files
authored
Opamp client api (#1835)
1 parent 0b1780d commit dda8cbf

File tree

3 files changed

+201
-3
lines changed

3 files changed

+201
-3
lines changed

opamp-client/build.gradle.kts

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,75 @@
1+
import de.undercouch.gradle.tasks.download.Download
2+
import de.undercouch.gradle.tasks.download.DownloadExtension
3+
import groovy.json.JsonSlurper
4+
15
plugins {
26
id("otel.java-conventions")
7+
id("de.undercouch.download") version "5.6.0"
8+
id("com.squareup.wire") version "5.3.1"
39
}
410

511
description = "Client implementation of the OpAMP spec."
612
otelJava.moduleName.set("io.opentelemetry.contrib.opamp.client")
713

8-
java {
9-
sourceCompatibility = JavaVersion.VERSION_1_8
10-
targetCompatibility = JavaVersion.VERSION_1_8
14+
dependencies {
15+
annotationProcessor("com.google.auto.value:auto-value")
16+
compileOnly("com.google.auto.value:auto-value-annotations")
17+
}
18+
19+
val opampReleaseInfo = tasks.register<Download>("opampLastReleaseInfo") {
20+
group = "opamp"
21+
src("https://api.github.com/repos/open-telemetry/opamp-spec/releases/latest")
22+
dest(project.layout.buildDirectory.file("opamp/release.json"))
23+
}
24+
25+
val opampProtos = tasks.register<DownloadOpampProtos>("opampProtoDownload", download)
26+
opampProtos.configure {
27+
group = "opamp"
28+
dependsOn(opampReleaseInfo)
29+
lastReleaseInfoJson.set {
30+
opampReleaseInfo.get().dest
31+
}
32+
outputProtosDir.set(project.layout.buildDirectory.dir("opamp/protos"))
33+
downloadedZipFile.set(project.layout.buildDirectory.file("intermediate/$name/release.zip"))
34+
}
35+
36+
wire {
37+
java {}
38+
sourcePath {
39+
srcDir(opampProtos)
40+
}
41+
}
42+
43+
abstract class DownloadOpampProtos @Inject constructor(
44+
private val download: DownloadExtension,
45+
private val archiveOps: ArchiveOperations,
46+
private val fileOps: FileSystemOperations,
47+
) : DefaultTask() {
48+
49+
@get:InputFile
50+
abstract val lastReleaseInfoJson: RegularFileProperty
51+
52+
@get:OutputDirectory
53+
abstract val outputProtosDir: DirectoryProperty
54+
55+
@get:Internal
56+
abstract val downloadedZipFile: RegularFileProperty
57+
58+
@Suppress("UNCHECKED_CAST")
59+
@TaskAction
60+
fun execute() {
61+
val releaseInfo = JsonSlurper().parse(lastReleaseInfoJson.get().asFile) as Map<String, String>
62+
val zipUrl = releaseInfo["zipball_url"]
63+
download.run {
64+
src(zipUrl)
65+
dest(downloadedZipFile)
66+
}
67+
val protos = archiveOps.zipTree(downloadedZipFile).matching {
68+
setIncludes(listOf("**/*.proto"))
69+
}
70+
fileOps.sync {
71+
from(protos.files)
72+
into(outputProtosDir)
73+
}
74+
}
1175
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.opamp.client.internal;
7+
8+
import io.opentelemetry.opamp.client.internal.response.MessageData;
9+
import opamp.proto.AgentDescription;
10+
import opamp.proto.RemoteConfigStatus;
11+
import opamp.proto.ServerErrorResponse;
12+
13+
public interface OpampClient {
14+
15+
/**
16+
* Starts the client and begin attempts to connect to the Server. Once connection is established
17+
* the client will attempt to maintain it by reconnecting if the connection is lost. All failed
18+
* connection attempts will be reported via {@link Callbacks#onConnectFailed(OpampClient,
19+
* Throwable)} callback.
20+
*
21+
* <p>This method does not wait until the connection to the Server is established and will likely
22+
* return before the connection attempts are even made.
23+
*
24+
* <p>This method may be called only once.
25+
*
26+
* @param callbacks The Callback to which the Client will notify about any Server requests and
27+
* responses.
28+
*/
29+
void start(Callbacks callbacks);
30+
31+
/**
32+
* Stops the client. May be called only after {@link #start(Callbacks)}. May be called only once.
33+
* After this call returns successfully it is guaranteed that no callbacks will be called. Once
34+
* stopped, the client cannot be started again.
35+
*/
36+
void stop();
37+
38+
/**
39+
* Sets attributes of the Agent. The attributes will be included in the next status report sent to
40+
* the Server. When called after {@link #start(Callbacks)}, the attributes will be included in the
41+
* next outgoing status report. This is typically used by Agents which allow their
42+
* AgentDescription to change dynamically while the OpAMPClient is started. May be also called
43+
* from {@link Callbacks#onMessage(OpampClient, MessageData)}.
44+
*
45+
* @param agentDescription The new agent description.
46+
*/
47+
void setAgentDescription(AgentDescription agentDescription);
48+
49+
/**
50+
* Sets the current remote config status which will be sent in the next agent to server request.
51+
*
52+
* @param remoteConfigStatus The new remote config status.
53+
*/
54+
void setRemoteConfigStatus(RemoteConfigStatus remoteConfigStatus);
55+
56+
interface Callbacks {
57+
/**
58+
* Called when the connection is successfully established to the Server. May be called after
59+
* {@link #start(Callbacks)} is called and every time a connection is established to the Server.
60+
* For WebSocket clients this is called after the handshake is completed without any error. For
61+
* HTTP clients this is called for any request if the response status is OK.
62+
*
63+
* @param client The relevant {@link OpampClient} instance.
64+
*/
65+
void onConnect(OpampClient client);
66+
67+
/**
68+
* Called when the connection to the Server cannot be established. May be called after {@link
69+
* #start(Callbacks)} is called and tries to connect to the Server. May also be called if the
70+
* connection is lost and reconnection attempt fails.
71+
*
72+
* @param client The relevant {@link OpampClient} instance.
73+
* @param throwable The exception.
74+
*/
75+
void onConnectFailed(OpampClient client, Throwable throwable);
76+
77+
/**
78+
* Called when the Server reports an error in response to some previously sent request. Useful
79+
* for logging purposes. The Agent should not attempt to process the error by reconnecting or
80+
* retrying previous operations. The client handles the ErrorResponse_UNAVAILABLE case
81+
* internally by performing retries as necessary.
82+
*
83+
* @param client The relevant {@link OpampClient} instance.
84+
* @param errorResponse The error returned by the Server.
85+
*/
86+
void onErrorResponse(OpampClient client, ServerErrorResponse errorResponse);
87+
88+
/**
89+
* Called when the Agent receives a message that needs processing. See {@link MessageData}
90+
* definition for the data that may be available for processing. During onMessage execution the
91+
* {@link OpampClient} functions that change the status of the client may be called, e.g. if
92+
* RemoteConfig is processed then {@link #setRemoteConfigStatus(opamp.proto.RemoteConfigStatus)}
93+
* should be called to reflect the processing result. These functions may also be called after
94+
* onMessage returns. This is advisable if processing can take a long time. In that case
95+
* returning quickly is preferable to avoid blocking the {@link OpampClient}.
96+
*
97+
* @param client The relevant {@link OpampClient} instance.
98+
* @param messageData The server response data that needs processing.
99+
*/
100+
void onMessage(OpampClient client, MessageData messageData);
101+
}
102+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.opamp.client.internal.response;
7+
8+
import com.google.auto.value.AutoValue;
9+
import io.opentelemetry.opamp.client.internal.OpampClient;
10+
import javax.annotation.Nullable;
11+
import opamp.proto.AgentRemoteConfig;
12+
13+
/**
14+
* Data class provided in {@link OpampClient.Callbacks#onMessage(OpampClient, MessageData)} with
15+
* Server's provided status changes.
16+
*/
17+
@AutoValue
18+
public abstract class MessageData {
19+
@Nullable
20+
public abstract AgentRemoteConfig getRemoteConfig();
21+
22+
public static Builder builder() {
23+
return new AutoValue_MessageData.Builder();
24+
}
25+
26+
@AutoValue.Builder
27+
public abstract static class Builder {
28+
public abstract Builder setRemoteConfig(AgentRemoteConfig remoteConfig);
29+
30+
public abstract MessageData build();
31+
}
32+
}

0 commit comments

Comments
 (0)