diff --git a/docs/platforms/dotnet/guides/aspnetcore/index.mdx b/docs/platforms/dotnet/guides/aspnetcore/index.mdx index 4b33240722ecea..041ce3d9c7184b 100644 --- a/docs/platforms/dotnet/guides/aspnetcore/index.mdx +++ b/docs/platforms/dotnet/guides/aspnetcore/index.mdx @@ -86,7 +86,7 @@ public static IWebHost BuildWebHost(string[] args) => ### Additional configuration -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. +The framework takes configuration settings from `appsettings.json`, environment variables, or from code. These settings get applied to `SentryAspNetCoreOptions`, which extends `SentryHostOptions`, which in turn extends `SentryOptions`. This means options for `Sentry.AspNetCore` as well as all the inner packages are available to be configured through the configuration system. ### appsettings.json diff --git a/docs/platforms/dotnet/guides/extensions-logging/index.mdx b/docs/platforms/dotnet/guides/extensions-logging/index.mdx index 058be82f62cc94..9de5d3a3fae4b8 100644 --- a/docs/platforms/dotnet/guides/extensions-logging/index.mdx +++ b/docs/platforms/dotnet/guides/extensions-logging/index.mdx @@ -20,7 +20,7 @@ The default value to report a log entry as an event to Sentry is `Error`. This means that out of the box, any `LogError` call will create an `Event` which will include breadcrumbs for all prior log messages of level `Information`, `Warning`, `Error` and `Critical`. -Additionally, when enabled, log messages are sent to Sentry as [Structured Logs](logs/). Filtering to control the minimum log level to capture should be done [via `Microsoft.Extensions.Logging` configuration](https://learn.microsoft.com/dotnet/core/extensions/logging/overview?tabs=command-line#how-filtering-rules-are-applied). +Log messages can also be sent to Sentry as [Structured Logs](logs/). This is on by default when you initialize Sentry with `SentrySdk.Init`. With `UseSentry`, set `EnableLogs` to `true`. Filtering to control the minimum log level to capture should be done [via `Microsoft.Extensions.Logging` configuration](https://learn.microsoft.com/dotnet/core/extensions/logging/overview?tabs=command-line#how-filtering-rules-are-applied). ## Install @@ -36,6 +36,8 @@ dotnet add package Sentry.Extensions.Logging -v {{@inject packages.version('sent This package extends `Sentry` main SDK. That means that besides the logging related features, through this package you'll also get access to all API and features available in the main `Sentry` SDK. +Generic host apps install the `Sentry.Extensions.Hosting` package instead, which depends on this one. See [Generic Host](#generic-host). + Messages logged from assemblies with the name starting with `Sentry` will not generate events. @@ -44,103 +46,141 @@ Messages logged from assemblies with the name starting with `Sentry` will not ge ## Configure -There are two ways to add this integration into your project. In both cases it means calling an extension method. The places where it's available are: +How you initialize Sentry depends on how your app starts. -- `ILoggingBuilder` -- `ILoggerFactory` +If you use a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/) or [MAUI](/platforms/dotnet/guides/maui/), skip this setup. Instead, use the `UseSentry` extension for that integration, which will initialize Sentry and the logging integration for you. -The `ILoggingBuilder` extension is useful when using a `WebHostBuilder` or a `HostBuilder`, also known as _Generic host_. This extension method is used by the ASP.NET Core integration under the hood to automatically. +### Generic Host -The extension to `ILoggerFactory` is a convenient way when only the `LoggerFactory` is being used, without any framework integration. +Worker services, Windows services and console apps built on the .NET generic host initialize Sentry with `UseSentry` from the `Sentry.Extensions.Hosting` package: -In both cases the method call is: +```csharp {tabTitle:Host.CreateApplicationBuilder} +using Microsoft.Extensions.Hosting; -**AddSentry()** +var builder = Host.CreateApplicationBuilder(args); +builder.UseSentry(options => options.Dsn = "___PUBLIC_DSN___"); -### Example configuration +await builder.Build().RunAsync(); +``` -#### Through `ILoggingBuilder` +```csharp {tabTitle:Host.CreateDefaultBuilder} +using Microsoft.Extensions.Hosting; -```csharp -public static Task Main() - => new HostBuilder() - .ConfigureHostConfiguration(c => - { - c.SetBasePath(Directory.GetCurrentDirectory()); - c.AddJsonFile("appsettings.json", optional: false); - }) - .ConfigureLogging((c, l) => - { - l.AddConfiguration(c.Configuration); - // Adding Sentry integration to Microsoft.Extensions.Logging - l.AddSentry(); - }) - .Build(); +await Host.CreateDefaultBuilder(args) + .UseSentry(options => options.Dsn = "___PUBLIC_DSN___") + .Build() + .RunAsync(); ``` -In this example, a _generic host_ is being built and the MEL integration with Sentry added through `ConfigureLogging`. The example also demonstrates how to bind the `appsettings.json` configuration to make the values available to the Sentry integration. +`UseSentry` also adds this logging integration, so don't call `AddSentry()` as well. If you do, the call has no effect and its options are ignored. + +It reads SDK options from the `Sentry` section of your configuration, and registers `IHub` and `ISentryClient` so your services can inject them. -With this approach, options like `Dsn`, `SendDefaultPii`, `MinimumBreadcrumbLevel`, to name a few, can be set in `appsettings.json`. +On .NET Framework, `UseSentry` is only available on `IHostBuilder`, which `Host.CreateDefaultBuilder()` returns. Apps there that use `Host.CreateApplicationBuilder()` can switch to `Host.CreateDefaultBuilder()`, or initialize Sentry with `SentrySdk.Init` as shown in [Other Apps](#other-apps). -Example using `appsettings.json`: +### Other Apps +Apps that can't use `UseSentry` initialize Sentry with `SentrySdk.Init`, then add the integration with `AddSentry()`. This includes apps without a host, such as those that create a `LoggerFactory` themselves, and .NET Framework apps on `Host.CreateApplicationBuilder()`: -```json +```csharp {tabTitle:LoggerFactory} +using Microsoft.Extensions.Logging; + +using var sentry = SentrySdk.Init(options => { - "Logging": { - "LogLevel": { - "Default": "Debug", - "Microsoft": "Warning" - } - }, - "Sentry": { - "Dsn": "___PUBLIC_DSN___", - "SendDefaultPii": true, - "MinimumBreadcrumbLevel": "Debug", - "MinimumEventLevel": "Warning", - "MaxBreadcrumbs": 50 - } -} -``` + options.Dsn = "___PUBLIC_DSN___"; +}); -Above we set the application wide minimum log level to `Debug` and we configure a minimum log level for Microsoft specific logs to `Warning`. Sentry specific settings are set under the `Sentry` property. Options are documented below. +using var loggerFactory = LoggerFactory.Create(builder => builder.AddSentry()); +var logger = loggerFactory.CreateLogger(); +``` -#### Through `ILoggerFactory` +```csharp {tabTitle:Host.CreateApplicationBuilder (.NET Framework)} +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +var builder = Host.CreateApplicationBuilder(args); -```csharp -using (var loggerFactory = new LoggerFactory() - .AddConsole(LogLevel.Trace) - .AddSentry(o => o.Dsn = "___PUBLIC_DSN___")) +using var sentry = SentrySdk.Init(options => { - var logger = loggerFactory.CreateLogger(); -} + options.Dsn = "___PUBLIC_DSN___"; +}); + +builder.Logging.AddSentry(); + +await builder.Build().RunAsync(); ``` -This approach doesn't include any of the framework's configuration system. Since the DSN is being provided via parameter, the SDK will be initialized. +Set other [SDK options](/platforms/dotnet/guides/extensions-logging/configuration/options/) in `SentrySdk.Init` too. Disposing the object it returns sends any pending events before your app exits. + +`AddSentry()` doesn't register `IHub`, `ISentryClient` or `Func`. If your services inject them, register them with `HubAdapter.Instance`. Otherwise the host fails to start with `Unable to resolve service for type 'Sentry.IHub'`: -More settings can be passed via the callback configuring the `SentryOptions`. +```csharp +using Sentry.Extensibility; -## Options and Initialization +builder.Services.AddSingleton(HubAdapter.Instance); +builder.Services.AddSingleton(HubAdapter.Instance); +builder.Services.AddSingleton>(() => HubAdapter.Instance); +``` -In cases where `AddSentry` is called without arguments, it's worth noting that an overload exists where `SentryOptions` can be configured just like if `SentrySdk.Init` had been called. +You only need the lines for the types your services inject. - + -The SDK needs to be initialized only once. If the `DSN` is made available to this integration, by default it **will** initialize the SDK. If you do not wish to initialize the SDK via this configuration, set the `InitializeSdk` flag to **false**. Not providing a DSN or leaving it as an _empty string_ will disable the SDK. +Prior to version 7.0.0 `AddSentry` could also initialize the SDK itself, and it registered `IHub` and `ISentryClient`. On those versions, set the DSN in `AddSentry(options => ...)` instead of calling `SentrySdk.Init`. `Sentry.Extensions.Hosting` and its `UseSentry` are new in version 7.0.0. -For example: +### Clearing Logger Providers + +`ClearProviders()` removes every logger provider registered before it, including the ones `UseSentry` adds. Call `UseSentry` after `ClearProviders()`: + +```csharp +builder.Logging.ClearProviders(); +builder.UseSentry(options => options.Dsn = "___PUBLIC_DSN___"); +``` + +If you have to call `ClearProviders()` later, call `AddSentry()` after it to add Sentry's providers back. They use the options from `UseSentry`, so options passed to this `AddSentry()` call are ignored: ```csharp -using (var loggerFactory = new LoggerFactory() - .AddSentry(o => o.InitializeSdk = false)) -{ } +builder.UseSentry(options => options.Dsn = "___PUBLIC_DSN___"); +builder.Logging.ClearProviders(); +builder.Logging.AddSentry(); ``` +Don't add Sentry's providers back if [Serilog](/platforms/dotnet/guides/serilog/), [NLog](/platforms/dotnet/guides/nlog/) or [log4net](/platforms/dotnet/guides/log4net/) already sends your `ILogger` entries to Sentry. Otherwise each entry reaches Sentry twice. + +With `Debug` enabled, the SDK warns when Sentry's providers were removed and nothing added them back. + +### Logging Configuration + +In a generic host app, the integration reads its settings from the `Logging:Sentry` section of your configuration, such as `appsettings.json`. With `UseSentry`, SDK options go in the top-level `Sentry` section: + +```json {filename:appsettings.json} +{ + "Sentry": { + "Dsn": "___PUBLIC_DSN___", + "EnableLogs": true + }, + "Logging": { + "Sentry": { + "LogLevel": { + "Default": "Information" + }, + "MinimumBreadcrumbLevel": "Debug", + "MinimumEventLevel": "Warning" + } + } +} +``` + +`LogLevel` controls which entries are sent as [structured logs](logs/). `MinimumBreadcrumbLevel` and `MinimumEventLevel` are described under [Options](#options). + +The `Logging:Sentry` section only accepts these three keys. Any other key, such as `Dsn` or `EnableLogs`, makes the app fail at startup. Set SDK options in the `Sentry` section if you use `UseSentry`, or in `SentrySdk.Init`. + ### Options +With `UseSentry`, set these in its options. Otherwise, set them in `AddSentry(options => ...)`. You can also set the two levels in configuration. + #### MinimumBreadcrumbLevel A `LogLevel` which indicates the minimum level a log message has to be included as a breadcrumb. By default this value is `Information`. @@ -149,13 +189,29 @@ A `LogLevel` which indicates the minimum level a log message has to be included A `LogLevel` which indicates the minimum level a log message has to be sent to Sentry as an event. By default this value is `Error`. -#### InitializeSdk +#### Log Entry Filters -Whether or not this integration should initialize the SDK. If you intend to call `SentrySdk.Init` yourself, you should set this flag to `false`. +Filters run before a log entry is processed. They get the entry's `Microsoft.Extensions.Logging` data, so you can drop the entry before it becomes a `Breadcrumb` or an `Event`. Return `true` to drop it: -#### Filters +```csharp {tabTitle:UseSentry} +using Sentry.Extensions.Logging; -A list of filters which are invoked before processing log messages. This allows you to inspect the details of the log entry before they become a `Breadcrumb` or an `Event` with full access to the `Microsoft.Extensions.Logging` data. +builder.UseSentry(options => +{ + options.AddLogEntryFilter((category, level, eventId, exception) => + level < LogLevel.Critical && exception is DivideByZeroException); +}); +``` + +```csharp {tabTitle:AddSentry} +using Sentry.Extensions.Logging; + +builder.Logging.AddSentry(options => +{ + options.AddLogEntryFilter((category, level, eventId, exception) => + level < LogLevel.Critical && exception is DivideByZeroException); +}); +``` @@ -167,7 +223,7 @@ These filters only apply to breadcrumbs and events. They don't control which log A list of filters which are invoked before processing any log message to filter out undesired tags. -For example, to remove all tags starting with `PROC_`, add a tag filter to your `SentryOptions` when initializing the SDK. +`TagFilters` is an SDK option, so set it in `UseSentry` or `SentrySdk.Init`. For example, to remove all tags starting with `PROC_`: ```csharp options.TagFilters.Add("PROC_");