Skip to content

Commit ee1b67a

Browse files
committed
Add entity operation trace span creation
Create trace spans for entity operation execution in OnRunEntityBatchAsync, using the trace context propagated from the parent orchestration. This completes the distributed tracing story for entities by making entity operations visible in trace viewers. - Add EntityOperation constant to TraceActivityConstants - Add StartTraceActivityForEntityOperation to TraceHelper - Create span with entity metadata tags in GrpcDurableTaskWorker.Processor
1 parent 6fade3c commit ee1b67a

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

src/Shared/Grpc/Tracing/TraceActivityConstants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ static class TraceActivityConstants
2424
/// </summary>
2525
public const string Event = "event";
2626

27+
/// <summary>
28+
/// The name of the activity that represents entity operation execution.
29+
/// </summary>
30+
public const string EntityOperation = "entity_operation";
31+
2732
/// <summary>
2833
/// The name of the activity that represents timer operations.
2934
/// </summary>

src/Shared/Grpc/Tracing/TraceHelper.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,58 @@ static class TraceHelper
156156
return newActivity;
157157
}
158158

159+
/// <summary>
160+
/// Starts a new trace activity for executing an entity operation.
161+
/// </summary>
162+
/// <param name="entityName">The name of the entity.</param>
163+
/// <param name="operationName">The name of the operation being executed.</param>
164+
/// <param name="instanceId">The instance ID of the entity.</param>
165+
/// <param name="traceParent">The W3C traceparent header value from the parent orchestration.</param>
166+
/// <param name="traceState">The W3C tracestate header value from the parent orchestration.</param>
167+
/// <returns>
168+
/// Returns a newly started <see cref="Activity"/> with entity operation metadata, or null if tracing is not enabled.
169+
/// </returns>
170+
public static Activity? StartTraceActivityForEntityOperation(
171+
string entityName,
172+
string? operationName,
173+
string instanceId,
174+
string? traceParent,
175+
string? traceState)
176+
{
177+
if (traceParent is null || !ActivityContext.TryParse(
178+
traceParent,
179+
traceState,
180+
out ActivityContext activityContext))
181+
{
182+
return null;
183+
}
184+
185+
string spanName = string.IsNullOrEmpty(operationName)
186+
? $"{TraceActivityConstants.EntityOperation}:{entityName}"
187+
: $"{TraceActivityConstants.EntityOperation}:{entityName}:{operationName}";
188+
189+
Activity? newActivity = ActivityTraceSource.StartActivity(
190+
spanName,
191+
kind: ActivityKind.Server,
192+
parentContext: activityContext);
193+
194+
if (newActivity == null)
195+
{
196+
return null;
197+
}
198+
199+
newActivity.SetTag(Schema.Task.Type, TraceActivityConstants.EntityOperation);
200+
newActivity.SetTag(Schema.Task.Name, entityName);
201+
newActivity.SetTag(Schema.Task.InstanceId, instanceId);
202+
203+
if (!string.IsNullOrEmpty(operationName))
204+
{
205+
newActivity.SetTag("durabletask.entity.operation", operationName);
206+
}
207+
208+
return newActivity;
209+
}
210+
159211
/// <summary>
160212
/// Emits a new trace activity for a (task) activity that successfully completes.
161213
/// </summary>

src/Worker/Grpc/GrpcDurableTaskWorker.Processor.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,15 @@ async Task OnRunEntityBatchAsync(
865865
var coreEntityId = DTCore.Entities.EntityId.FromString(batchRequest.InstanceId!);
866866
EntityId entityId = new(coreEntityId.Name, coreEntityId.Key);
867867

868+
// Start a trace span for entity operation execution using the first operation's trace context.
869+
OperationRequest? firstOp = batchRequest.Operations?.FirstOrDefault();
870+
using Activity? traceActivity = TraceHelper.StartTraceActivityForEntityOperation(
871+
entityId.Name,
872+
firstOp?.Operation,
873+
batchRequest.InstanceId!,
874+
firstOp?.TraceContext?.TraceParent,
875+
firstOp?.TraceContext?.TraceState);
876+
868877
TaskName name = new(entityId.Name);
869878

870879
EntityBatchResult? batchResult;
@@ -913,6 +922,8 @@ async Task OnRunEntityBatchAsync(
913922
{
914923
FailureDetails = new FailureDetails(frameworkException),
915924
};
925+
926+
traceActivity?.SetStatus(ActivityStatusCode.Error, frameworkException.Message);
916927
}
917928

918929
P.EntityBatchResult response = batchResult.ToEntityBatchResult(

0 commit comments

Comments
 (0)