Skip to content

Commit 946988a

Browse files
committed
Adding OpampClient and MessageData
1 parent 6bf15df commit 946988a

File tree

6 files changed

+1103
-1
lines changed

6 files changed

+1103
-1
lines changed

dependencyManagement/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ val DEPENDENCIES = listOf(
6767
"org.jctools:jctools-core:4.0.5",
6868
"tools.profiler:async-profiler:3.0",
6969
"com.blogspot.mydailyjava:weak-lock-free:0.18",
70-
"org.agrona:agrona:1.22.0"
70+
"org.agrona:agrona:1.22.0",
71+
"com.google.protobuf:protobuf-java:4.28.2"
7172
)
7273

7374
javaPlatform {

opamp-client/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
plugins {
22
id("otel.java-conventions")
3+
id("com.google.protobuf") version "0.9.4"
34
}
45

56
description = "Client implementation of the OpAMP spec."
@@ -9,3 +10,9 @@ java {
910
sourceCompatibility = JavaVersion.VERSION_1_8
1011
targetCompatibility = JavaVersion.VERSION_1_8
1112
}
13+
14+
dependencies {
15+
implementation("com.google.protobuf:protobuf-java")
16+
annotationProcessor("com.google.auto.value:auto-value")
17+
compileOnly("com.google.auto.value:auto-value-annotations")
18+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package io.opentelemetry.opamp.client.internal;
2+
3+
import io.opentelemetry.opamp.client.internal.response.MessageData;
4+
import opamp.proto.Opamp;
5+
6+
public interface OpampClient {
7+
8+
/**
9+
* Starts the client and begin attempts to connect to the Server. Once connection is established
10+
* the client will attempt to maintain it by reconnecting if the connection is lost. All failed
11+
* connection attempts will be reported via {@link Callback#onConnectFailed(OpampClient,
12+
* Throwable)} callback.
13+
*
14+
* <p>This method does not wait until the connection to the Server is established and will likely
15+
* return before the connection attempts are even made.
16+
*
17+
* <p>This method may be called only once.
18+
*
19+
* @param callback The Callback to which the Client will notify about any Server requests and
20+
* responses.
21+
*/
22+
void start(Callback callback);
23+
24+
/**
25+
* Stops the client. May be called only after {@link #start(OpampClient.Callback)}. May be called
26+
* only once. After this call returns successfully it is guaranteed that no callbacks will be
27+
* called. Once stopped, the client cannot be started again.
28+
*/
29+
void stop();
30+
31+
/**
32+
* Sets the current remote config status which will be sent in the next agent to server request.
33+
*
34+
* @param remoteConfigStatus The new remote config status.
35+
*/
36+
void setRemoteConfigStatus(Opamp.RemoteConfigStatus remoteConfigStatus);
37+
38+
/**
39+
* Sets the current effective config which will be sent in the next agent to server request.
40+
*
41+
* @param effectiveConfig The new effective config.
42+
*/
43+
void setEffectiveConfig(Opamp.EffectiveConfig effectiveConfig);
44+
45+
interface Callback {
46+
/**
47+
* Called when the connection is successfully established to the Server. May be called after
48+
* {@link #start(OpampClient.Callback)} is called and every time a connection is established to
49+
* the Server. For WebSocket clients this is called after the handshake is completed without any
50+
* error. For HTTP clients this is called for any request if the response status is OK.
51+
*
52+
* @param client The relevant {@link OpampClient} instance.
53+
*/
54+
void onConnect(OpampClient client);
55+
56+
/**
57+
* Called when the connection to the Server cannot be established. May be called after {@link
58+
* #start(OpampClient.Callback)} is called and tries to connect to the Server. May also be
59+
* called if the connection is lost and reconnection attempt fails.
60+
*
61+
* @param client The relevant {@link OpampClient} instance.
62+
* @param throwable The exception.
63+
*/
64+
void onConnectFailed(OpampClient client, Throwable throwable);
65+
66+
/**
67+
* Called when the Server reports an error in response to some previously sent request. Useful
68+
* for logging purposes. The Agent should not attempt to process the error by reconnecting or
69+
* retrying previous operations. The client handles the ErrorResponse_UNAVAILABLE case
70+
* internally by performing retries as necessary.
71+
*
72+
* @param client The relevant {@link OpampClient} instance.
73+
* @param errorResponse The error returned by the Server.
74+
*/
75+
void onErrorResponse(OpampClient client, Opamp.ServerErrorResponse errorResponse);
76+
77+
/**
78+
* Called when the Agent receives a message that needs processing. See {@link MessageData}
79+
* definition for the data that may be available for processing. During onMessage execution the
80+
* {@link OpampClient} functions that change the status of the client may be called, e.g. if
81+
* RemoteConfig is processed then {@link
82+
* #setRemoteConfigStatus(opamp.proto.Opamp.RemoteConfigStatus)} should be called to reflect the
83+
* processing result. These functions may also be called after onMessage returns. This is
84+
* advisable if processing can take a long time. In that case returning quickly is preferable to
85+
* avoid blocking the {@link OpampClient}.
86+
*
87+
* @param client The relevant {@link OpampClient} instance.
88+
* @param messageData The server response data that needs processing.
89+
*/
90+
void onMessage(OpampClient client, MessageData messageData);
91+
}
92+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.opentelemetry.opamp.client.internal.response;
2+
3+
import com.google.auto.value.AutoValue;
4+
import io.opentelemetry.opamp.client.internal.OpampClient;
5+
import javax.annotation.Nullable;
6+
import opamp.proto.Opamp;
7+
8+
/**
9+
* Data class provided in {@link OpampClient.Callback#onMessage(OpampClient, MessageData)} with
10+
* Server's provided status changes.
11+
*/
12+
@AutoValue
13+
public abstract class MessageData {
14+
@Nullable
15+
public abstract Opamp.AgentRemoteConfig getRemoteConfig();
16+
17+
public static Builder builder() {
18+
return new AutoValue_MessageData.Builder();
19+
}
20+
21+
@AutoValue.Builder
22+
public abstract static class Builder {
23+
public abstract Builder setRemoteConfig(Opamp.AgentRemoteConfig remoteConfig);
24+
25+
public abstract MessageData build();
26+
}
27+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright 2019, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// This file is copied and modified from https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/common/v1/common.proto
16+
// Modifications:
17+
// - Removal of unneeded InstrumentationLibrary and StringKeyValue messages.
18+
// - Change of go_package to reference a package in this repo.
19+
// - Removal of gogoproto usage.
20+
21+
syntax = "proto3";
22+
23+
package opamp.proto;
24+
25+
option go_package = "github.com/open-telemetry/opamp-go/protobufs";
26+
27+
// AnyValue is used to represent any type of attribute value. AnyValue may contain a
28+
// primitive value such as a string or integer or it may contain an arbitrary nested
29+
// object containing arrays, key-value lists and primitives.
30+
message AnyValue {
31+
// The value is one of the listed fields. It is valid for all values to be unspecified
32+
// in which case this AnyValue is considered to be "null".
33+
oneof value {
34+
string string_value = 1;
35+
bool bool_value = 2;
36+
int64 int_value = 3;
37+
double double_value = 4;
38+
ArrayValue array_value = 5;
39+
KeyValueList kvlist_value = 6;
40+
bytes bytes_value = 7;
41+
}
42+
}
43+
44+
// ArrayValue is a list of AnyValue messages. We need ArrayValue as a message
45+
// since oneof in AnyValue does not allow repeated fields.
46+
message ArrayValue {
47+
// Array of values. The array may be empty (contain 0 elements).
48+
repeated AnyValue values = 1;
49+
}
50+
51+
// KeyValueList is a list of KeyValue messages. We need KeyValueList as a message
52+
// since `oneof` in AnyValue does not allow repeated fields. Everywhere else where we need
53+
// a list of KeyValue messages (e.g. in Span) we use `repeated KeyValue` directly to
54+
// avoid unnecessary extra wrapping (which slows down the protocol). The 2 approaches
55+
// are semantically equivalent.
56+
message KeyValueList {
57+
// A collection of key/value pairs of key-value pairs. The list may be empty (may
58+
// contain 0 elements).
59+
repeated KeyValue values = 1;
60+
}
61+
62+
// KeyValue is a key-value pair that is used to store Span attributes, Link
63+
// attributes, etc.
64+
message KeyValue {
65+
string key = 1;
66+
AnyValue value = 2;
67+
}

0 commit comments

Comments
 (0)