Skip to content

Generic host apps silently report the wrong environment (no IHostEnvironment bridge outside Sentry.AspNetCore) #5468

Description

@jamescrosswell

Problem Statement

Sentry.AspNetCore bridges the .NET hosting environment to the Sentry environment automatically, via SentryAspNetCoreOptions.SetEnvironment(IWebHostEnvironment). Nothing else does.

Grepping the repo, no source file outside Sentry.AspNetCore references IHostEnvironment at all. AddSentry exists on ILoggingBuilder, ILoggerFactory, IServiceCollection, TracerProviderBuilder and IChatClient; none of them look at the host environment. So for a Worker Service, a console app, or anything else on the generic host, the only thing the SDK can resolve is SENTRY_ENVIRONMENT, because that's all SettingLocator.GetEnvironment reads.

The result is a silent misreport. Setting DOTNET_ENVIRONMENT — the documented way to tell a generic host where it's running — has no effect on Sentry, and events land in production while the host says Staging. Nothing warns, and the value looks plausible, so it tends to be discovered long after the fact.

Reproduction

Generic host, logging.AddSentry, no explicit options.Environment:

var host = Host.CreateDefaultBuilder(args)
    .ConfigureLogging((context, logging) =>
    {
        logging.ClearProviders();
        logging.AddSentry(options =>
        {
            options.Dsn = "...";
            options.SetBeforeSend((e, _) =>
            {
                Console.WriteLine($"HostingEnvironment = {context.HostingEnvironment.EnvironmentName}");
                Console.WriteLine($"event.Environment  = {e.Environment}");
                return null;
            });
        });
    })
    .Build();

host.Services.GetRequiredService<ILogger<Program>>().LogError("probe");
DOTNET_ENVIRONMENT SENTRY_ENVIRONMENT HostingEnvironment event.Environment
(unset) staging Production staging
Staging (unset) Staging production
Staging preview Staging preview

Row 2 is the problem. Verified against 6.4.1 on .NET 10.

Why it's easy to get wrong

The asymmetry isn't visible from the calling code. Both surfaces are configured the same way, so an app with an ASP.NET Core API and a generic-host worker reporting to the same project will have the API tag events staging while the worker tags them production — from what looks like identical setup. Cross-surface filtering then quietly excludes half the system.

It's also not obvious that Sentry.Extensions.Logging would be the wrong place to look for hosting behaviour. It's the package a worker app references, but it's a logging integration, so it has no hosting concepts — the bridge lives in a package such an app has no reason to reference.

Solution Brainstorm

A few options:

  1. A generic-host integrationSentry.Extensions.Hosting, or an IHostBuilder.UseSentry() overload, applying the same SetEnvironment logic (including AdjustStandardEnvironmentNameCasing) that Sentry.AspNetCore does. Most complete, and it gives generic-host apps a natural home for other host-aware defaults later.

  2. Diagnostics only — if IHostEnvironment is resolvable and disagrees with the resolved Sentry environment, log a warning at init. Cheap, doesn't change behaviour, and would have turned a silent misreport into something discoverable.

  3. Docs — the .NET options docs note that the ASP.NET Core integration surfaces staging/development, but don't say that non-ASP.NET Core apps get no host inference at all. Worth stating explicitly whatever else is done.

Context

Found while instrumenting mentaldesk/truman (ASP.NET Core API + generic-host batch worker + Svelte frontend). The JobRunner worker needed hand-written mapping to reproduce what the API gets for free.

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETPull requests that update .net codeFeatureNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions