Skip to content

Add a non-logging way to initialise Sentry in generic host apps #5572

Closed

Description

@jamescrosswell

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 SDK

There 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:

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

Open questions

  • which package it lives in — Sentry.Extensions.Logging doesn't currently reference Microsoft.Extensions.Hosting.Abstractions, so either it takes that dependency or this becomes a new Sentry.Extensions.Hosting package. Note the same question applies to SentryHostOptions, added in feat(mel)!: the Microsoft.Extensions.Logging integration no longer initializes the SDK #5595, which currently lives in Sentry.Extensions.Logging because that is the one package ASP.NET Core, MAUI and Blazor all reference.
  • naming: builder.UseSentry() for consistency with ASP.NET Core and MAUI, or builder.Services.AddSentry()
  • what happens to HttpClientFactory instrumentation for logging-only apps. Losing IHub and ISentryClient from DI is a compile error, so it is loud. Losing SentryHttpMessageHandlerBuilderFilter is not: outgoing-HTTP breadcrumbs and spans would quietly stop for anyone whose only Sentry call is builder.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.

Activity

  1. added
    FeatureNew feature or request
    .NETPull requests that update .net code
    Next MajorChanges scheduled for the next Major release.
    on Sep 14, 2026
  2. linear-code commented on Sep 14, 2026

    @linear-code
  3. added this to the 7.0.0 milestone on Sep 14, 2026
  4. XAN9xXx commented on Sep 14, 2026

    @XAN9xXx
    Contributor

    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.Logging with a Microsoft.Extensions.Hosting.Abstractions dependency, or introducing a separate Sentry.Extensions.Hosting package?

  5. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Sep 14, 2026
  6. jamescrosswell commented on Sep 17, 2026

    @jamescrosswell
    CollaboratorAuthor

    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.Logging with a Microsoft.Extensions.Hosting.Abstractions dependency, or introducing a separate Sentry.Extensions.Hosting package?

    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.

  7. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Sep 17, 2026
  8. jamescrosswell commented on Sep 21, 2026

    @jamescrosswell
    CollaboratorAuthor

    @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, ISentryClient and SentryOptions with 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 every HttpClientFactory client — 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:

    builder.Logging.AddSentry(dsn);

    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 SentryHostOptions class that can be used in #5572:

    Image

    Existing building blocks

    • `SentryHostOptions` - abstract base type for some new `SentryGenericHostOptions` class
    • `ServiceCollectionExtensions.AddSentry<TOptions>()` - registers the plumbing and initialises Sentry the first time the hub is resolved. No need to call `SentrySdk.Init`.
    • `SentryHostOptionsSetup<TOptions>` - binds the Sentry section of `appsettings.json` onto those options. 
    • `WebAssemblyHostBuilderExtensions.UseSentry` is about 20 lines  that is pretty close to what we’d need for a generic host extension. #5572 would be the same pattern against `IHostApplicationBuilder`.
    

    So the issue is now mostly wiring rather than design.

    Packaging

    In #5595 SentryHostOptions sits in Sentry.Extensions.Logging which 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.Abstractions as a dependency.

    Typically we name our packages after the core dependency they take – so that would mean a new Sentry.Extensions.Hosting package where SentryHostOptions lives... 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.

  9. jamescrosswell commented on Oct 6, 2026

    @jamescrosswell
    CollaboratorAuthor

    Note

    There may be some overlap between this issue and:

    Might make sense to tackle these at the same time then.

  10. jamescrosswell commented on Oct 11, 2026

    @jamescrosswell
    CollaboratorAuthor

    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) onto SentryHostOptions, so once it's merged the generic-host UseSentry only needs to call:

    options.SetEnvironment(builder.Environment.EnvironmentName);

    Call it after the user's configure callback and the Sentry section binding, as ASP.NET Core and Blazor WebAssembly do, so that an explicit Environment or SENTRY_ENVIRONMENT still wins. Add a test like AddSentryBlazor_NoEnvironmentConfigured_UsesHostEnvironment, and put Closes #5468 in the PR.

  11. ric-oliv commented on Oct 12, 2026

    @ric-oliv
    Member

    Also, something that needs to be considered here: WebApplicationBuilder implements IHostApplicationBuilder, and the Web SDK's implicit usings include Microsoft.Extensions.Hosting. If this ends up as a UseSentry on IHostApplicationBuilder in 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: no SentryMiddleware, no startup filters, no request tracing.

    So I think Sentry.AspNetCore should get matching UseSentry overloads on WebApplicationBuilder, shipping no later than this one. Overload resolution picks the more specific type. I checked with a dotnet new web app 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 the WebApplicationBuilder one.

    This also removes a trap we have today. The only ASP.NET Core entry point is builder.WebHost.UseSentry(...), which returns IWebHostBuilder, so chaining .Build() onto it in a minimal-hosting app gives ASPDEPR008 and CS1929. I hit that during onboarding (#5700 covers the snippets).

  12. ric-oliv commented on Oct 12, 2026

    @ric-oliv
    Member

    Picking this up. Two things I'd like your view on:

    1. New Sentry.Extensions.Hosting package? My lean: yes. Serilog and NLog both split hosting from logging the same way, it matches our name-after-the-dependency convention, and it keeps Hosting.Abstractions out of every MAUI and Blazor WASM app. Cost is the usual new-package plumbing, once. Code is identical either way.

    2. Make SentryHostOptions concrete and use it as the generic-host options type, instead of a fourth subclass that would only hold EnableLogs and a SetSdk call. EnableLogs moves to the base. New in v7, so no API cost.

    Planned unless you object:

    • UseSentry on IHostApplicationBuilder (net8+) and IHostBuilder (all TFMs, including netstandard2.0, for parity with v6's Logging.AddSentry(dsn)). Environment from the host, closes Generic host apps silently report the wrong environment (no IHostEnvironment bridge outside Sentry.AspNetCore) #5468.
    • A small hosted service initializes on start and closes on ApplicationStopped, like ASP.NET Core, so init can't be skipped by ClearProviders().
    • Logging.AddSentry() keeps only its providers plus the HttpClientFactory filter (both on HubAdapter.Instance), so logging-only apps don't silently lose outgoing-HTTP spans.
    • Three PRs on version7: WebApplicationBuilder overloads first, then generic-host UseSentry, then the logging-path change.
  13. jamescrosswell commented on Oct 12, 2026

    @jamescrosswell
    CollaboratorAuthor

    New Sentry.Extensions.Hosting package?

    Yes - I think so

    Make SentryHostOptions concrete

    I'd keep it abstract and add a SentryGenericHostOptions.

    • Abstract → concrete is non-breaking later; concrete → abstract isn't. If we ever need a generic-host-only option, a concrete base means it'd leak onto the ASP.NET Core/MAUI/Blazor options
    • options is SentryHostOptions stays meaning "any host integration", and is SentryGenericHostOptions can identify the generic host specifically.
    • It matches the one-options-type-per-integration pattern everywhere else.

    One gap in the WebApplicationBuilder overload approach: Aspire's ServiceDefaults uses AddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder, and a builder.UseSentry() in there would bind to the generic overload even in a web app. So it might be worth having the generic UseSentry detect 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].

  14. jamescrosswell commented on Oct 13, 2026

    @jamescrosswell
    CollaboratorAuthor
    • Three PRs on version7: WebApplicationBuilder overloads first, then generic-host UseSentry, then the logging-path change.

    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.

  15. self-assigned this
    on Oct 13, 2026
  16. ric-oliv commented on Oct 13, 2026

    @ric-oliv
    Member

    Thanks! Agreed on both new package, and SentryGenericHostOptions on top of the abstract base.

    About Aspire, good point. We can make it so the generic overload detects a WebApplicationBuilder and logs a warning through the host logger at startup; the docs will show the is WebApplicationBuilder branch for ServiceDefaults.

    PRs: each of the three is user-visible on its own, so each gets its own changelog line: the WebApplicationBuilder overloads (feature), the new package (feature), and the logging-path change (breaking, with a migration note). Stacked for review, each squash-merged into version7.

  17. ric-oliv commented on Oct 13, 2026

    @ric-oliv
    Member

    Update on the PR plan: the WebApplicationBuilder overloads moved to their own issue, #5719. They don't depend on anything in v7, so that PR targets main and ships in 6.x, and version7 picks it up with the next merge of main. The generic-host UseSentry and the logging-path change stay on version7 as planned, after that merge.

  18. ric-oliv commented on Oct 13, 2026

    @ric-oliv
    Member

    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:

    Both reach version7 with the next merge of main.

  19. ric-oliv commented on Oct 20, 2026

    @ric-oliv
    Member

    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!

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

Metadata

Metadata

Assignees

Labels

.NETPull requests that update .net codeFeatureNew feature or requestNext MajorChanges scheduled for the next Major release.

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions