Skip to content

Commit 2765b97

Browse files
authored
Opamp first iteration completion (open-telemetry#2067)
1 parent ad68129 commit 2765b97

File tree

16 files changed

+269
-115
lines changed

16 files changed

+269
-115
lines changed

buildSrc/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies {
1616
implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.3.0")
1717
implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.2.0")
1818
implementation("org.owasp:dependency-check-gradle:12.1.3")
19+
implementation("ru.vyarus.animalsniffer:ru.vyarus.animalsniffer.gradle.plugin:2.0.1")
1920
}
2021

2122
spotless {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer
2+
3+
plugins {
4+
id("otel.java-conventions")
5+
id("ru.vyarus.animalsniffer")
6+
}
7+
8+
dependencies {
9+
signature("com.toasttab.android:gummy-bears-api-21:0.12.0:coreLib@signature")
10+
}
11+
12+
animalsniffer {
13+
sourceSets = listOf(java.sourceSets.main.get())
14+
}
15+
16+
// Always having declared output makes this task properly participate in tasks up-to-date checks
17+
tasks.withType<AnimalSniffer> {
18+
reports.text.required.set(true)
19+
}

disk-buffering/build.gradle.kts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2-
import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer
32

43
plugins {
54
id("otel.java-conventions")
65
id("otel.publish-conventions")
6+
id("otel.animalsniffer-conventions")
77
id("com.gradleup.shadow")
88
id("me.champeau.jmh") version "0.7.3"
9-
id("ru.vyarus.animalsniffer") version "2.0.1"
109
id("com.squareup.wire") version "5.3.11"
1110
}
1211

@@ -20,27 +19,12 @@ dependencies {
2019
implementation("io.opentelemetry:opentelemetry-api-incubator")
2120
compileOnly("com.google.auto.value:auto-value-annotations")
2221
annotationProcessor("com.google.auto.value:auto-value")
23-
signature("com.toasttab.android:gummy-bears-api-21:0.12.0:coreLib@signature")
2422
testImplementation("org.mockito:mockito-inline")
2523
testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
2624

2725
protos("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha@jar")
2826
}
2927

30-
animalsniffer {
31-
sourceSets = listOf(java.sourceSets.main.get())
32-
}
33-
34-
// Always having declared output makes this task properly participate in tasks up-to-date checks
35-
tasks.withType<AnimalSniffer> {
36-
reports.text.required.set(true)
37-
}
38-
39-
// Attaching animalsniffer check to the compilation process.
40-
tasks.named("classes").configure {
41-
finalizedBy("animalsnifferMain")
42-
}
43-
4428
jmh {
4529
warmupIterations.set(0)
4630
fork.set(2)

opamp-client/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,56 @@
33
Java implementation of the OpAMP
44
client [spec](https://github.com/open-telemetry/opamp-spec/blob/main/specification.md).
55

6+
> [!WARNING]
7+
> This is an incubating feature. Breaking changes can happen on a new release without previous
8+
> notice and without backward compatibility guarantees.
9+
10+
## Usage
11+
12+
```java
13+
// Initializing it
14+
15+
RequestService requestService = HttpRequestService.create(OkHttpSender.create("[OPAMP_SERVICE_URL]"));
16+
// RequestService requestService = WebSocketRequestService.create(OkHttpWebSocket.create("[OPAMP_SERVICE_URL]")); // Use this instead to connect to the server via WebSocket.
17+
OpampClient client =
18+
OpampClient.builder()
19+
.putIdentifyingAttribute("service.name", "My service name")
20+
.enableRemoteConfig()
21+
.setRequestService(requestService)
22+
.build(
23+
new OpampClient.Callbacks() {
24+
@Override
25+
public void onConnect() {}
26+
27+
@Override
28+
public void onConnectFailed(@Nullable Throwable throwable) {}
29+
30+
@Override
31+
public void onErrorResponse(ServerErrorResponse errorResponse) {}
32+
33+
@Override
34+
public void onMessage(MessageData messageData) {
35+
AgentRemoteConfig remoteConfig = messageData.getRemoteConfig();
36+
if (remoteConfig != null) {
37+
// A remote config was received
38+
39+
// After applying it...
40+
client.setRemoteConfigStatus(
41+
new RemoteConfigStatus.Builder()
42+
.status(RemoteConfigStatuses.RemoteConfigStatuses_APPLIED)
43+
.build());
44+
}
45+
}
46+
});
47+
48+
// State update
49+
client.setAgentDescription(new AgentDescription.Builder().build());
50+
51+
// App shutdown
52+
client.close();
53+
54+
```
55+
656
## Component owners
757

858
- [Cesar Munoz](https://github.com/LikeTheSalad), Elastic

opamp-client/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import java.net.URL
44

55
plugins {
66
id("otel.java-conventions")
7+
id("otel.publish-conventions")
8+
id("otel.animalsniffer-conventions")
79
id("de.undercouch.download") version "5.6.0"
810
id("com.squareup.wire") version "5.3.11"
911
}
@@ -14,6 +16,7 @@ otelJava.moduleName.set("io.opentelemetry.contrib.opamp.client")
1416
dependencies {
1517
implementation("com.squareup.okhttp3:okhttp")
1618
implementation("com.github.f4b6a3:uuid-creator")
19+
implementation("io.opentelemetry:opentelemetry-api")
1720
annotationProcessor("com.google.auto.value:auto-value")
1821
compileOnly("com.google.auto.value:auto-value-annotations")
1922
testImplementation("org.mockito:mockito-inline")

opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClient.java

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,23 @@
66
package io.opentelemetry.opamp.client.internal;
77

88
import io.opentelemetry.opamp.client.internal.response.MessageData;
9+
import java.io.Closeable;
910
import javax.annotation.Nullable;
1011
import opamp.proto.AgentDescription;
1112
import opamp.proto.RemoteConfigStatus;
1213
import opamp.proto.ServerErrorResponse;
1314

14-
public interface OpampClient {
15+
public interface OpampClient extends Closeable {
1516

1617
static OpampClientBuilder builder() {
1718
return new OpampClientBuilder();
1819
}
1920

2021
/**
21-
* Starts the client and begin attempts to connect to the Server. Once connection is established
22-
* the client will attempt to maintain it by reconnecting if the connection is lost. All failed
23-
* connection attempts will be reported via {@link Callbacks#onConnectFailed(Throwable)} callback.
24-
*
25-
* <p>This method does not wait until the connection to the Server is established and will likely
26-
* return before the connection attempts are even made.
27-
*
28-
* <p>This method may be called only once.
29-
*
30-
* @param callbacks The Callback to which the Client will notify about any Server requests and
31-
* responses.
32-
*/
33-
void start(Callbacks callbacks);
34-
35-
/**
36-
* Stops the client. May be called only after {@link #start(Callbacks)}. May be called only once.
37-
* After this call returns successfully it is guaranteed that no callbacks will be called. Once
38-
* stopped, the client cannot be started again.
39-
*/
40-
void stop();
41-
42-
/**
43-
* Sets attributes of the Agent. The attributes will be included in the next status report sent to
44-
* the Server. When called after {@link #start(Callbacks)}, the attributes will be included in the
45-
* next outgoing status report. This is typically used by Agents which allow their
46-
* AgentDescription to change dynamically while the OpAMPClient is started. May be also called
47-
* from {@link Callbacks#onMessage(MessageData)}.
22+
* Sets attributes of the Agent. The attributes will be included in the next outgoing status
23+
* report. This is typically used by Agents which allow their AgentDescription to change
24+
* dynamically while the OpAMPClient is started. May be also called from {@link
25+
* Callbacks#onMessage(MessageData)}.
4826
*
4927
* @param agentDescription The new agent description.
5028
*/
@@ -59,16 +37,14 @@ static OpampClientBuilder builder() {
5937

6038
interface Callbacks {
6139
/**
62-
* Called when the connection is successfully established to the Server. May be called after
63-
* {@link #start(Callbacks)} is called and every time a connection is established to the Server.
64-
* For WebSocket clients this is called after the handshake is completed without any error. For
65-
* HTTP clients this is called for any request if the response status is OK.
40+
* Called when the connection is successfully established to the Server. For WebSocket clients
41+
* this is called after the handshake is completed without any error. For HTTP clients this is
42+
* called for any request if the response status is OK.
6643
*/
6744
void onConnect();
6845

6946
/**
70-
* Called when the connection to the Server cannot be established. May be called after {@link
71-
* #start(Callbacks)} is called and tries to connect to the Server. May also be called if the
47+
* Called when the connection to the Server cannot be established. May also be called if the
7248
* connection is lost and reconnection attempt fails.
7349
*
7450
* @param throwable The exception.

opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClientBuilder.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -381,11 +381,7 @@ public OpampClientBuilder setEffectiveConfigState(State.EffectiveConfig effectiv
381381
return this;
382382
}
383383

384-
public OpampClient build() {
385-
if (service == null) {
386-
throw new IllegalStateException(
387-
"The request service is not set. You must provide it by calling setRequestService()");
388-
}
384+
public OpampClient build(OpampClient.Callbacks callbacks) {
389385
List<KeyValue> protoIdentifyingAttributes = new ArrayList<>();
390386
List<KeyValue> protoNonIdentifyingAttributes = new ArrayList<>();
391387
identifyingAttributes.forEach(
@@ -411,7 +407,7 @@ public OpampClient build() {
411407
new State.InstanceUid(instanceUid),
412408
new State.Flags(0L),
413409
effectiveConfigState);
414-
return OpampClientImpl.create(service, state);
410+
return OpampClientImpl.create(service, state, callbacks);
415411
}
416412

417413
private static State.EffectiveConfig createEffectiveConfigNoop() {

opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/http/OkHttpSender.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.opamp.client.internal.connectivity.http;
77

8+
import io.opentelemetry.api.internal.InstrumentationUtil;
89
import java.io.IOException;
910
import java.io.InputStream;
1011
import java.util.concurrent.CompletableFuture;
@@ -13,6 +14,7 @@
1314
import okhttp3.Callback;
1415
import okhttp3.MediaType;
1516
import okhttp3.OkHttpClient;
17+
import okhttp3.Request;
1618
import okhttp3.RequestBody;
1719
import okio.BufferedSink;
1820

@@ -45,8 +47,16 @@ public CompletableFuture<Response> send(BodyWriter writer, int contentLength) {
4547
RequestBody body = new RawRequestBody(writer, contentLength, MEDIA_TYPE);
4648
builder.post(body);
4749

50+
// By suppressing instrumentations, we prevent automatic instrumentations for the okhttp request
51+
// that polls the opamp server.
52+
InstrumentationUtil.suppressInstrumentation(() -> doSendRequest(builder.build(), future));
53+
54+
return future;
55+
}
56+
57+
private void doSendRequest(Request request, CompletableFuture<Response> future) {
4858
client
49-
.newCall(builder.build())
59+
.newCall(request)
5060
.enqueue(
5161
new Callback() {
5262
@Override
@@ -59,8 +69,6 @@ public void onFailure(Call call, IOException e) {
5969
future.completeExceptionally(e);
6070
}
6171
});
62-
63-
return future;
6472
}
6573

6674
private static class OkHttpResponse implements Response {

0 commit comments

Comments
 (0)