System.Diagnostics.Activity Update and Distributed Tracing in C#

Tsuyoshi Ushio
5 min readJan 2, 2020

--

I heard that the Activity class has a big update at 4.6.0 Currently latest is 4.7.0 I wrote some code to enable distributed tracing on 4.5.0 I’d like to share some experiment that what is the differences between 4.5.0 and 4.7.0 I tested on netstandard2.0

For the fundamental of Activity, please refer to this blog.

I can’t find a specific release, not that shows differences, so I’m writing that I noticed at least. For the Overview is listed below:

  • Microsoft.ApplicationInsights dependency is gone for W3C
  • Interface changes
  • Activity.Id
  • Activity.Current assignment
  • Default IdFormat

Microsoft.ApplicationInsights dependency is gone for W3C

The biggest change I love is, we don’t need Microsoft.ApplicationInsights.DependencyCollector for handling W3C TraceContext. Activity class belongs to System.Diagnostics.DiagnosticSource NuGet package. Until 4.5.0 , if we want to use W3C Trace Context , You need to add Microsoft.ApplicationInsights.DependencyCollector for adding extension methods for the Activity class.

This is my csproj file differences. I also use DiagnosticListener for the project.

System.Diagnostics.DiagnosticSource 4.5.0 (old)

<ItemGroup><PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.5.0" /><PackageReference Include="System.Reactive.Core" Version="3.1.1" /><PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.8.0" /></ItemGroup>

System.Diagnostics.DiagnosticSource 4.7.0 (new)

<ItemGroup><PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.7.0" /><PackageReference Include="System.Reactive.Core" Version="4.3.2" /></ItemGroup>

Interface changes

It has several breaking changes for interfaces.

IdFormat methods

We used to need to use theGenerateW3CContext() method for W3C Trace Context. Now it’s gone. Instead, we need to set ActivityIdFormat enum.

Old

Instantiate a new activity for W3C (old)

New

Instantiate a new activity for W3C(new)

If you don’t specify the IdFormat, it will be the Hierachical that mean HttpCorrelation protocol. However, is there is Activity.Current it is automatically set as a parent. The IdFormat is automatically inherited from the IdFormat of the parent.

SetParent

If you want to correlation, you need to use SetParent Method. However, In the case of the W3C trace context, it looked different. It becomes very simple. It also has different SetParentId method that takes traceId spanId

SetParentId (another parameters)

Old

Set Parent for W3C (Old)

New

Set Parent for W3C (New)

methods for W3C

Methods for W3C has been changed. TraceContext related value is managed by tag at 4.5.0 . For 4.7.0 Activity has individual properties for W3C. Also, the new version introduces a new class ActivityTraceId and ActivitySpanId . When I use the old version, I need to write a method to handle these by myself. Now I can remove these methods. I use the ToString() method for showing the Ids, however, You can also use ToHexString() method.

Old

methods(old)

New

Methods(new)

Activity.Id

The Activity.Id was used to be the Http Correlation Protocol even if it uses the W3C trace context. Because W3C Trace Context was an additional feature of Activity.

Old

4.5.0 sample for W3C trace context on Activity

New

4.7.0 sample for W3C Trace context on Activity

Activity.Current assignment

We couldn’t assign an Activity instance to Activity. Current. I used do it by using reflection. Now we can do it.

Activity.Current = parent;

Activity. Current is automatically assigned when you start the activity. However, sometimes, you might want to override by your self.

Default IdFormat

When there is Activity. Current instance, Activity automatically thinks it is the parent. The behavior is the same as the old and new. The point is, IdFormat(W3C or Hierarchical), is automatically defined if there is Activity. Current. Let me show an example. After I use the W3C trace context, right after that, If I execute this method. See what happens.

4.7.0 code for Http Correlation Protocol

Surprisingly, It becomes W3C TraceContext format even if I specify SetIdFormat as ActivityIdFormat.Hierarchical .

The outcome of the code

I’m not sure if it is expected behavior, so I post issue on the repo.

To avoid this, simply clear Activity.Current

Code avoid using the type of Activity. Current
The outcome of the improved code

Azure Function/WebJobs

Azure Functions / WebJobs are using System.DiagnosticSource new API. It is 4.6.0. However, You can use these APIs. The change is introduced by this

For Azure Functions, the W3C Trace context becomes the default. You can find the option EnableW3CDistributedTracing on the official documentation.

The code is here.

Also, The W3C telemetries that are sent for the portal are changed. The request/dependency Id was traceparent. Now it is Span Id. Parent Id is also changed into ParentSpanId from Parent’s traceparent.

Portal View

Conclusion

Activity Behavior change

The new Activity enable us to remove the dependency of Application Insights, also, support W3C without adding extension. Now we can assign Activity.Current by my self. However, there is some behavior change Activity.Id . Please note the SetIdFormat behavior as I wrote.

When I wrote a distributed tracing code using 4.5.0 I clearly separate code for W3C and HttpCorrelation protocol. Since there was a lot of difference on the code, now the interface is similar.

Resource

This is a sample program for comparison.

--

--