I try to integrate OpenTelemetry with a console exporter in an application that uses WCF.
The problem is, that the trace id of my current System.Diagnostics.DiagnosticSource.Activity
is not propagated to the other side.
And thus on the other side the parent information is missing and the trace is broken.
I did turn on ActivityPropagation in WCF which is working when examining the logs.
The problem is, that my Activity on the other side has no/wrong Activity Id.
At the moment I am clueless what I can do to also propagate the System.Diagnostics.DiagnosticSource.Activity.Id
over WCF
- How do I set up OpenTelemetry or WCF correctly to propagate the Activity Id/Context?
The code is basically only the microsoft WCF Calculator Tutorial. Into which I try to integrate OpenTelemetry.
These are the parts where I am using to OpenTelemetry
Client:
public class Program
{
private static readonly ActivitySource MyActivitySource = new ActivitySource("MyCompany.MyProduct.MyClient");
public static void Main(string[] args)
{
var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("MyCompany.MyProduct.MyClient")
.AddConsoleExporter()
.Build();
using (var activity_wcf_session = MyActivitySource.StartActivity("WCF_Session"))
{
activity_wcf_session?.SetTag("index", 0);
//Step 1: Create an instance of the WCF proxy.
CalculatorClient client = new CalculatorClient();
// Step 2: Call the service operations.
// Call the Add service operation.
using (var activity = MyActivitySource.StartActivity("Client_call_add()"))
{
activity?.SetTag("msg", "foo");
double result = client.Add(100.00D, 15.99D);
}
// Step 3: Close the client to gracefully close the connection and clean up resources.
Console.WriteLine("\nPress <Enter> to terminate the wcf client.");
Console.ReadLine();
client.Close();
}
}
}
Service:
public class CalculatorService : ICalculator
{
private static readonly ActivitySource MyActivitySource = new ActivitySource(
"MyCompany.MyProduct.CalculatorService");
private TracerProvider tracerProvider;
public CalculatorService()
{
tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("MyCompany.MyProduct.CalculatorService")
.AddConsoleExporter()
.Build();
}
public double Add(double n1, double n2)
{
Console.WriteLine("Activity.Current is null: " + (Activity.Current == null)); // is always null
using (var activity = MyActivitySource.StartActivity("CalculatorService_add()", ActivityKind.Server))
{
// activity.parent is not set
double result = n1 + n2;
return result;
}
}
// ...
}
}
This is how I activated Activity-Propagation in the projects (same for host)
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information,ActivityTracing" propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="C:\logs\GettingStarted_Client.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="xml" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
You need to parse the HTTP headers and create the
Activity
on your own. Here's how you could do it:(Requirement: System.Diagnostics.DiagnosticSource nuget package.)
ActivityListener
s, otherwise theActivity
s created byActivitySource
s are going to be null. For example:Variations
IEndpointBehavior
, butIServiceBehavior
andIContractBehavior
would also have worked.headers[HeaderNames.SOAPAction]
for the activity name, but it could have been anything.BehaviorExtensionElement
though.Notes
IParameterInspector
, becauseAfterCall()
is not executed in case of failure.System.Diagnostics.Acitivity
s.