Skip to content

Commit 6d53eb9

Browse files
torosentCopilot
andcommitted
Address PR review comments
- Move create_orchestration span into scheduleNewOrchestrationInstance() so SDK creates it automatically (bachuv feedback: span should not be in user code). TYPE_CREATE_ORCHESTRATION is now used by the client. - Remove manual span creation from TracingPattern sample; simplify code - Update all 4 screenshots with latest trace structure - README span detail shows activity:GetWeather attributes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 33d0808 commit 6d53eb9

File tree

7 files changed

+37
-41
lines changed

7 files changed

+37
-41
lines changed

client/src/main/java/com/microsoft/durabletask/DurableTaskGrpcClient.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import com.microsoft.durabletask.implementation.protobuf.TaskHubSidecarServiceGrpc.*;
1010

1111
import io.grpc.*;
12+
import io.opentelemetry.api.trace.Span;
13+
import io.opentelemetry.context.Scope;
1214

1315
import javax.annotation.Nullable;
1416
import java.time.Duration;
@@ -135,14 +137,30 @@ public String scheduleNewOrchestrationInstance(
135137
builder.putAllTags(options.getTags());
136138
}
137139

138-
TraceContext traceContext = TracingHelper.getCurrentTraceContext();
139-
if (traceContext != null) {
140-
builder.setParentTraceContext(traceContext);
141-
}
140+
// Create a create_orchestration span (matching .NET SDK pattern)
141+
Map<String, String> spanAttrs = new HashMap<>();
142+
spanAttrs.put(TracingHelper.ATTR_TYPE, TracingHelper.TYPE_CREATE_ORCHESTRATION);
143+
spanAttrs.put(TracingHelper.ATTR_TASK_NAME, orchestratorName);
144+
spanAttrs.put(TracingHelper.ATTR_INSTANCE_ID, instanceId);
145+
Span createSpan = TracingHelper.startSpan(
146+
TracingHelper.TYPE_CREATE_ORCHESTRATION + ":" + orchestratorName,
147+
null, null, spanAttrs);
148+
Scope createScope = createSpan.makeCurrent();
142149

143-
CreateInstanceRequest request = builder.build();
144-
CreateInstanceResponse response = this.sidecarClient.startInstance(request);
145-
return response.getInstanceId();
150+
try {
151+
// Capture trace context from the create_orchestration span
152+
TraceContext traceContext = TracingHelper.getCurrentTraceContext();
153+
if (traceContext != null) {
154+
builder.setParentTraceContext(traceContext);
155+
}
156+
157+
CreateInstanceRequest request = builder.build();
158+
CreateInstanceResponse response = this.sidecarClient.startInstance(request);
159+
return response.getInstanceId();
160+
} finally {
161+
createScope.close();
162+
createSpan.end();
163+
}
146164
}
147165

148166
@Override

samples/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ Full span hierarchy showing the fan-out/fan-in pattern with paired Client+Server
6868

6969
![Jaeger trace detail](images/jaeger-full-trace-detail.png)
7070

71-
### Jaeger — Span Attributes (Timer)
71+
### Jaeger — Span Attributes
7272

73-
Timer span showing attributes aligned with the .NET SDK schema:
74-
- `durabletask.type=timer`
75-
- `durabletask.task.name=FanOutFanIn`
76-
- `durabletask.fire_at=2026-03-03T21:13:15.142Z`
73+
Activity span showing attributes aligned with the .NET SDK schema:
74+
- `durabletask.type=activity`
75+
- `durabletask.task.name=GetWeather`
7776
- `durabletask.task.instance_id=<orchestrationId>`
77+
- `durabletask.task.task_id=1`
7878
- `otel.scope.name=Microsoft.DurableTask`
79-
- `span.kind=internal`
79+
- `span.kind=server`
8080

8181
![Jaeger span detail](images/jaeger-span-detail.png)
8282

-21.4 KB
Loading
3.29 KB
Loading
3.61 KB
Loading
-2 Bytes
Loading

samples/src/main/java/io/durabletask/samples/TracingPattern.java

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@
66
import com.microsoft.durabletask.azuremanaged.DurableTaskSchedulerClientExtensions;
77
import com.microsoft.durabletask.azuremanaged.DurableTaskSchedulerWorkerExtensions;
88

9-
import io.opentelemetry.api.GlobalOpenTelemetry;
10-
import io.opentelemetry.api.trace.Span;
11-
import io.opentelemetry.api.trace.StatusCode;
12-
import io.opentelemetry.api.trace.Tracer;
13-
import io.opentelemetry.context.Context;
14-
import io.opentelemetry.context.Scope;
159
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
1610
import io.opentelemetry.sdk.OpenTelemetrySdk;
1711
import io.opentelemetry.sdk.resources.Resource;
@@ -41,9 +35,6 @@
4135
final class TracingPattern {
4236
private static final Logger logger = Logger.getLogger(TracingPattern.class.getName());
4337

44-
// Shared parent context so activity spans become children of the orchestration span
45-
private static volatile Context orchestrationContext;
46-
4738
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
4839
// Configure OpenTelemetry with OTLP exporter to Jaeger
4940
String otlpEndpoint = System.getenv("OTEL_EXPORTER_OTLP_ENDPOINT");
@@ -68,7 +59,6 @@ public static void main(String[] args) throws IOException, InterruptedException,
6859
.setTracerProvider(tracerProvider)
6960
.buildAndRegisterGlobal();
7061

71-
Tracer tracer = openTelemetry.getTracer("Microsoft.DurableTask");
7262
logger.info("OpenTelemetry configured with OTLP exporter at " + otlpEndpoint);
7363

7464
// Build connection string for DTS emulator
@@ -149,29 +139,17 @@ public TaskOrchestration create() {
149139
DurableTaskClient client = DurableTaskSchedulerClientExtensions
150140
.createClientBuilder(connectionString).build();
151141

152-
// Create a parent span — the SDK automatically propagates W3C trace context
153-
Span orchestrationSpan = tracer.spanBuilder("create_orchestration:FanOutFanIn")
154-
.setAttribute("durabletask.task.name", "FanOutFanIn")
155-
.setAttribute("durabletask.type", "orchestration")
156-
.startSpan();
157-
158-
orchestrationContext = Context.current().with(orchestrationSpan);
159-
160-
String instanceId;
161-
try (Scope scope = orchestrationSpan.makeCurrent()) {
162-
logger.info("Scheduling FanOutFanIn orchestration...");
163-
instanceId = client.scheduleNewOrchestrationInstance(
164-
"FanOutFanIn",
165-
new NewOrchestrationInstanceOptions().setInput("weather-request"));
166-
orchestrationSpan.setAttribute("durabletask.task.instance_id", instanceId);
167-
logger.info("Started orchestration: " + instanceId);
168-
}
142+
// The SDK automatically creates a create_orchestration span and propagates W3C trace context
143+
logger.info("Scheduling FanOutFanIn orchestration...");
144+
String instanceId = client.scheduleNewOrchestrationInstance(
145+
"FanOutFanIn",
146+
new NewOrchestrationInstanceOptions().setInput("weather-request"));
147+
logger.info("Started orchestration: " + instanceId);
169148

170149
// Wait for completion
171150
logger.info("Waiting for completion...");
172151
OrchestrationMetadata result = client.waitForInstanceCompletion(
173152
instanceId, Duration.ofSeconds(60), true);
174-
orchestrationSpan.end();
175153

176154
logger.info("Status: " + result.getRuntimeStatus());
177155
logger.info("Result: " + result.readOutputAs(String.class));

0 commit comments

Comments
 (0)