diff --git a/opamp-client/README.md b/opamp-client/README.md index a5aa42fb9..d917f68b6 100644 --- a/opamp-client/README.md +++ b/opamp-client/README.md @@ -12,10 +12,9 @@ client [spec](https://github.com/open-telemetry/opamp-spec/blob/main/specificati ```java // Initializing it -RequestService requestService = HttpRequestService.create(OkHttpSender.create("[OPAMP_SERVICE_URL]")); -// RequestService requestService = WebSocketRequestService.create(OkHttpWebSocket.create("[OPAMP_SERVICE_URL]")); // Use this instead to connect to the server via WebSocket. OpampClient client = OpampClient.builder() + .setEndpoint("[OPAMP_SERVICE_URL]") .putIdentifyingAttribute("service.name", "My service name") .enableRemoteConfig() .setRequestService(requestService) diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java index d6af850fa..be5ce7e9c 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java @@ -7,19 +7,23 @@ import com.github.f4b6a3.uuid.UuidCreator; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.opamp.client.internal.Experimental; import io.opentelemetry.opamp.client.internal.connectivity.http.OkHttpSender; +import io.opentelemetry.opamp.client.internal.connectivity.websocket.OkHttpWebSocket; import io.opentelemetry.opamp.client.internal.impl.OpampClientImpl; import io.opentelemetry.opamp.client.internal.impl.OpampClientState; import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; +import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.request.service.WebSocketRequestService; import io.opentelemetry.opamp.client.internal.state.State; -import io.opentelemetry.opamp.client.request.service.RequestService; +import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.function.Function; import javax.annotation.Nullable; import opamp.proto.AgentCapabilities; import opamp.proto.AgentDescription; @@ -30,27 +34,57 @@ /** Builds an {@link OpampClient} instance. */ public final class OpampClientBuilder { + private static final String DEFAULT_ENDPOINT_URL = "http://localhost:4320/v1/opamp"; + private static final URI DEFAULT_ENDPOINT = URI.create(DEFAULT_ENDPOINT_URL); + private final Map identifyingAttributes = new HashMap<>(); private final Map nonIdentifyingAttributes = new HashMap<>(); private long capabilities = 0; - private RequestService service = - HttpRequestService.create(OkHttpSender.create("http://localhost:4320/v1/opamp")); + private Function serviceFactory = + endpoint -> { + String scheme = endpoint.getScheme(); + if ("ws".equalsIgnoreCase(scheme) || "wss".equalsIgnoreCase(scheme)) { + return WebSocketRequestService.create(OkHttpWebSocket.create(endpoint.toString())); + } else { + return HttpRequestService.create(OkHttpSender.create(endpoint.toString())); + } + }; + @Nullable private byte[] instanceUid; @Nullable private State.EffectiveConfig effectiveConfigState; + @Nullable private URI endpoint = DEFAULT_ENDPOINT; + + static { + Experimental.internalSetServiceFactory( + (builder, serviceFactory) -> builder.serviceFactory = serviceFactory); + } OpampClientBuilder() {} /** - * Sets an implementation of a {@link RequestService} to handle the request's sending process. - * There are 2 possible options, either {@link HttpRequestService} to use HTTP, or {@link - * WebSocketRequestService} to use WebSocket. + * Sets the OpAMP endpoint to connect to. If unset, defaults to {@value DEFAULT_ENDPOINT_URL}. The + * endpoint must start with either http://, https://, ws:// or wss://. Sets the address of the + * OpAMP Server. + * + * @param endpoint The OpAMP endpoint. + * @return this + */ + @CanIgnoreReturnValue + public OpampClientBuilder setEndpoint(String endpoint) { + return setEndpoint(URI.create(endpoint)); + } + + /** + * Sets the OpAMP endpoint to connect to. If unset, defaults to {@value DEFAULT_ENDPOINT_URL}. The + * endpoint must start with either http://, https://, ws:// or wss://. Sets the address of the + * OpAMP Server. * - * @param service The request service implementation. + * @param endpoint The OpAMP endpoint. * @return this */ @CanIgnoreReturnValue - public OpampClientBuilder setRequestService(RequestService service) { - this.service = service; + public OpampClientBuilder setEndpoint(URI endpoint) { + this.endpoint = endpoint; return this; } @@ -402,7 +436,7 @@ public OpampClient build(OpampClient.Callbacks callbacks) { new State.InstanceUid(instanceUid), new State.Flags(0L), effectiveConfigState); - return OpampClientImpl.create(service, state, callbacks); + return OpampClientImpl.create(serviceFactory.apply(endpoint), state, callbacks); } private static State.EffectiveConfig createEffectiveConfigNoop() { diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/Experimental.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/Experimental.java new file mode 100644 index 000000000..917e87b52 --- /dev/null +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/Experimental.java @@ -0,0 +1,42 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.opamp.client.internal; + +import io.opentelemetry.opamp.client.OpampClientBuilder; +import io.opentelemetry.opamp.client.internal.request.service.RequestService; +import java.net.URI; +import java.util.function.BiConsumer; +import java.util.function.Function; +import javax.annotation.Nullable; + +/** + * This class is internal and experimental. Its APIs are unstable and can change at any time. Its + * APIs (or a version of them) may be promoted to the public stable API in the future, but no + * guarantees are made. + */ +public final class Experimental { + + @Nullable + private static volatile BiConsumer> + setServiceFactory; + + /** + * Sets factory function for creating {@link RequestService} instances form a given server URI. + */ + public static void setServiceFactory( + OpampClientBuilder builder, Function serviceFactory) { + if (setServiceFactory != null) { + setServiceFactory.accept(builder, serviceFactory); + } + } + + public static void internalSetServiceFactory( + BiConsumer> setServiceFactory) { + Experimental.setServiceFactory = setServiceFactory; + } + + private Experimental() {} +} diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java index 1441093d7..12f5a5f75 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java @@ -19,12 +19,12 @@ import io.opentelemetry.opamp.client.internal.impl.recipe.appenders.SequenceNumberAppender; import io.opentelemetry.opamp.client.internal.request.Field; import io.opentelemetry.opamp.client.internal.request.Request; +import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.response.MessageData; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; import io.opentelemetry.opamp.client.internal.state.ObservableState; import io.opentelemetry.opamp.client.internal.state.State; -import io.opentelemetry.opamp.client.request.service.RequestService; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java index 8badaa98f..8c87d7bb4 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java @@ -14,7 +14,6 @@ import io.opentelemetry.opamp.client.internal.request.delay.RetryPeriodicDelay; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; -import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.IOException; import java.time.Duration; import java.util.Objects; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java similarity index 92% rename from opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java rename to opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java index 76d1650e3..44f32c32a 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java @@ -3,12 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.opamp.client.request.service; +package io.opentelemetry.opamp.client.internal.request.service; import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.request.Request; -import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; -import io.opentelemetry.opamp.client.internal.request.service.WebSocketRequestService; import io.opentelemetry.opamp.client.internal.response.Response; import java.util.function.Supplier; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java index 280725884..13ef9b117 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java @@ -13,7 +13,6 @@ import io.opentelemetry.opamp.client.internal.request.delay.RetryPeriodicDelay; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; -import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Duration; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java index 020b1b2e2..7963916c8 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java @@ -17,9 +17,9 @@ import io.opentelemetry.opamp.client.internal.connectivity.http.OkHttpSender; import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; +import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.response.MessageData; import io.opentelemetry.opamp.client.internal.state.State; -import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.IOException; import java.time.Duration; import java.util.ArrayList; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java index 9c5ea516d..cbaac6ee8 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java @@ -21,7 +21,6 @@ import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.request.delay.PeriodicDelay; import io.opentelemetry.opamp.client.internal.response.Response; -import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayInputStream; import java.time.Duration; import java.util.ArrayList; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java index 6e96554ea..12fce409d 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java @@ -23,7 +23,6 @@ import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; -import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Duration;