io.micrometer
micrometer-observation-test
diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java
index 6b6dcac34b..9a763ba7c7 100644
--- a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java
+++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java
@@ -21,6 +21,8 @@
import io.dapr.spring.boot.properties.client.ClientPropertiesDaprConnectionDetails;
import io.dapr.spring.boot.properties.client.DaprClientProperties;
import io.dapr.spring.boot.properties.client.DaprConnectionDetails;
+import io.dapr.spring.observation.client.ObservationDaprClient;
+import io.dapr.spring.observation.client.ObservationDaprWorkflowClient;
import io.dapr.workflows.client.DaprWorkflowClient;
import io.dapr.workflows.runtime.WorkflowRuntimeBuilder;
import io.micrometer.observation.ObservationRegistry;
diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/ObservationDaprClient.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/ObservationDaprClient.java
deleted file mode 100644
index 2529a65a95..0000000000
--- a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/ObservationDaprClient.java
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright 2025 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.spring.boot.autoconfigure.client;
-
-import io.dapr.client.DaprClient;
-import io.dapr.client.domain.BulkPublishRequest;
-import io.dapr.client.domain.BulkPublishResponse;
-import io.dapr.client.domain.ConfigurationItem;
-import io.dapr.client.domain.DaprMetadata;
-import io.dapr.client.domain.DeleteJobRequest;
-import io.dapr.client.domain.DeleteStateRequest;
-import io.dapr.client.domain.ExecuteStateTransactionRequest;
-import io.dapr.client.domain.GetBulkSecretRequest;
-import io.dapr.client.domain.GetBulkStateRequest;
-import io.dapr.client.domain.GetConfigurationRequest;
-import io.dapr.client.domain.GetJobRequest;
-import io.dapr.client.domain.GetJobResponse;
-import io.dapr.client.domain.GetSecretRequest;
-import io.dapr.client.domain.GetStateRequest;
-import io.dapr.client.domain.HttpExtension;
-import io.dapr.client.domain.InvokeBindingRequest;
-import io.dapr.client.domain.InvokeMethodRequest;
-import io.dapr.client.domain.PublishEventRequest;
-import io.dapr.client.domain.SaveStateRequest;
-import io.dapr.client.domain.ScheduleJobRequest;
-import io.dapr.client.domain.State;
-import io.dapr.client.domain.StateOptions;
-import io.dapr.client.domain.SubscribeConfigurationRequest;
-import io.dapr.client.domain.SubscribeConfigurationResponse;
-import io.dapr.client.domain.TransactionalStateOperation;
-import io.dapr.client.domain.UnsubscribeConfigurationRequest;
-import io.dapr.client.domain.UnsubscribeConfigurationResponse;
-import io.dapr.utils.TypeRef;
-import io.grpc.Channel;
-import io.grpc.stub.AbstractStub;
-import io.micrometer.observation.Observation;
-import io.micrometer.observation.ObservationRegistry;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/**
- * A {@link DaprClient} decorator that creates Micrometer Observation spans (bridged to OpenTelemetry)
- * for each non-deprecated method call. Consumers continue to use {@link DaprClient} as-is; no code
- * changes are required on their side.
- *
- * Deprecated methods are delegated directly without any observation.
- */
-public class ObservationDaprClient implements DaprClient {
-
- private final DaprClient delegate;
- private final ObservationRegistry observationRegistry;
-
- /**
- * Creates a new {@code ObservationDaprClient}.
- *
- * @param delegate the underlying {@link DaprClient} to delegate calls to
- * @param observationRegistry the Micrometer {@link ObservationRegistry} used to create spans
- */
- public ObservationDaprClient(DaprClient delegate, ObservationRegistry observationRegistry) {
- this.delegate = Objects.requireNonNull(delegate, "delegate must not be null");
- this.observationRegistry = Objects.requireNonNull(observationRegistry,
- "observationRegistry must not be null");
- }
-
- // -------------------------------------------------------------------------
- // Internal helpers
- // -------------------------------------------------------------------------
-
- private Mono observe(Observation obs, Supplier> monoSupplier) {
- return Mono.defer(() -> {
- obs.start();
- return monoSupplier.get()
- .doOnError(obs::error)
- .doFinally(signal -> obs.stop());
- });
- }
-
- private Flux observeFlux(Observation obs, Supplier> fluxSupplier) {
- return Flux.defer(() -> {
- obs.start();
- return fluxSupplier.get()
- .doOnError(obs::error)
- .doFinally(signal -> obs.stop());
- });
- }
-
- private static String safe(String value) {
- return value != null ? value : "";
- }
-
- private Observation observation(String name) {
- return Observation.createNotStarted(name, observationRegistry);
- }
-
- // -------------------------------------------------------------------------
- // Lifecycle
- // -------------------------------------------------------------------------
-
- @Override
- public Mono waitForSidecar(int timeoutInMilliseconds) {
- return observe(observation("dapr.client.wait_for_sidecar"),
- () -> delegate.waitForSidecar(timeoutInMilliseconds));
- }
-
- @Override
- public Mono shutdown() {
- return observe(observation("dapr.client.shutdown"),
- () -> delegate.shutdown());
- }
-
- @Override
- public void close() throws Exception {
- delegate.close();
- }
-
- // -------------------------------------------------------------------------
- // Pub/Sub
- // -------------------------------------------------------------------------
-
- @Override
- public Mono publishEvent(String pubsubName, String topicName, Object data) {
- return observe(
- observation("dapr.client.publish_event")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(pubsubName))
- .highCardinalityKeyValue("dapr.topic.name", safe(topicName)),
- () -> delegate.publishEvent(pubsubName, topicName, data));
- }
-
- @Override
- public Mono publishEvent(String pubsubName, String topicName, Object data,
- Map metadata) {
- return observe(
- observation("dapr.client.publish_event")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(pubsubName))
- .highCardinalityKeyValue("dapr.topic.name", safe(topicName)),
- () -> delegate.publishEvent(pubsubName, topicName, data, metadata));
- }
-
- @Override
- public Mono publishEvent(PublishEventRequest request) {
- return observe(
- observation("dapr.client.publish_event")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(request.getPubsubName()))
- .highCardinalityKeyValue("dapr.topic.name", safe(request.getTopic())),
- () -> delegate.publishEvent(request));
- }
-
- @Override
- public Mono> publishEvents(BulkPublishRequest request) {
- return observe(
- observation("dapr.client.publish_events")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(request.getPubsubName()))
- .highCardinalityKeyValue("dapr.topic.name", safe(request.getTopic())),
- () -> delegate.publishEvents(request));
- }
-
- @Override
- public Mono> publishEvents(String pubsubName, String topicName,
- String contentType, List events) {
- return observe(
- observation("dapr.client.publish_events")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(pubsubName))
- .highCardinalityKeyValue("dapr.topic.name", safe(topicName)),
- () -> delegate.publishEvents(pubsubName, topicName, contentType, events));
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public Mono> publishEvents(String pubsubName, String topicName,
- String contentType, T... events) {
- return observe(
- observation("dapr.client.publish_events")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(pubsubName))
- .highCardinalityKeyValue("dapr.topic.name", safe(topicName)),
- () -> delegate.publishEvents(pubsubName, topicName, contentType, events));
- }
-
- @Override
- public Mono> publishEvents(String pubsubName, String topicName,
- String contentType,
- Map requestMetadata,
- List events) {
- return observe(
- observation("dapr.client.publish_events")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(pubsubName))
- .highCardinalityKeyValue("dapr.topic.name", safe(topicName)),
- () -> delegate.publishEvents(pubsubName, topicName, contentType, requestMetadata, events));
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public Mono> publishEvents(String pubsubName, String topicName,
- String contentType,
- Map requestMetadata,
- T... events) {
- return observe(
- observation("dapr.client.publish_events")
- .highCardinalityKeyValue("dapr.pubsub.name", safe(pubsubName))
- .highCardinalityKeyValue("dapr.topic.name", safe(topicName)),
- () -> delegate.publishEvents(pubsubName, topicName, contentType, requestMetadata, events));
- }
-
- // -------------------------------------------------------------------------
- // Service Invocation — all deprecated, delegate directly
- // -------------------------------------------------------------------------
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, Object data,
- HttpExtension httpExtension, Map metadata,
- TypeRef type) {
- return delegate.invokeMethod(appId, methodName, data, httpExtension, metadata, type);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, Object request,
- HttpExtension httpExtension, Map metadata,
- Class clazz) {
- return delegate.invokeMethod(appId, methodName, request, httpExtension, metadata, clazz);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, Object request,
- HttpExtension httpExtension, TypeRef type) {
- return delegate.invokeMethod(appId, methodName, request, httpExtension, type);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, Object request,
- HttpExtension httpExtension, Class clazz) {
- return delegate.invokeMethod(appId, methodName, request, httpExtension, clazz);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, HttpExtension httpExtension,
- Map metadata, TypeRef type) {
- return delegate.invokeMethod(appId, methodName, httpExtension, metadata, type);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, HttpExtension httpExtension,
- Map metadata, Class clazz) {
- return delegate.invokeMethod(appId, methodName, httpExtension, metadata, clazz);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, Object request,
- HttpExtension httpExtension, Map metadata) {
- return delegate.invokeMethod(appId, methodName, request, httpExtension, metadata);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, Object request,
- HttpExtension httpExtension) {
- return delegate.invokeMethod(appId, methodName, request, httpExtension);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, HttpExtension httpExtension,
- Map metadata) {
- return delegate.invokeMethod(appId, methodName, httpExtension, metadata);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(String appId, String methodName, byte[] request,
- HttpExtension httpExtension, Map metadata) {
- return delegate.invokeMethod(appId, methodName, request, httpExtension, metadata);
- }
-
- @Override
- @Deprecated
- public Mono invokeMethod(InvokeMethodRequest invokeMethodRequest, TypeRef type) {
- return delegate.invokeMethod(invokeMethodRequest, type);
- }
-
- // -------------------------------------------------------------------------
- // Bindings
- // -------------------------------------------------------------------------
-
- @Override
- public Mono invokeBinding(String bindingName, String operation, Object data) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(bindingName))
- .highCardinalityKeyValue("dapr.binding.operation", safe(operation)),
- () -> delegate.invokeBinding(bindingName, operation, data));
- }
-
- @Override
- public Mono invokeBinding(String bindingName, String operation, byte[] data,
- Map metadata) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(bindingName))
- .highCardinalityKeyValue("dapr.binding.operation", safe(operation)),
- () -> delegate.invokeBinding(bindingName, operation, data, metadata));
- }
-
- @Override
- public Mono invokeBinding(String bindingName, String operation, Object data,
- TypeRef type) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(bindingName))
- .highCardinalityKeyValue("dapr.binding.operation", safe(operation)),
- () -> delegate.invokeBinding(bindingName, operation, data, type));
- }
-
- @Override
- public Mono invokeBinding(String bindingName, String operation, Object data,
- Class clazz) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(bindingName))
- .highCardinalityKeyValue("dapr.binding.operation", safe(operation)),
- () -> delegate.invokeBinding(bindingName, operation, data, clazz));
- }
-
- @Override
- public Mono invokeBinding(String bindingName, String operation, Object data,
- Map metadata, TypeRef type) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(bindingName))
- .highCardinalityKeyValue("dapr.binding.operation", safe(operation)),
- () -> delegate.invokeBinding(bindingName, operation, data, metadata, type));
- }
-
- @Override
- public Mono invokeBinding(String bindingName, String operation, Object data,
- Map metadata, Class clazz) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(bindingName))
- .highCardinalityKeyValue("dapr.binding.operation", safe(operation)),
- () -> delegate.invokeBinding(bindingName, operation, data, metadata, clazz));
- }
-
- @Override
- public Mono invokeBinding(InvokeBindingRequest request) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(request.getName()))
- .highCardinalityKeyValue("dapr.binding.operation", safe(request.getOperation())),
- () -> delegate.invokeBinding(request));
- }
-
- @Override
- public Mono invokeBinding(InvokeBindingRequest request, TypeRef type) {
- return observe(
- observation("dapr.client.invoke_binding")
- .highCardinalityKeyValue("dapr.binding.name", safe(request.getName()))
- .highCardinalityKeyValue("dapr.binding.operation", safe(request.getOperation())),
- () -> delegate.invokeBinding(request, type));
- }
-
- // -------------------------------------------------------------------------
- // State Management
- // -------------------------------------------------------------------------
-
- @Override
- public Mono> getState(String storeName, State state, TypeRef type) {
- return observe(
- observation("dapr.client.get_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(state.getKey())),
- () -> delegate.getState(storeName, state, type));
- }
-
- @Override
- public Mono> getState(String storeName, State state, Class clazz) {
- return observe(
- observation("dapr.client.get_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(state.getKey())),
- () -> delegate.getState(storeName, state, clazz));
- }
-
- @Override
- public Mono> getState(String storeName, String key, TypeRef type) {
- return observe(
- observation("dapr.client.get_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.getState(storeName, key, type));
- }
-
- @Override
- public Mono> getState(String storeName, String key, Class clazz) {
- return observe(
- observation("dapr.client.get_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.getState(storeName, key, clazz));
- }
-
- @Override
- public Mono> getState(String storeName, String key, StateOptions options,
- TypeRef type) {
- return observe(
- observation("dapr.client.get_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.getState(storeName, key, options, type));
- }
-
- @Override
- public Mono> getState(String storeName, String key, StateOptions options,
- Class clazz) {
- return observe(
- observation("dapr.client.get_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.getState(storeName, key, options, clazz));
- }
-
- @Override
- public Mono> getState(GetStateRequest request, TypeRef type) {
- return observe(
- observation("dapr.client.get_state")
- .highCardinalityKeyValue("dapr.store.name", safe(request.getStoreName()))
- .highCardinalityKeyValue("dapr.state.key", safe(request.getKey())),
- () -> delegate.getState(request, type));
- }
-
- @Override
- public Mono>> getBulkState(String storeName, List keys,
- TypeRef type) {
- return observe(
- observation("dapr.client.get_bulk_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName)),
- () -> delegate.getBulkState(storeName, keys, type));
- }
-
- @Override
- public Mono>> getBulkState(String storeName, List keys,
- Class clazz) {
- return observe(
- observation("dapr.client.get_bulk_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName)),
- () -> delegate.getBulkState(storeName, keys, clazz));
- }
-
- @Override
- public Mono>> getBulkState(GetBulkStateRequest request, TypeRef type) {
- return observe(
- observation("dapr.client.get_bulk_state")
- .highCardinalityKeyValue("dapr.store.name", safe(request.getStoreName())),
- () -> delegate.getBulkState(request, type));
- }
-
- @Override
- public Mono executeStateTransaction(String storeName,
- List> operations) {
- return observe(
- observation("dapr.client.execute_state_transaction")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName)),
- () -> delegate.executeStateTransaction(storeName, operations));
- }
-
- @Override
- public Mono executeStateTransaction(ExecuteStateTransactionRequest request) {
- return observe(
- observation("dapr.client.execute_state_transaction")
- .highCardinalityKeyValue("dapr.store.name", safe(request.getStateStoreName())),
- () -> delegate.executeStateTransaction(request));
- }
-
- @Override
- public Mono saveBulkState(String storeName, List> states) {
- return observe(
- observation("dapr.client.save_bulk_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName)),
- () -> delegate.saveBulkState(storeName, states));
- }
-
- @Override
- public Mono saveBulkState(SaveStateRequest request) {
- return observe(
- observation("dapr.client.save_bulk_state")
- .highCardinalityKeyValue("dapr.store.name", safe(request.getStoreName())),
- () -> delegate.saveBulkState(request));
- }
-
- @Override
- public Mono saveState(String storeName, String key, Object value) {
- return observe(
- observation("dapr.client.save_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.saveState(storeName, key, value));
- }
-
- @Override
- public Mono saveState(String storeName, String key, String etag, Object value,
- StateOptions options) {
- return observe(
- observation("dapr.client.save_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.saveState(storeName, key, etag, value, options));
- }
-
- @Override
- public Mono saveState(String storeName, String key, String etag, Object value,
- Map meta, StateOptions options) {
- return observe(
- observation("dapr.client.save_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.saveState(storeName, key, etag, value, meta, options));
- }
-
- @Override
- public Mono deleteState(String storeName, String key) {
- return observe(
- observation("dapr.client.delete_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.deleteState(storeName, key));
- }
-
- @Override
- public Mono deleteState(String storeName, String key, String etag,
- StateOptions options) {
- return observe(
- observation("dapr.client.delete_state")
- .highCardinalityKeyValue("dapr.store.name", safe(storeName))
- .highCardinalityKeyValue("dapr.state.key", safe(key)),
- () -> delegate.deleteState(storeName, key, etag, options));
- }
-
- @Override
- public Mono deleteState(DeleteStateRequest request) {
- return observe(
- observation("dapr.client.delete_state")
- .highCardinalityKeyValue("dapr.store.name", safe(request.getStateStoreName()))
- .highCardinalityKeyValue("dapr.state.key", safe(request.getKey())),
- () -> delegate.deleteState(request));
- }
-
- // -------------------------------------------------------------------------
- // Secrets
- // -------------------------------------------------------------------------
-
- @Override
- public Mono
+