ASP.NET Core

Sentry provides an integration with ASP.NET Core through the Sentry.AspNetCore NuGet package.

  • Single line ASP.NET Core integration: UseSentry
  • Capture unhandled exceptions and exceptions with custom exception handlers
  • Capture LogError or LogCritical
  • Any event sent will include relevant application log messages
  • Automatically capture request info, browser details, ServerOS and Runtime info, release information etc.
  • Capture request headers and, if you opt in, request payload
  • Support for EventProcessors and ExceptionProcessors (registered via Dependency Injection)
  • HTTP Proxy configuration
  • Event flooding protection (429 retry-after and internal bound queue)
  • Tested on Windows, macOS, Linux, .NET Core, .NET Framework and Mono

Add the Sentry dependency:

Copied
Install-Package Sentry.AspNetCore -Version 4.4.0

This package extends Sentry.Extensions.Logging. This means that besides the ASP.NET Core related features, through this package you'll also get access to all the framework's logging integration and also the features available in the main Sentry SDK.

The simplest way to initialize Sentry in ASP.NET Core is by using the UseSentry extension method from the Sentry.AspNetCore package in conjunction with the framework configuration system.

When configuring the SDK via the frameworks configuration system, it's possible to add the SDK by simply calling UseSentry without providing any further information:

Copied
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseSentry(); // Initialize Sentry

Copied
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            // Add the following line:
            webBuilder.UseSentry();
        });

Copied
public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        // Add the following line:
        .UseSentry()

The framework takes configuration settings from appsettings.json, environment variables, or from code. These settings get applied to Sentry.AspNetCore.SentryAspNetCoreOptions, which extends Sentry.Extensions.Logging.SentryLoggingOptions, which in turn extends Sentry.SentryOptions. This means options for Sentry.AspNetCore as well as all the inner packages are available to be configured through the configuration system.

An example of some of the options that can be configured via appsettings.json:

appsettings.json
Copied
  "Sentry": {
    "Dsn": "https://examplePublicKey@o0.ingest.sentry.io/0",
    "SendDefaultPii": true,
    "MaxRequestBodySize": "Always",
    "MinimumBreadcrumbLevel": "Debug",
    "MinimumEventLevel": "Warning",
    "AttachStackTrace": true,
    "Debug": true,
    "DiagnosticLevel": "Error",
    "TracesSampleRate": 1.0
  },

Setting TracesSampleRate to 1.0 in this example configures Sentry to capture 100% of transactions for performance monitoring. We recommend adjusting this value in production. See Automatic Instrumentation for further information.

It's also possible to bind properties to the SDK via environment variables, like:

Copied
set Sentry__Debug=true

ASP.NET Core will automatically read this environment variable and bind it to the SDK configuration object.

Finally, any settings that can be configured via appsettings.json or environment variables can also be configured via code. Some settings can only be configured in code, such as the BeforeSend callback:

Copied
.UseSentry(options =>
{
    options.TracesSampleRate = 1.0; // <- Set this to configure automatic tracing
    options.SetBeforeSend((@event, hint) =>
    {
        // Never report server names
        @event.ServerName = null;
        return @event;
    });
})

Example modifying all events before they are sent to avoid server names being reported.

Much of the behavior of the ASP.NET Core integration with Sentry can be customized by using the frameworks dependency injection system. That is done by registering your own implementation of some of the exposed abstraction.

The lifetime used will be respected by the SDK. For example, when registering a Transient dependency, a new instance of the processor is created for each event sent out to Sentry. This allows the use of non thread-safe event processors.

When opting-in to SendDefaultPii, the SDK will automatically read the user from the request by inspecting HttpContext.User. Default claim values like NameIdentifier for the Id will be used.

If you wish to change the behavior of how to read the user from the request, you can register a new IUserFactory into the container:

Copied
public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IUserFactory, MyUserFactory>();
}

Event processors and exception processors can be added via DI:

Copied
public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ISentryEventProcessor, MyEventProcessor>();
    services.AddScoped<ISentryEventExceptionProcessor, MyExceptionProcessor>();
}

As previously mentioned, this package is a wrapper around Sentry.Extensions.Logging and Sentry. Please refer to the documentation of these packages to get the options that are defined at those levels.

Below, the options that are specific to Sentry.AspNetCore will be described.

Although this setting is part of the Sentry package, in the context of ASP.NET Core, it means reporting the user by reading the frameworks HttpContext.User. The strategy to create the SentryUser can be customized. Please read retrieving user info for more.

The environment name is automatically populated by reading the frameworks IHostingEnvironment value.

This option is part of the Sentry package. The value of IHostingEnvironment will only be used if no other method was used.

Methods that take precedence over IHostingEnvironment are:

  • Programmatically: options.Environment
  • Environment variable SENTRY_ENVIRONMENT
  • Configuration system like appsettings.json

This parameter controls whether integrations should capture HTTP request bodies. It can be set to one of the following values:

  • None: Request bodies are never sent.
  • Small: Only small request bodies will be captured. The cutoff for small depends on the SDK (typically 4KB).
  • Medium: Medium and small requests will be captured (typically 10KB).
  • Always: The SDK will always capture the request body as long as Sentry can make sense of it.

If the request bodies should be captured, all requests will have the EnableRewind method invoked. This is done so that the request data can be read later, in case an error happens while processing the request.

When set to true, the SDK will detect blocking calls in async methods (like Task.Wait() and Task.Result) and report these to Sentry as errors. Blocking calls can lead to Threadpool starvation.

Check out the MVC Sample for an example of how to use this feature.

In that sample you can also see an example of how to suppress blocking detection for specific code blocks.

This feature makes use of the Ben.BlockingDetector library and so has the same caveats:

  1. For async methods with occurrences of .ConfigureAwait(false), detection won't alert for blocking Monitor calls after occurrences in the case where the returned Task wasn't already completed
  2. Won't alert for blocking calls that don't block, like on precompleted Tasks (such as a single small Body.Write)
  3. Won't alert for blocking that happens in syscalls (like File.Read(...) and Thread.Sleep)

It will detect CLR-initiated waits lock, ManualResetEventSlim, Semaphore\{Slim\}, Task.Wait, Task.Result etc. if they do block.

Opt-in to capture values from System.Diagnostic.Activity if one exists.

  • A simple example without MVC. (C#)
  • An example using MVC and most of the SDK features. (C#)
  • An example using Giraffe on top of ASP.NET Core with a basic overview of available features. (F#)
  • For more samples of the .NET SDKs.

If events are being logged to Sentry from the client-side, then you should use a tunnel.

A tunnel is an HTTP endpoint that acts as a proxy between Sentry and your application. Because you control this server, there is no risk of any requests sent to it being blocked.

  • Add to the container by calling AddSentryTunneling(); on IServiceCollection.
  • Add the web app by calling UseSentryTunneling(); on IApplicationBuilder.
  • In the client-side JavaScript configuration, ensure the tunnel option is used:
Copied
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  tunnel: "/tunnel",
});

The AspNetCore.Mvc sample uses this approach.

Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").