Skip to content

Commit

Permalink
[otlp] Export instrumentation scope attributes from ActivitySource.Ta…
Browse files Browse the repository at this point in the history
…gs (#5897)

Co-authored-by: Mikel Blanchard <[email protected]>
  • Loading branch information
rajkumar-rangaraj and CodeBlanch authored Oct 15, 2024
1 parent 963ec41 commit cddc091
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 44 deletions.
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Notes](../../RELEASENOTES.md).

## Unreleased

* Added support for exporting instrumentation scope attributes from
`ActivitySource.Tags`.
([#5897](https:/open-telemetry/opentelemetry-dotnet/pull/5897))

## 1.10.0-beta.1

Released 2024-Sep-30
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ internal static void AddBatch(
};
request.ResourceSpans.Add(resourceSpans);

var maxTags = sdkLimitOptions.AttributeCountLimit ?? int.MaxValue;

foreach (var activity in activityBatch)
{
Span? span = activity.ToOtlpSpan(sdkLimitOptions);
Expand All @@ -44,15 +46,15 @@ internal static void AddBatch(
}

var activitySourceName = activity.Source.Name;
if (!spansByLibrary.TryGetValue(activitySourceName, out var spans))
if (!spansByLibrary.TryGetValue(activitySourceName, out var scopeSpans))
{
spans = GetSpanListFromPool(activitySourceName, activity.Source.Version);
scopeSpans = GetSpanListFromPool(activity.Source, maxTags, sdkLimitOptions.AttributeValueLengthLimit);

spansByLibrary.Add(activitySourceName, spans);
resourceSpans.ScopeSpans.Add(spans);
spansByLibrary.Add(activitySourceName, scopeSpans);
resourceSpans.ScopeSpans.Add(scopeSpans);
}

spans.Spans.Add(span);
scopeSpans.Spans.Add(span);
}
}

Expand All @@ -65,34 +67,69 @@ internal static void Return(this ExportTraceServiceRequest request)
return;
}

foreach (var scope in resourceSpans.ScopeSpans)
foreach (var scopeSpan in resourceSpans.ScopeSpans)
{
scope.Spans.Clear();
SpanListPool.Add(scope);
scopeSpan.Spans.Clear();
scopeSpan.Scope.Attributes.Clear();
SpanListPool.Add(scopeSpan);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ScopeSpans GetSpanListFromPool(string name, string? version)
internal static ScopeSpans GetSpanListFromPool(ActivitySource activitySource, int maxTags, int? attributeValueLengthLimit)
{
if (!SpanListPool.TryTake(out var spans))
if (!SpanListPool.TryTake(out var scopeSpans))
{
spans = new ScopeSpans
scopeSpans = new ScopeSpans
{
Scope = new InstrumentationScope
{
Name = name, // Name is enforced to not be null, but it can be empty.
Version = version ?? string.Empty, // NRE throw by proto
Name = activitySource.Name, // Name is enforced to not be null, but it can be empty.
Version = activitySource.Version ?? string.Empty, // NRE throw by proto
},
};
}
else
{
spans.Scope.Name = name;
spans.Scope.Version = version ?? string.Empty;
scopeSpans.Scope.Name = activitySource.Name; // Name is enforced to not be null, but it can be empty.
scopeSpans.Scope.Version = activitySource.Version ?? string.Empty; // NRE throw by proto
}

if (activitySource.Tags != null)
{
var scopeAttributes = scopeSpans.Scope.Attributes;

if (activitySource.Tags is IReadOnlyList<KeyValuePair<string, object?>> activitySourceTagsList)
{
for (int i = 0; i < activitySourceTagsList.Count; i++)
{
if (scopeAttributes.Count < maxTags)
{
OtlpTagWriter.Instance.TryWriteTag(ref scopeAttributes, activitySourceTagsList[i], attributeValueLengthLimit);
}
else
{
scopeSpans.Scope.DroppedAttributesCount++;
}
}
}
else
{
foreach (var tag in activitySource.Tags)
{
if (scopeAttributes.Count < maxTags)
{
OtlpTagWriter.Instance.TryWriteTag(ref scopeAttributes, tag, attributeValueLengthLimit);
}
else
{
scopeSpans.Scope.DroppedAttributesCount++;
}
}
}
}

return spans;
return scopeSpans;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public async Task TestRecoveryAfterFailedExport()
await httpClient.GetAsync($"/MockCollector/SetResponseCodes/{string.Join(",", codes.Select(x => (int)x))}");

var exportResults = new List<ExportResult>();
var otlpExporter = new OtlpTraceExporter(new OtlpExporterOptions() { Endpoint = new Uri($"http://localhost:{testGrpcPort}") });
using var otlpExporter = new OtlpTraceExporter(new OtlpExporterOptions() { Endpoint = new Uri($"http://localhost:{testGrpcPort}") });
var delegatingExporter = new DelegatingExporter<Activity>
{
OnExportFunc = (batch) =>
Expand Down Expand Up @@ -183,7 +183,7 @@ public async Task GrpcRetryTests(bool useRetryTransmissionHandler, ExportResult
.AddInMemoryCollection(new Dictionary<string, string?> { [ExperimentalOptions.OtlpRetryEnvVar] = useRetryTransmissionHandler ? "in_memory" : null })
.Build();

var otlpExporter = new OtlpTraceExporter(exporterOptions, new SdkLimitOptions(), new ExperimentalOptions(configuration));
using var otlpExporter = new OtlpTraceExporter(exporterOptions, new SdkLimitOptions(), new ExperimentalOptions(configuration));

var activitySourceName = "otel.grpc.retry.test";
using var source = new ActivitySource(activitySourceName);
Expand Down Expand Up @@ -268,7 +268,7 @@ public async Task HttpRetryTests(bool useRetryTransmissionHandler, ExportResult
.AddInMemoryCollection(new Dictionary<string, string?> { [ExperimentalOptions.OtlpRetryEnvVar] = useRetryTransmissionHandler ? "in_memory" : null })
.Build();

var otlpExporter = new OtlpTraceExporter(exporterOptions, new SdkLimitOptions(), new ExperimentalOptions(configuration));
using var otlpExporter = new OtlpTraceExporter(exporterOptions, new SdkLimitOptions(), new ExperimentalOptions(configuration));

var activitySourceName = "otel.http.retry.test";
using var source = new ActivitySource(activitySourceName);
Expand Down Expand Up @@ -371,7 +371,7 @@ public async Task HttpPersistentStorageRetryTests(bool usePersistentStorageTrans
transmissionHandler = new OtlpExporterTransmissionHandler<ExportTraceServiceRequest>(exportClient, exporterOptions.TimeoutMilliseconds);
}

var otlpExporter = new OtlpTraceExporter(exporterOptions, new(), new(), transmissionHandler);
using var otlpExporter = new OtlpTraceExporter(exporterOptions, new(), new(), transmissionHandler);

var activitySourceName = "otel.http.persistent.storage.retry.test";
using var source = new ActivitySource(activitySourceName);
Expand Down Expand Up @@ -510,7 +510,7 @@ public async Task GrpcPersistentStorageRetryTests(bool usePersistentStorageTrans
transmissionHandler = new OtlpExporterTransmissionHandler<ExportTraceServiceRequest>(exportClient, exporterOptions.TimeoutMilliseconds);
}

var otlpExporter = new OtlpTraceExporter(exporterOptions, new(), new(), transmissionHandler);
using var otlpExporter = new OtlpTraceExporter(exporterOptions, new(), new(), transmissionHandler);

var activitySourceName = "otel.grpc.persistent.storage.retry.test";
using var source = new ActivitySource(activitySourceName);
Expand Down
Loading

0 comments on commit cddc091

Please sign in to comment.