-
-
Notifications
You must be signed in to change notification settings - Fork 229
feat: Add support to send OTEL traces via OTLP #4899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2122abb
a2fb0e4
442fc7d
08d8711
907850b
6f8312d
8fbbf89
1ea156a
83f9097
ee67a6e
d1597d8
c8856a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| using Sentry.Extensibility; | ||
| using Sentry.Internal.OpenTelemetry; | ||
|
|
||
| namespace Sentry.OpenTelemetry; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| using Sentry.Extensibility; | ||
| using Sentry.Internal; | ||
|
|
||
| namespace Sentry.OpenTelemetry; | ||
|
|
||
| internal class OtelPropagationContext : IPropagationContext | ||
| { | ||
| public DynamicSamplingContext? DynamicSamplingContext { get; private set; } | ||
|
|
||
| public SentryId TraceId => Activity.Current?.TraceId.AsSentryId() ?? default; | ||
| public SpanId SpanId => Activity.Current?.SpanId.AsSentrySpanId() ?? default; | ||
| public SpanId? ParentSpanId => Activity.Current?.ParentSpanId.AsSentrySpanId(); | ||
|
|
||
| /// <summary> | ||
| /// Warning: this method may throw an exception if Activity.Current is null. | ||
| /// This method should not be used when instrumenting with OTEL. | ||
| /// </summary> | ||
| public DynamicSamplingContext GetOrCreateDynamicSamplingContext(SentryOptions options, IReplaySession replaySession) | ||
| { | ||
| if (DynamicSamplingContext is null) | ||
| { | ||
| options.LogDebug("Creating the Dynamic Sampling Context from the Propagation Context."); | ||
| DynamicSamplingContext = this.CreateDynamicSamplingContext(options, replaySession); | ||
| } | ||
|
|
||
| return DynamicSamplingContext; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| using OpenTelemetry; | ||
| using OpenTelemetry.Context.Propagation; | ||
| using Sentry.Extensibility; | ||
| using Sentry.Internal.OpenTelemetry; | ||
|
|
||
| namespace Sentry.OpenTelemetry; | ||
|
|
||
|
|
@@ -49,12 +50,12 @@ private static class OTelKeys | |
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public override PropagationContext Extract<T>(PropagationContext context, T carrier, Func<T, string, IEnumerable<string>> getter) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Flash0ver turns out I had to bring the bump to 1.10.0 forward in order to address this... and it looks like the bump introduces a breaking change - they changed the nullability on some of the methods in a base class that we're overriding. Unfortunately this is on a class that is also marked as Still... bit of a pain. |
||
| public override PropagationContext Extract<T>(PropagationContext context, T carrier, Func<T, string, IEnumerable<string>?> getter) | ||
| { | ||
| Options?.LogDebug("SentryPropagator.Extract"); | ||
|
|
||
| var result = base.Extract(context, carrier, getter); | ||
| var baggage = result.Baggage; // The Otel .NET SDK takes care of baggage headers alread | ||
| var baggage = result.Baggage; // The Otel .NET SDK takes care of baggage headers already | ||
|
|
||
| Options?.LogDebug("Baggage"); | ||
| foreach (var entry in baggage) | ||
|
|
@@ -121,13 +122,17 @@ public override void Inject<T>(PropagationContext context, T carrier, Action<T, | |
| base.Inject(context, carrier, setter); | ||
| } | ||
|
|
||
| private static SentryTraceHeader? TryGetSentryTraceHeader<T>(T carrier, Func<T, string, IEnumerable<string>> getter) | ||
| private static SentryTraceHeader? TryGetSentryTraceHeader<T>(T carrier, Func<T, string, IEnumerable<string>?> getter) | ||
| { | ||
| var headerValue = getter(carrier, SentryTraceHeader.HttpHeaderName); | ||
| if (headerValue is null) | ||
| { | ||
| return null; | ||
| } | ||
| try | ||
| { | ||
| var value = new StringValues(headerValue.ToArray()); | ||
| return SentryTraceHeader.Parse(value); | ||
| return SentryTraceHeader.Parse(value!); | ||
| } | ||
| catch (Exception) | ||
| { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Root activity ParentSpanId returns zero instead of null
Medium Severity
OtelPropagationContext.ParentSpanIdreturns a non-null zeroSpanId("0000000000000000") for root activities instead ofnull. WhenActivity.Currentis a root activity (no parent),Activity.ParentSpanIdreturnsdefault(ActivitySpanId), whichAsSentrySpanId()converts to a validSpanId. The?.operator only producesnullwhenActivity.Currentitself is null. This causes events captured during root OTEL activities to include a bogusparent_span_idin their trace context, inconsistent withSentryPropagationContextwhich correctly usesnullfor root spans.