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}