Description
Component(s)
exporter/azuremonitor
What happened?
Description
The AzureMonitor exporter doesn't seem to export span links. I've had a look through the code and I can't see any mapping of span links taking place.
Steps to Reproduce
In a C# app with otel configured and pointing to a collector with the azure monitor exporter
var remoteActivity = GetActivityFromSomeRemoteSource();
var myActivity = CreateLocalActivityWithoutRemoteContext( links: new List<ActivityLink> { new ActivityLink(remoteActivity.Context} );
Expected Result
Link between activities to appear in application insights timeline view
Actual Result
No link in timeline view
Collector version
a2a52e43c1a80aa94120ad78c2db68780eb90e6d11c8db5b3ce2f6a0cc6b5029
Environment information
Environment
OS: (macos 14.7)
Collector image otel/opentelemetry-collector-contrib sha256:a2a52e43c1a80aa94120ad78c2db68780eb90e6d11c8db5b3ce2f6a0cc6b5029
Dotnet sdk: 8.0.401
OpenTelemetry.* Nuget packages: 1.9.0
OpenTelemetry Collector configuration
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
exporters:
debug:
verbosity: detailed # '
azuremonitor:
connection_string:
spaneventsenabled: true
service:
telemetry:
logs:
level: debug
pipelines:
traces:
receivers: [otlp]
processors: []
exporters: [ debug, azuremonitor]
logs:
receivers: [otlp]
processors: []
exporters: [debug, azuremonitor]
Log output
2024-10-17 09:16:32 SpanLink #0
2024-10-17 09:16:32 -> Trace ID: 8a399a6101a2783da2ee92c57c6dc77f
2024-10-17 09:16:32 -> ID: ce21439755dcecfe
2024-10-17 09:16:32 -> TraceState:
2024-10-17 09:16:32 -> DroppedAttributesCount: 0
Additional context
I've attached logs from the collector showing that span are being produced links
Workaround
Setting a tag on the localActivity with the key of _MS.links
and and array of operation links with the following schema links the activities in the application insights timeline view
[
{
"operation_Id": <remoteActivity.Context.TraceId>,
"id": <remoteActivity.Context.SpanId>
}
]
Processor
public class LinkProcessor : BaseProcessor<Activity>
{
public override void OnEnd(Activity data)
{
if (data.Links.Any())
{
var links = data.Links.Select(activityLink => new OperationLink(activityLink.Context.TraceId.ToString(), activityLink.Context.SpanId.ToString())).ToList();
data.SetTag("_MS.links", JsonSerializer.Serialize(links));
}
base.OnEnd(data);
}
private record OperationLink(
[property: JsonPropertyName("operation_Id")] string OperationId,
[property: JsonPropertyName("id")] string Id);
}