diff --git a/sdk-actors/src/main/java/io/dapr/actors/ActorUtils.java b/sdk-actors/src/main/java/io/dapr/actors/ActorUtils.java index 105a96dd2..342b2a0f1 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/ActorUtils.java +++ b/sdk-actors/src/main/java/io/dapr/actors/ActorUtils.java @@ -49,4 +49,5 @@ public static String findActorTypeName(Class actorClass) { ActorType actorTypeAnnotation = node.getAnnotation(ActorType.class); return actorTypeAnnotation != null ? actorTypeAnnotation.name() : actorClass.getSimpleName(); } + } diff --git a/sdk-actors/src/main/java/io/dapr/actors/client/ActorClient.java b/sdk-actors/src/main/java/io/dapr/actors/client/ActorClient.java index 5017553ca..c69b60ff0 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/client/ActorClient.java +++ b/sdk-actors/src/main/java/io/dapr/actors/client/ActorClient.java @@ -16,6 +16,7 @@ import io.dapr.client.DaprApiProtocol; import io.dapr.client.DaprHttpBuilder; import io.dapr.config.Properties; +import io.dapr.utils.Version; import io.dapr.v1.DaprGrpc; import io.grpc.Channel; import io.grpc.ManagedChannel; @@ -102,7 +103,10 @@ private static ManagedChannel buildManagedChannel(DaprApiProtocol apiProtocol) { throw new IllegalArgumentException("Invalid port."); } - return ManagedChannelBuilder.forAddress(Properties.SIDECAR_IP.get(), port).usePlaintext().build(); + return ManagedChannelBuilder.forAddress(Properties.SIDECAR_IP.get(), port) + .usePlaintext() + .userAgent(Version.getSdkVersion()) + .build(); } /** diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntime.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntime.java index a4adcc5c2..f9870fd0d 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntime.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorRuntime.java @@ -20,6 +20,7 @@ import io.dapr.config.Properties; import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DefaultObjectSerializer; +import io.dapr.utils.Version; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import reactor.core.publisher.Mono; @@ -338,7 +339,10 @@ private static ManagedChannel buildManagedChannel() { throw new IllegalStateException("Invalid port."); } - return ManagedChannelBuilder.forAddress(Properties.SIDECAR_IP.get(), port).usePlaintext().build(); + return ManagedChannelBuilder.forAddress(Properties.SIDECAR_IP.get(), port) + .usePlaintext() + .userAgent(Version.getSdkVersion()) + .build(); } /** diff --git a/sdk/pom.xml b/sdk/pom.xml index e6c04275b..09efa68bf 100644 --- a/sdk/pom.xml +++ b/sdk/pom.xml @@ -25,6 +25,12 @@ + + org.apache.maven.plugins + maven-resources-plugin + 3.3.0 + maven-plugin + io.dapr dapr-sdk-autogen @@ -106,6 +112,22 @@ + + + src/main/resources + true + + **/sdk_version.properties + + + + src/main/resources + false + + **/sdk_version.properties + + + org.apache.maven.plugins diff --git a/sdk/src/main/java/io/dapr/client/DaprClientBuilder.java b/sdk/src/main/java/io/dapr/client/DaprClientBuilder.java index 855c6013e..7f3926c63 100644 --- a/sdk/src/main/java/io/dapr/client/DaprClientBuilder.java +++ b/sdk/src/main/java/io/dapr/client/DaprClientBuilder.java @@ -16,6 +16,7 @@ import io.dapr.config.Properties; import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DefaultObjectSerializer; +import io.dapr.utils.Version; import io.dapr.v1.DaprGrpc; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; @@ -158,7 +159,7 @@ private DaprClient buildDaprClientGrpc() { throw new IllegalArgumentException("Invalid port."); } ManagedChannel channel = ManagedChannelBuilder.forAddress( - Properties.SIDECAR_IP.get(), port).usePlaintext().build(); + Properties.SIDECAR_IP.get(), port).usePlaintext().userAgent(Version.getSdkVersion()).build(); Closeable closeableChannel = () -> { if (channel != null && !channel.isShutdown()) { channel.shutdown(); @@ -176,4 +177,5 @@ private DaprClient buildDaprClientGrpc() { private DaprClient buildDaprClientHttp() { return new DaprClientHttp(this.daprHttpBuilder.build(), this.objectSerializer, this.stateSerializer); } + } diff --git a/sdk/src/main/java/io/dapr/client/DaprHttp.java b/sdk/src/main/java/io/dapr/client/DaprHttp.java index 0172304d3..66b9c9a06 100644 --- a/sdk/src/main/java/io/dapr/client/DaprHttp.java +++ b/sdk/src/main/java/io/dapr/client/DaprHttp.java @@ -18,6 +18,7 @@ import io.dapr.config.Properties; import io.dapr.exceptions.DaprError; import io.dapr.exceptions.DaprException; +import io.dapr.utils.Version; import okhttp3.Call; import okhttp3.Callback; import okhttp3.HttpUrl; @@ -304,6 +305,8 @@ private CompletableFuture doInvokeApi(String method, if (daprApiToken != null) { requestBuilder.addHeader(Headers.DAPR_API_TOKEN, daprApiToken); } + + requestBuilder.addHeader(Headers.DAPR_USER_AGENT, Version.getSdkVersion()); if (headers != null) { Optional.ofNullable(headers.entrySet()).orElse(Collections.emptySet()).stream() diff --git a/sdk/src/main/java/io/dapr/client/Headers.java b/sdk/src/main/java/io/dapr/client/Headers.java index 13dfadc71..c65a5741e 100644 --- a/sdk/src/main/java/io/dapr/client/Headers.java +++ b/sdk/src/main/java/io/dapr/client/Headers.java @@ -27,4 +27,9 @@ class Headers { * Token for authentication from Application to Dapr runtime. */ static final String DAPR_API_TOKEN = "dapr-api-token"; + + /** + * Header for Api Logging User-Agent. + */ + static final String DAPR_USER_AGENT = "User-Agent"; } diff --git a/sdk/src/main/java/io/dapr/utils/Version.java b/sdk/src/main/java/io/dapr/utils/Version.java new file mode 100644 index 000000000..e55e77f4a --- /dev/null +++ b/sdk/src/main/java/io/dapr/utils/Version.java @@ -0,0 +1,46 @@ +/* + * Copyright 2022 The Dapr Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and +limitations under the License. +*/ + +package io.dapr.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public final class Version { + + private static String sdkVersion = null; + + /** + * Retrieves sdk version from resources. + * + * @return String version of sdk. + */ + public static String getSdkVersion() { + + if (sdkVersion != null) { + return sdkVersion; + } + + try (InputStream input = Version.class.getResourceAsStream("/sdk_version.properties");) { + Properties properties = new Properties(); + properties.load(input); + sdkVersion = "dapr-sdk-java/v" + properties.getProperty("sdk_version", "unknown"); + } catch (IOException e) { + sdkVersion = "unknown"; + } + + return sdkVersion; + } + +} diff --git a/sdk/src/main/resources/sdk_version.properties b/sdk/src/main/resources/sdk_version.properties new file mode 100644 index 000000000..10563b7f3 --- /dev/null +++ b/sdk/src/main/resources/sdk_version.properties @@ -0,0 +1 @@ +sdk_version=${project.version}