Skip to content

feat: Add support to send OTEL traces via OTLP#4899

Merged
jamescrosswell merged 61 commits intomainfrom
oltp-integration
May 5, 2026
Merged

feat: Add support to send OTEL traces via OTLP#4899
jamescrosswell merged 61 commits intomainfrom
oltp-integration

Conversation

@jamescrosswell
Copy link
Copy Markdown
Collaborator

@jamescrosswell jamescrosswell commented Feb 9, 2026

Resolves: #4859

Problem

Sentry's .NET SDK has an existing OpenTelemetry integration (Sentry.OpenTelemetry) that works by acting as a bridge — it intercepts OTel spans via a custom SpanProcessor and converts them into Sentry's proprietary transaction/span format before sending them to Sentry's envelope endpoint. This works, but it means Sentry is translating OTel data into its own model, which adds complexity and loses fidelity. Meanwhile, Sentry now has a native OTLP (OpenTelemetry Protocol) endpoint that can ingest standard OTel traces directly — no translation needed.

Solution

This PR introduces a new NuGet package, Sentry.OpenTelemetry.Exporter, that lets users send traces to Sentry via the standard OTLP protocol instead of Sentry's proprietary format. The key pieces are:

New package with OTLP exporter wiring

TracerProviderBuilderExtensions.cs provides an AddSentryOtlp(dsn) extension method that configures the standard OpenTelemetry.Exporter.OpenTelemetryProtocol exporter to point at Sentry's OTLP traces endpoint (derived from the DSN). Users call .AddSentryOtlp(dsn) on their TracerProviderBuilder instead of the old .AddSentry().

Propagation context bridging

OtelPropagationContext.cs implements IPropagationContext by reading trace/span IDs from the current Activity (OTel's span representation) rather than from Sentry's internal state. SentryPropagator.cs ensures that Sentry's sentry-trace and baggage headers are still injected into outbound requests alongside the standard W3C traceparent, so that errors, replays, and other Sentry events can be linked to the correct OTLP trace.

Disabling redundant Sentry tracing

SentryOptionsExtensions.cs provides a UseOtlp() method on SentryOptions that sets the instrumenter to OpenTelemetry and disables Sentry's own tracing integrations (the SentryHttpMessageHandler span creation, DiagnosticSource listener, EF interception) to avoid duplicate spans. A new DisableSentryTracing option provides a clean way to turn off Sentry's built-in span creation when OTel is handling it.

GetBaggage safety

The public Hub.GetBaggage() method could throw an ArgumentOutOfRangeException when OTel tracing is active (because the Sentry TraceId is empty — the real trace ID lives on the Activity). This is now handled gracefully: when OTel is enabled, it logs a warning and returns an empty baggage header instead of throwing.

Samples and dependency updates

The ASP.NET Core, Azure Functions, and Console OTel samples are updated to use the new AddSentryOtlp(dsn) / UseOtlp() pattern, and all OTel package references are bumped to 1.15.0 (needed to fix an AOT compilation error with IL3050).

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 9, 2026

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Features ✨

  • feat: Add support to send OTEL traces via OTLP by jamescrosswell in #4899
  • feat: Add network details for session replay on iOS by jamescrosswell in #4891
  • feat: Add option to exclude certain HTTP statuses from tracing by jamescrosswell in #5034

Fixes 🐛

  • fix: prevent redundant native exceptions on Android/CoreCLR by jpnurmi in #5127
  • fix: memory leak when profiling is enabled by jamescrosswell in #5133
  • fix: prevent redundant native exceptions on iOS by jpnurmi in #5126
  • fix: prevent redundant native exceptions on Android/Mono by jpnurmi in #4676
    • Note: opt in by setting options.Native.ExperimentalOptions.SignalHandlerStrategy to Sentry.Android.SignalHandlerStrategy.ChainAtStart

Dependencies ⬆️

Deps

  • chore(deps): update Java SDK to v8.39.0 by github-actions in #5137
  • chore(deps): update Native SDK to v0.13.7 by github-actions in #5136
  • chore(deps): update Cocoa SDK to v9.10.0 by github-actions in #5132
  • chore(deps): update Cocoa SDK to v9.9.0 by github-actions in #5115
  • chore(deps): update Java SDK to v8.38.0 by github-actions in #5124

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 9, 2026

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against d2406ef

Comment thread samples/Sentry.Samples.OpenTelemetry.AspNetCore/Program.cs Outdated
Comment thread src/Sentry.OpenTelemetry/TracerProviderBuilderExtensions.cs Outdated
@jamescrosswell jamescrosswell mentioned this pull request Feb 9, 2026
Comment thread src/Sentry.OpenTelemetry/SentryOptionsExtensions.cs Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 9, 2026

Codecov Report

❌ Patch coverage is 76.72956% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.09%. Comparing base (c91416f) to head (e057d69).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...y.OpenTelemetry.Exporter/OtelPropagationContext.cs 71.92% 11 Missing and 5 partials ⚠️
src/Sentry/HubExtensions.cs 33.33% 3 Missing and 1 partial ⚠️
...i.CommunityToolkit.Mvvm/SentryOptionsExtensions.cs 0.00% 3 Missing ⚠️
...rc/Sentry.OpenTelemetry/SentryOptionsExtensions.cs 0.00% 3 Missing ⚠️
src/Sentry/SentryGraphQLHttpMessageHandler.cs 0.00% 2 Missing and 1 partial ⚠️
src/Sentry/SentryHttpMessageHandler.cs 0.00% 2 Missing and 1 partial ⚠️
.../Sentry.OpenTelemetry.Exporter/SentryPropagator.cs 50.00% 1 Missing and 1 partial ⚠️
src/Sentry/DynamicSamplingContext.cs 87.50% 1 Missing and 1 partial ⚠️
src/Sentry/Internal/IExternalPropagationContext.cs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4899      +/-   ##
==========================================
+ Coverage   74.07%   74.09%   +0.02%     
==========================================
  Files         501      506       +5     
  Lines       18113    18247     +134     
  Branches     3521     3564      +43     
==========================================
+ Hits        13417    13520     +103     
- Misses       3837     3857      +20     
- Partials      859      870      +11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jamescrosswell
Copy link
Copy Markdown
Collaborator Author

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Odd that we're still seeing this after having moved to conventional commits.

It doesn't look like the danger workflow is aware of our release.yml file or accounts for this in it's logic.

@Flash0ver any ideas what we might be doing wrong?

Comment thread src/Sentry.OpenTelemetry/TracerProviderBuilderExtensions.cs Outdated
@Flash0ver
Copy link
Copy Markdown
Member

@Flash0ver any ideas what we might be doing wrong?

I'm not sure how to remove the Danger Changelog Missing automation off the top of my head ... I'll look into it tomorrow.

Comment thread src/Sentry/Internal/Hub.cs Outdated
Comment thread src/Sentry.OpenTelemetry/SentryOptionsExtensions.cs Outdated
Comment thread src/Sentry.OpenTelemetry/Sentry.OpenTelemetry.csproj Outdated
Comment thread src/Sentry/DynamicSamplingContext.cs Outdated
@jamescrosswell
Copy link
Copy Markdown
Collaborator Author

jamescrosswell commented Feb 18, 2026

Dang...

ILC : AOT analysis error IL3050: OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ActivityExtensions.CreateRepeatedFieldOfSpanSetCountAction(): Using member 'System.Reflection.Emit.DynamicMethod.DynamicMethod(String,Type,Type[],Module,Boolean)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Creating a DynamicMethod requires dynamic code. [/Users/runner/work/sentry-dotnet/sentry-dotnet/test/Sentry.TrimTest/Sentry.TrimTest.csproj]

Note

Needs a bump to the Otel package dependencies... since we're putting this in a new Sentry package, it's not a breaking change.

evgenygunko pushed a commit to evgenygunko/CopyWordsDA that referenced this pull request May 6, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [Sentry.Maui](https://sentry.io/) ([source](https://github.com/getsentry/sentry-dotnet)) | nuget | minor | `6.4.1` -> `6.5.0` |

---

### Release Notes

<details>
<summary>getsentry/sentry-dotnet (Sentry.Maui)</summary>

### [`v6.5.0`](https://github.com/getsentry/sentry-dotnet/blob/HEAD/CHANGELOG.md#650)

[Compare Source](getsentry/sentry-dotnet@6.4.1...6.5.0)

##### Features ✨

-   feat: Add support to send OTEL traces via OTLP by [@&#8203;jamescrosswell](https://github.com/jamescrosswell) in [#&#8203;4899](getsentry/sentry-dotnet#4899)

##### Fixes 🐛

-   fix(unity): update `SentryEvent` to have `IsCaptured` to allow dropping screenshots of filtered events by [@&#8203;JoshuaMoelans](https://github.com/JoshuaMoelans) in [#&#8203;5162](getsentry/sentry-dotnet#5162)
-   fix: Memory leak when filtered Activities get garbage collected before `PruneFilteredSpans` runs by [@&#8203;jamescrosswell](https://github.com/jamescrosswell) in [#&#8203;5186](getsentry/sentry-dotnet#5186)

##### Dependencies ⬆️

##### Deps

-   chore(deps): update Cocoa SDK to v9.12.0 by [@&#8203;github-actions](https://github.com/github-actions) in [#&#8203;5179](getsentry/sentry-dotnet#5179)
-   chore(deps): update CLI to v3.4.1 by [@&#8203;github-actions](https://github.com/github-actions) in [#&#8203;5171](getsentry/sentry-dotnet#5171)
-   chore(deps): update Native SDK to v0.13.8 by [@&#8203;github-actions](https://github.com/github-actions) in [#&#8203;5165](getsentry/sentry-dotnet#5165)
-   chore(deps): update Java SDK to v8.40.0 by [@&#8203;github-actions](https://github.com/github-actions) in [#&#8203;5161](getsentry/sentry-dotnet#5161)
-   chore(deps): update Cocoa SDK to v9.11.0 by [@&#8203;github-actions](https://github.com/github-actions) in [#&#8203;5160](getsentry/sentry-dotnet#5160)
-   chore(deps): update CLI to v3.4.0 by [@&#8203;github-actions](https://github.com/github-actions) in [#&#8203;5145](getsentry/sentry-dotnet#5145)
-   chore(deps): update Java SDK to v8.39.1 by [@&#8203;github-actions](https://github.com/github-actions) in [#&#8203;5144](getsentry/sentry-dotnet#5144)

##### Other

-   perf(logs): avoid string allocation when no parameters are passed by [@&#8203;Flash0ver](https://github.com/Flash0ver) in [#&#8203;4697](getsentry/sentry-dotnet#4697)
-   chore: fix missing skill by [@&#8203;jamescrosswell](https://github.com/jamescrosswell) in [#&#8203;5134](getsentry/sentry-dotnet#5134)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 *...
gunndabad added a commit to DFE-Digital/teaching-record-system that referenced this pull request May 6, 2026
Updated [Sentry.AspNetCore](https://github.com/getsentry/sentry-dotnet)
from 6.4.1 to 6.5.0.

<details>
<summary>Release notes</summary>

_Sourced from [Sentry.AspNetCore's
releases](https://github.com/getsentry/sentry-dotnet/releases)._

## 6.5.0

### Features ✨

- feat: Add support to send OTEL traces via OTLP by @​jamescrosswell in
[#​4899](getsentry/sentry-dotnet#4899)

### Fixes 🐛

- fix(unity): update `SentryEvent` to have `IsCaptured` to allow
dropping screenshots of filtered events by @​JoshuaMoelans in
[#​5162](getsentry/sentry-dotnet#5162)
- fix: Memory leak when filtered Activities get garbage collected before
`PruneFilteredSpans` runs by @​jamescrosswell in
[#​5186](getsentry/sentry-dotnet#5186)

### Dependencies ⬆️

#### Deps

- chore(deps): update Cocoa SDK to v9.12.0 by @​github-actions in
[#​5179](getsentry/sentry-dotnet#5179)
- chore(deps): update CLI to v3.4.1 by @​github-actions in
[#​5171](getsentry/sentry-dotnet#5171)
- chore(deps): update Native SDK to v0.13.8 by @​github-actions in
[#​5165](getsentry/sentry-dotnet#5165)
- chore(deps): update Java SDK to v8.40.0 by @​github-actions in
[#​5161](getsentry/sentry-dotnet#5161)
- chore(deps): update Cocoa SDK to v9.11.0 by @​github-actions in
[#​5160](getsentry/sentry-dotnet#5160)
- chore(deps): update CLI to v3.4.0 by @​github-actions in
[#​5145](getsentry/sentry-dotnet#5145)
- chore(deps): update Java SDK to v8.39.1 by @​github-actions in
[#​5144](getsentry/sentry-dotnet#5144)

### Other

- perf(logs): avoid string allocation when no parameters are passed by
@​Flash0ver in
[#​4697](getsentry/sentry-dotnet#4697)
- chore: fix missing skill by @​jamescrosswell in
[#​5134](getsentry/sentry-dotnet#5134)

Commits viewable in [compare
view](getsentry/sentry-dotnet@6.4.1...6.5.0).
</details>

Updated
[Sentry.Extensions.Logging](https://github.com/getsentry/sentry-dotnet)
from 6.4.1 to 6.5.0.

<details>
<summary>Release notes</summary>

_Sourced from [Sentry.Extensions.Logging's
releases](https://github.com/getsentry/sentry-dotnet/releases)._

## 6.5.0

### Features ✨

- feat: Add support to send OTEL traces via OTLP by @​jamescrosswell in
[#​4899](getsentry/sentry-dotnet#4899)

### Fixes 🐛

- fix(unity): update `SentryEvent` to have `IsCaptured` to allow
dropping screenshots of filtered events by @​JoshuaMoelans in
[#​5162](getsentry/sentry-dotnet#5162)
- fix: Memory leak when filtered Activities get garbage collected before
`PruneFilteredSpans` runs by @​jamescrosswell in
[#​5186](getsentry/sentry-dotnet#5186)

### Dependencies ⬆️

#### Deps

- chore(deps): update Cocoa SDK to v9.12.0 by @​github-actions in
[#​5179](getsentry/sentry-dotnet#5179)
- chore(deps): update CLI to v3.4.1 by @​github-actions in
[#​5171](getsentry/sentry-dotnet#5171)
- chore(deps): update Native SDK to v0.13.8 by @​github-actions in
[#​5165](getsentry/sentry-dotnet#5165)
- chore(deps): update Java SDK to v8.40.0 by @​github-actions in
[#​5161](getsentry/sentry-dotnet#5161)
- chore(deps): update Cocoa SDK to v9.11.0 by @​github-actions in
[#​5160](getsentry/sentry-dotnet#5160)
- chore(deps): update CLI to v3.4.0 by @​github-actions in
[#​5145](getsentry/sentry-dotnet#5145)
- chore(deps): update Java SDK to v8.39.1 by @​github-actions in
[#​5144](getsentry/sentry-dotnet#5144)

### Other

- perf(logs): avoid string allocation when no parameters are passed by
@​Flash0ver in
[#​4697](getsentry/sentry-dotnet#4697)
- chore: fix missing skill by @​jamescrosswell in
[#​5134](getsentry/sentry-dotnet#5134)

Commits viewable in [compare
view](getsentry/sentry-dotnet@6.4.1...6.5.0).
</details>

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Gunn <james@gunn.io>
@ericsampson
Copy link
Copy Markdown
Contributor

@jamescrosswell this is awesome. One thing I haven't figured out yet, what is the intended migration path for customers existing TracesSampler ? In an ideal world the answer is "it's automated respected by the OTel stuff because we do magic for you in our impl", but second best is "here's docs on how to migrate to the intended X pattern yourself". Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OTLP integration

5 participants