dd-trace-dotnet icon indicating copy to clipboard operation
dd-trace-dotnet copied to clipboard

Understand correct approach to encapsulating the `dd-trace-dotnet` sdk

Open robbiedhickey opened this issue 1 year ago β€’ 2 comments

Are you requesting automatic instrumentation for a framework or library? Please describe.

  • Framework or library name : Windows Service / Custom Instrumentation
  • Library type: worker process
  • Library version: 2.46.0

Is your feature request related to a problem? Please describe. I am attempting to encapsulate all of our Datadog SDK interactions into a centralized monitoring project shared between several of our solutions. Here is a simplified version of the API:

public class MonitoringContext
{
    public static IDisposable BeginTrace(
        string resourceName,
        Dictionary<string, string> tags = null)
    {
        var scope = Tracer.Instance.StartActive("method.call");
        scope.Span.ResourceName = resourceName;

        if (tags != null)
        {
            foreach (var tag in tags)
            {
                scope.Span.SetTag(tag.Key, tag.Value);
            }
        }

        return scope;
    }

    public static void TrackException(Exception e)
    {
        Tracer.Instance.ActiveScope.Span.SetException(e);
    }
}

This would then be used in the host project so that it did not have to take a direct dependency on the Datadog.Trace library (mainly to simplify the process of keeping the nuget package in sync with the tracer agent).

public class Worker
{
    public void DoWork()
    {
        using(MonitoringContext.BeginTrace("custom.worker"))
        {
            try
            {
                 // do work
            }
            catch(Exception e)
            {
                 MonitoringContext.TrackException(e);
            }
        }
    }
}

This approach was working for me locally while running the process in Visual Studio. However, once I deployed the application as a windows service my custom traces were no longer showing up.

I suspected that this had something to do with the indirection I was attempting. Sure enough, if I replace the Worker code above with direct references to the Tracer sdk, everything works exactly as I would expect.

Describe the solution you'd like I would like to know if there is an alternative approach to indirection/encapsulation that would work for my use case, and perhaps a bit of background on the implementation details that make my current approach incompatible with how the dd-trace-dotnet sdk works.

Describe alternatives you've considered As described, in-lining the Tracer sdk code directly instead of using the shared library works as expected.

Additional context Note that I've also tested this without the static implementation using thread local instances and see the same results.

robbiedhickey avatar Jan 25 '24 00:01 robbiedhickey

Why not just use ActivitySource + DD_TRACE_OTEL_ENABLED? Then you wouldn't need to worry about the dd trace SDK at all.

Hawxy avatar Feb 06 '24 06:02 Hawxy

I suspected that this had something to do with the indirection I was attempting. Sure enough, if I replace the Worker code above with direct references to the Tracer sdk, everything works exactly as I would expect.

AFAIK, this shouldn't happen πŸ€” What you've done should be perfectly fine as far as I can tell. Do you see any tracer logs when you use the encapsulated approach?

mainly to simplify the process of keeping the nuget package in sync with the tracer agent

This is certainly a good goal - though I have to admit it feels like encapsulating (i.e. forcing) the version is more likely to cause give you version conflict issues, but as long as you have found something that works for you πŸ™‚

FWIW, in an upcoming major version bump (v3) we're aiming to remove the version-conflict issue entirely - you'll be able to reference a single version of the NuGet package and increase the installed automatic instrumentation version, and everything should Just Workβ„’. Until then though, avoiding version conflict is still important!

Note that I've also tested this without the static implementation using thread local instances and see the same results.

This sounds very dubious, depending on exactly what you mean, thread local instances are likely to be problematic because of how the async local context flows around πŸ˜…

Why not just use ActivitySource + DD_TRACE_OTEL_ENABLED? Then you wouldn't need to worry about the dd trace SDK at all.

This is certainly a viable option, and if you're not using the Datadog.Trace NuGet package for anything more than you've shown, it may well be the best option for you πŸ™‚

andrewlock avatar Feb 13 '24 13:02 andrewlock

Closing this issue since it seems stale. If you're still having issues, please re-open or create a new issue, or contact the Datadog Support team at https://www.datadoghq.com/support/.

lucaspimentel avatar Aug 22 '24 19:08 lucaspimentel