Skip to content

Commit 1834576

Browse files
torosentCopilot
andcommitted
fix: proper trace hierarchy — orchestration span as parent of child spans
Start orchestration span BEFORE executor runs so child spans (activities, timers, client spans) are nested under it. Each dispatch creates its own orchestration span, matching JS/dotnet behavior (multiple orchestration spans per trace). Depth is now 3: create_orchestration → orchestration → activity/timer spans. Updated all Jaeger and DTS dashboard screenshots. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 35830d8 commit 1834576

File tree

5 files changed

+26
-25
lines changed

5 files changed

+26
-25
lines changed

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

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -192,46 +192,47 @@ public void startAndBlock() {
192192
? startedEvent.getParentTraceContext() : null;
193193
String orchName = startedEvent != null ? startedEvent.getName() : "";
194194

195-
TaskOrchestratorResult taskOrchestratorResult;
196-
try {
197-
taskOrchestratorResult = taskOrchestrationExecutor.execute(
198-
orchestratorRequest.getPastEventsList(),
199-
orchestratorRequest.getNewEventsList(),
200-
null);
201-
} catch (Throwable e) {
202-
if (e instanceof Error) {
203-
throw (Error) e;
204-
}
205-
throw new RuntimeException(e);
206-
}
207-
208-
// Emit orchestration span only on completion/termination.
209-
// Uses ExecutionStartedEvent timestamp as span start time for full lifecycle coverage.
210-
// Note: Java OTel doesn't support SetSpanId(), so we can't make this span
211-
// the parent of child spans across dispatches like .NET does. Child spans
212-
// (activities, timers) are siblings under the create_orchestration span.
213-
boolean isCompleting = taskOrchestratorResult.getActions().stream()
214-
.anyMatch(a -> a.getOrchestratorActionTypeCase() == OrchestratorAction.OrchestratorActionTypeCase.COMPLETEORCHESTRATION
215-
|| a.getOrchestratorActionTypeCase() == OrchestratorAction.OrchestratorActionTypeCase.TERMINATEORCHESTRATION);
216-
217-
if (isCompleting && orchTraceCtx != null) {
195+
// Start the orchestration span BEFORE execution so child spans
196+
// (activities, timers) are nested under it in the trace hierarchy.
197+
// Each dispatch creates its own orchestration span (matching JS/dotnet behavior).
198+
Span orchestrationSpan = null;
199+
TraceContext orchestrationSpanContext = null;
200+
if (orchTraceCtx != null) {
218201
Map<String, String> orchSpanAttrs = new HashMap<>();
219202
orchSpanAttrs.put(TracingHelper.ATTR_TYPE, TracingHelper.TYPE_ORCHESTRATION);
220203
orchSpanAttrs.put(TracingHelper.ATTR_TASK_NAME, orchName);
221204
orchSpanAttrs.put(TracingHelper.ATTR_INSTANCE_ID, orchestratorRequest.getInstanceId());
222205

223206
Instant spanStartTime = null;
224-
if (startedHistoryEvent.hasTimestamp()) {
207+
if (startedHistoryEvent != null && startedHistoryEvent.hasTimestamp()) {
225208
spanStartTime = DataConverter.getInstantFromTimestamp(
226209
startedHistoryEvent.getTimestamp());
227210
}
228211

229-
Span orchestrationSpan = TracingHelper.startSpanWithStartTime(
212+
orchestrationSpan = TracingHelper.startSpanWithStartTime(
230213
TracingHelper.TYPE_ORCHESTRATION + ":" + orchName,
231214
orchTraceCtx,
232215
SpanKind.SERVER,
233216
orchSpanAttrs,
234217
spanStartTime);
218+
orchestrationSpanContext = TracingHelper.getCurrentTraceContext(orchestrationSpan);
219+
}
220+
221+
TaskOrchestratorResult taskOrchestratorResult;
222+
try {
223+
taskOrchestratorResult = taskOrchestrationExecutor.execute(
224+
orchestratorRequest.getPastEventsList(),
225+
orchestratorRequest.getNewEventsList(),
226+
orchestrationSpanContext);
227+
} catch (Throwable e) {
228+
if (e instanceof Error) {
229+
throw (Error) e;
230+
}
231+
throw new RuntimeException(e);
232+
}
233+
234+
// End the orchestration span for every dispatch
235+
if (orchestrationSpan != null) {
235236
orchestrationSpan.end();
236237
}
237238

-698 Bytes
Loading
17.8 KB
Loading
23.2 KB
Loading
-668 Bytes
Loading

0 commit comments

Comments
 (0)