DataDog / dd-trace-dotnet

.NET Client Library for Datadog APM
https://docs.datadoghq.com/tracing/
Apache License 2.0
450 stars 140 forks source link

OpenTracing expose a way to create a parent span context #2268

Open tylerohlsen opened 2 years ago

tylerohlsen commented 2 years ago

I have my own way of triggering a downstream call to another process that I want to correlate with the upstream process trace. I don't see a way with the OpenTracing API (v2.0.1) for me to create a new parent context. SpanBuilder.AsChildOf does allow me to pass in an ISpanContext, but privately the SpanBuilder requires that ISpanContext to be of type OpenTracingSpanContext (reference) which is internal.

lucaspimentel commented 2 years ago

Thanks for bringing this to our attention, Tyler. I had not looked at this API in a long time, so I had to take some time to review it. And I agree, it's not great:

There is one very convoluted way to get an OpenTracingSpanContext instance that you can use now without changes to the tracer:

public OpenTracing.ISpanContext CreateSpanContext(OpenTracing.ITracer tracer, ulong traceId, ulong parentSpanId)
{
    var contextValues = new Dictionary<string, string>
    {
        { Datadog.Trace.HttpHeaderNames.TraceId, traceId.ToString(CultureInfo.InvariantCulture) },
        { Datadog.Trace.HttpHeaderNames.ParentId, parentSpanId.ToString(CultureInfo.InvariantCulture) }
    };

    var textMap = new OpenTracing.Propagation.TextMapExtractAdapter(contextValues);
    return tracer.Extract(OpenTracing.Propagation.BuiltinFormats.TextMap, textMap);
}

// usage
OpenTracing.ITracer tracer = ...;
ulong traceId = ...;
ulong parentSpanId = ...;

OpenTracing.ISpanContext spanContext = CreateSpanContext(tracer, traceId, parentSpanId);
OpenTracing.ISpanBuilder builder = tracer.BuildSpan(...).AsChildOf(spanContext);

I can think of two changes we can make to improve this situation. We could implement either one or both:

tylerohlsen commented 2 years ago

IMO, both of those changes would be beneficial.