Repository navigation
Add a non-logging way to initialise Sentry in generic host apps #5572
Description
Description
Companion to #5245, which removes the ability to initialise the SDK from the logging integrations in v7.
In a generic-host app (Host.CreateApplicationBuilder(), worker services, etc.) the only way to initialise Sentry today is through the Microsoft.Extensions.Logging integration:
var builder = Host.CreateApplicationBuilder();
builder.Logging.AddSentry(dsn); // initialises the SDKThere is no UseSentry() outside ASP.NET Core. That path also gives these users appsettings.json binding for free, because AddSentry registers IOptions<SentryLoggingOptions> and binds the Sentry configuration section.
Once #5245 lands, builder.Logging.AddSentry() only wires up the logger provider. Generic-host users would be left calling SentrySdk.Init and binding configuration into it by hand — a capability removed without a replacement.
Proposal
Add a host-level, non-logging way to initialise Sentry for generic-host apps, e.g. an extension on IHostApplicationBuilder (and possibly IHostBuilder), analogous to UseSentry() for ASP.NET Core:
- initialises the SDK through the existing
ServiceCollectionExtensions.AddSentry<TOptions>plumbing (the same path ASP.NET Core and MAUI use) - binds the
Sentryconfiguration section, soappsettings.jsonkeeps working - registers the logger provider, so that
builder.Logging.AddSentry()is not also needed - sets the Sentry environment from the host environment, as ASP.NET Core, Blazor WebAssembly and Google Cloud Functions do: call
options.SetEnvironment(builder.Environment.EnvironmentName)after the user's configure callback and theSentrysection binding, so an explicitEnvironmentorSENTRY_ENVIRONMENTstill wins (see the comment below). This closes Generic host apps silently report the wrong environment (no IHostEnvironment bridge outside Sentry.AspNetCore) #5468, and docs(dotnet): Document release and environment resolution for SDK 7.0.0 sentry-docs#19960 already documents Generic Host apps this way for 7.0.0
samples/Sentry.Samples.GenericHost is the case to design against.
Also in scope: move the hub plumbing off the logging path
The logging integration currently registers more than logging. LoggingBuilderExtensions.AddSentry calls into ServiceCollectionExtensions.AddSentryHub, which registers:
| Registration | Who needs it | A logging concern? |
|---|---|---|
Func<IHub> |
the IHub factory, SentryHttpMessageHandlerBuilderFilter |
no |
IHub |
the two logging providers, and user code | only indirectly |
ISentryClient |
user code | no |
IHttpMessageHandlerBuilderFilter → SentryHttpMessageHandlerBuilderFilter |
instruments every HttpClientFactory client |
no |
That is a leftover from when the logging integration initialised the SDK. It should belong to whatever initialises Sentry, which is what this issue adds. After that, Logging.AddSentry() should register only its two ILoggerProviders, and those can take HubAdapter.Instance directly — the same "never capture a hub, always dereference the current one" contract that Func<IHub> provides today (see #157), and what SentryLoggerFactoryExtensions already does on the non-DI path.
Why in this issue rather than a follow-up. The removal is only safe once the replacement exists. Removing first leaves generic-host apps with no way to get these services; adding first ships duplicate registrations to clean up later. Doing both here avoids either state, gives one migration story, and makes the release constraint structural: the removal is breaking, so both halves have to land in v7.
It also removes a hazard at the root rather than managing it. Because both paths register Func<IHub> with TryAdd, whichever ran first won, and calling builder.Logging.AddSentry() before UseSentry silently disabled the SDK. #5595 fixed that by making the initializing registration replace any existing accessor; once the logging path registers no accessor at all, nothing competes.
Sequencing and dependencies
- Add regression tests for the multiple-container-build behaviour behind Func<IHub> #5645 should land first. It adds the missing regression tests for the multiple-container-build behaviour behind
Func<IHub>(Failure to capture event: System.ObjectDisposedException: Cannot access a disposed object. #103, fixed by fix: Support multiple container builds #157, never covered by a test). This issue moves exactly that plumbing, so the tests are worth having against today's code rather than against whatever the new code happens to do. - Don't initialise the Sdk from logging integrations #5245 / feat(mel)!: the Microsoft.Extensions.Logging integration no longer initializes the SDK #5595 remove initialisation from the logging integrations, which is what makes
builder.Logging.AddSentry(dsn)— currently the only way to initialise in a generic host — go away. This issue is the replacement, and must ship in the same release.
Open questions
- which package it lives in —
Sentry.Extensions.Loggingdoesn't currently referenceMicrosoft.Extensions.Hosting.Abstractions, so either it takes that dependency or this becomes a newSentry.Extensions.Hostingpackage. Note the same question applies toSentryHostOptions, added in feat(mel)!: the Microsoft.Extensions.Logging integration no longer initializes the SDK #5595, which currently lives inSentry.Extensions.Loggingbecause that is the one package ASP.NET Core, MAUI and Blazor all reference. - naming:
builder.UseSentry()for consistency with ASP.NET Core and MAUI, orbuilder.Services.AddSentry() - what happens to
HttpClientFactoryinstrumentation for logging-only apps. LosingIHubandISentryClientfrom DI is a compile error, so it is loud. LosingSentryHttpMessageHandlerBuilderFilteris not: outgoing-HTTP breadcrumbs and spans would quietly stop for anyone whose only Sentry call isbuilder.Logging.AddSentry(), and there is no tombstone trick for a DI registration that is simply absent. Either accept it as documented v7 behaviour, or keep registering the filter from the logging path even after the hub plumbing moves.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsNo status
Activity
linear-code commentedon Sep 14, 2026
NET-813
XAN9xXx commentedon Sep 14, 2026
Hi, I'd be happy to take this one. Before I start implementing it, do you have a preference on the package question: adding the host-level API to
Sentry.Extensions.Loggingwith aMicrosoft.Extensions.Hosting.Abstractionsdependency, or introducing a separateSentry.Extensions.Hosting package?jamescrosswell commentedon Sep 17, 2026
Hi @XAN9xXx - thank you for offering to contribute again. This particular issue is may require quite a bit of conversation and back and forth though, so I think either @ric-oliv or I will pick this one up.
jamescrosswell commentedon Sep 21, 2026
@ric-oliv there's a bit of background here:
How that relates to this issue...
ASP.NET Core and MAUI have UseSentry( which initialises Sentry and registers
IHub,ISentryClientandSentryOptionswith the ServiceRegistry, so you can inject them... not sure how important that is. More importantly, it hooks up:•
SentryHttpMessageHandlerBuilderFilter, which adds Sentry's handler to everyHttpClientFactoryclient — outbound HTTP breadcrumbs and trace propagation• Configuration binding of options via appsettings.json
Today the only way to get those things in things in a generic host app such as a worker service, or anything built with
Host.CreateApplicationBuilder()is via:However #5595 removes the ability to do that.
The goal of #5572 is to provide a host-level
UseSentry()for generic-host apps to provide the above capabilities.On the plus side, #5595 adds a new
SentryHostOptionsclass that can be used in #5572:Existing building blocks
So the issue is now mostly wiring rather than design.
Packaging
In #5595
SentryHostOptionssits inSentry.Extensions.Loggingwhich ASP.NET Core, MAUI and Blazor all already reference.If we’re going to expose it as a way to initialise Sentry from generic Host applications, it probably needs a new packages since it takes
Microsoft.Extensions.Hosting.Abstractionsas a dependency.Typically we name our packages after the core dependency they take – so that would mean a new
Sentry.Extensions.Hostingpackage whereSentryHostOptionslives... added to.craft.yml, docs, and a first release.Caution
#5595 is the top of a four-PR stack against version7, all still open drafts. Presumably any PR resolving #5572 would also need to stack on top of #5595 then.
jamescrosswell commentedon Oct 6, 2026
Note
There may be some overlap between this issue and:
Might make sense to tackle these at the same time then.
jamescrosswell commentedon Oct 11, 2026
This should also close #5468: generic-host apps should get the same host-environment → Sentry environment bridge that ASP.NET Core has.
#5703 moves that mapping (and
AdjustStandardEnvironmentNameCasing) ontoSentryHostOptions, so once it's merged the generic-hostUseSentryonly needs to call:Call it after the user's configure callback and the
Sentrysection binding, as ASP.NET Core and Blazor WebAssembly do, so that an explicitEnvironmentorSENTRY_ENVIRONMENTstill wins. Add a test likeAddSentryBlazor_NoEnvironmentConfigured_UsesHostEnvironment, and putCloses #5468in the PR.ric-oliv commentedon Oct 12, 2026
Also, something that needs to be considered here:
WebApplicationBuilderimplementsIHostApplicationBuilder, and the Web SDK's implicit usings includeMicrosoft.Extensions.Hosting. If this ends up as aUseSentryonIHostApplicationBuilderin that namespace,builder.UseSentry()will compile in every minimal-hosting ASP.NET Core app. There it would initialize the SDK without the ASP.NET Core integration: noSentryMiddleware, no startup filters, no request tracing.So I think
Sentry.AspNetCoreshould get matchingUseSentryoverloads onWebApplicationBuilder, shipping no later than this one. Overload resolution picks the more specific type. I checked with adotnet new webapp on the .NET 11 RC 1 SDK: with only the interface extension in scope,builder.UseSentry()binds to it, and with both, it binds to theWebApplicationBuilderone.This also removes a trap we have today. The only ASP.NET Core entry point is
builder.WebHost.UseSentry(...), which returnsIWebHostBuilder, so chaining.Build()onto it in a minimal-hosting app gives ASPDEPR008 and CS1929. I hit that during onboarding (#5700 covers the snippets).ric-oliv commentedon Oct 12, 2026
Picking this up. Two things I'd like your view on:
1. New
Sentry.Extensions.Hostingpackage? My lean: yes. Serilog and NLog both split hosting from logging the same way, it matches our name-after-the-dependency convention, and it keepsHosting.Abstractionsout of every MAUI and Blazor WASM app. Cost is the usual new-package plumbing, once. Code is identical either way.2. Make
SentryHostOptionsconcrete and use it as the generic-host options type, instead of a fourth subclass that would only holdEnableLogsand aSetSdkcall.EnableLogsmoves to the base. New in v7, so no API cost.Planned unless you object:
UseSentryonIHostApplicationBuilder(net8+) andIHostBuilder(all TFMs, including netstandard2.0, for parity with v6'sLogging.AddSentry(dsn)). Environment from the host, closes Generic host apps silently report the wrong environment (no IHostEnvironment bridge outside Sentry.AspNetCore) #5468.ApplicationStopped, like ASP.NET Core, so init can't be skipped byClearProviders().Logging.AddSentry()keeps only its providers plus theHttpClientFactoryfilter (both onHubAdapter.Instance), so logging-only apps don't silently lose outgoing-HTTP spans.WebApplicationBuilderoverloads first, then generic-hostUseSentry, then the logging-path change.jamescrosswell commentedon Oct 12, 2026
Yes - I think so
I'd keep it abstract and add a
SentryGenericHostOptions.options is SentryHostOptionsstays meaning "any host integration", andis SentryGenericHostOptionscan identify the generic host specifically.One gap in the
WebApplicationBuilderoverload approach: Aspire's ServiceDefaults usesAddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder, and abuilder.UseSentry()in there would bind to the generic overload even in a web app. So it might be worth having the genericUseSentrydetect that case at runtime and warn/log... otherwise everything appears to run fine but folks don't get all the functionality that they might [expect].jamescrosswell commentedon Oct 13, 2026
Worth asking which of those delivers concrete value to SDK users (and so which deserves a changelog)... If it's just a way to incrementally deliver one thing in 3 technical increments, we could have three PRs... each targeting the prior - just to make review easier - but squash merge them all down into the version7 branch when we approve/merge.
ric-oliv commentedon Oct 13, 2026
Thanks! Agreed on both new package, and
SentryGenericHostOptionson top of the abstract base.About Aspire, good point. We can make it so the generic overload detects a
WebApplicationBuilderand logs a warning through the host logger at startup; the docs will show theis WebApplicationBuilderbranch for ServiceDefaults.PRs: each of the three is user-visible on its own, so each gets its own changelog line: the
WebApplicationBuilderoverloads (feature), the new package (feature), and the logging-path change (breaking, with a migration note). Stacked for review, each squash-merged into version7.ric-oliv commentedon Oct 13, 2026
Update on the PR plan: the
WebApplicationBuilderoverloads moved to their own issue, #5719. They don't depend on anything in v7, so that PR targetsmainand ships in 6.x, andversion7picks it up with the next merge ofmain. The generic-hostUseSentryand the logging-path change stay onversion7as planned, after that merge.ric-oliv commentedon Oct 13, 2026
Two PRs came out of this work. They don't depend on anything in v7, so they were split off and go straight to
main:UseSentryoverloads onWebApplicationBuilder(Add UseSentry overloads on WebApplicationBuilder #5719).Both reach
version7with the next merge ofmain.feat(hosting): add an empty Sentry.Extensions.Hosting package
feat(hosting): add an empty Sentry.Extensions.Hosting package
feat: add Sentry.Extensions.Hosting with UseSentry for generic host a…
ric-oliv commentedon Oct 20, 2026
Merged, will be released with 7.0.
Thanks @jamescrosswell for all the prep work and onboarding here, and also @XAN9xXx for offering to implement it!