From 3b34ee349b74f99267ff906432bdc8bdd623832f Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 13 Oct 2026 13:34:58 +1300 Subject: [PATCH 01/11] docs(dotnet): Update logging docs for SDK 7.0.0 In sentry-dotnet 7.0.0, SentryOptions.EnableLogs and EnableMetrics are removed, and the Serilog, NLog, log4net and Microsoft.Extensions.Logging integrations no longer initialize the SDK. Initialize Sentry with SentrySdk.Init or a host integration first, then add the integration. Serilog, NLog and log4net send logs without a switch; EnableLogs stays only on the ASP.NET Core, MAUI and Blazor WebAssembly options. Co-Authored-By: Claude Opus 5.5 --- .../guides/azure-functions-worker/index.mdx | 33 +++--- .../guides/blazor-webassembly/index.mdx | 8 +- .../platforms/dotnet/guides/log4net/index.mdx | 29 +++-- .../advanced-configuration-example.mdx | 63 +++++------ docs/platforms/dotnet/guides/nlog/index.mdx | 87 +++++---------- .../platforms/dotnet/guides/serilog/index.mdx | 52 ++++----- .../config-intro/dotnet.nlog.mdx | 87 --------------- .../enriching-events/set-tag/dotnet.nlog.mdx | 2 +- .../enriching-events/set-user/dotnet.nlog.mdx | 6 +- platform-includes/logs/options/dotnet.mdx | 30 ++--- platform-includes/logs/setup/dotnet.mdx | 103 +++++++++++------- platform-includes/logs/usage/dotnet.mdx | 8 +- platform-includes/metrics/options/dotnet.mdx | 2 +- .../set-environment/dotnet.nlog.mdx | 40 ------- platform-includes/set-release/dotnet.nlog.mdx | 46 -------- 15 files changed, 188 insertions(+), 408 deletions(-) delete mode 100644 platform-includes/configuration/config-intro/dotnet.nlog.mdx delete mode 100644 platform-includes/set-environment/dotnet.nlog.mdx delete mode 100644 platform-includes/set-release/dotnet.nlog.mdx diff --git a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx index b70a17997070fb..02e8ed59799a97 100644 --- a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx +++ b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx @@ -40,7 +40,7 @@ The [Sentry.Extensions.Logging](/platforms/dotnet/guides/extensions-logging/) pa ## Configure -The core features of Sentry are enabled by calling `AddSentry` when configuring logging. +Initialize Sentry with `SentrySdk.Init`, then call `AddSentry` when configuring logging to capture log messages. Performance tracing can be enabled by adding Sentry to the OpenTelemetry `TracerProviderBuilder` and then configuring Sentry itself to use OpenTelemetry. @@ -57,6 +57,17 @@ using OpenTelemetry.Trace; // ___PRODUCT_OPTION_END___ using Sentry.OpenTelemetry; +SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; + // ___PRODUCT_OPTION_START___ performance + options.TracesSampleRate = 1.0; + options.UseOpenTelemetry(); // <-- Configure Sentry to use open telemetry + options.DisableSentryHttpMessageHandler = true; // So Sentry doesn't also create spans for outbound HTTP requests + // ___PRODUCT_OPTION_END___ + options.Debug = true; +}); + var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() // ___PRODUCT_OPTION_START___ performance @@ -70,25 +81,19 @@ var host = new HostBuilder() }); }) // ___PRODUCT_OPTION_END___ - .ConfigureLogging(logging => - { - logging.AddSentry(options => - { - options.Dsn = "___PUBLIC_DSN___"; - // ___PRODUCT_OPTION_START___ performance - options.TracesSampleRate = 1.0; - options.UseOpenTelemetry(); // <-- Configure Sentry to use open telemetry - options.DisableSentryHttpMessageHandler = true; // So Sentry doesn't also create spans for outbound HTTP requests - // ___PRODUCT_OPTION_END___ - options.Debug = true; - }); - }) + .ConfigureLogging(logging => logging.AddSentry()) .Build(); await host.RunAsync(); ``` + + +Before version 7.0.0, `AddSentry` initializes the SDK itself. Pass the options to `logging.AddSentry(options => ...)` instead of calling `SentrySdk.Init`. + + + ## Verify This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. diff --git a/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx b/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx index 5b784b93f6c633..4c86369fc00c24 100644 --- a/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx +++ b/docs/platforms/dotnet/guides/blazor-webassembly/index.mdx @@ -24,13 +24,10 @@ This package extends [Sentry.Extensions.Logging](/platforms/dotnet/guides/extens ## Configure -Sentry integration with Blazor WebAssembly is done by calling `.UseSentry()` and specifying the options, for example: - - +Sentry integration with Blazor WebAssembly is done by calling `.UseSentry()` and specifying the options. `UseSentry` also adds Sentry's `ILogger` integration, which captures `LogError` and higher as events. For example: ```csharp using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using Microsoft.Extensions.Logging; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.UseSentry(options => @@ -45,9 +42,6 @@ builder.UseSentry(options => // ___PRODUCT_OPTION_END___ performance }); -// Captures logError and higher as events -builder.Logging.AddSentry(o => o.InitializeSdk = false); - await builder.Build().RunAsync(); ``` diff --git a/docs/platforms/dotnet/guides/log4net/index.mdx b/docs/platforms/dotnet/guides/log4net/index.mdx index 99c61499a86b4f..54408d8d04159a 100644 --- a/docs/platforms/dotnet/guides/log4net/index.mdx +++ b/docs/platforms/dotnet/guides/log4net/index.mdx @@ -7,9 +7,9 @@ og_image: /og-images/platforms-dotnet-guides-log4net.gif Sentry provides an integration with log4net through the [Sentry.Log4Net NuGet package](https://www.nuget.org/packages/Sentry.Log4Net). -Without any code change, this package is able to initialize the Sentry SDK and capture events while including additional properties like `Exception` data and more. +The `SentryAppender` captures log events as Sentry events and breadcrumbs, including additional properties like `Exception` data and more. -Additionally, when enabled, log messages are sent to Sentry as [Structured Logs](logs/). +Log messages are also sent to Sentry as [Structured Logs](logs/). ## Install @@ -27,36 +27,35 @@ This package extends `Sentry` main SDK. That means besides the log4net `Appender ## Configure -Once the log4net integration package is installed in your project, you can modify your configuration file to add the appender. +The appender doesn't initialize the SDK. Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/): + +```csharp +SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; +}); +``` + +Then add the appender to your log4net configuration. This can be done, for example, via the `app.config` for console and desktop apps or `web.config` in case of ASP.NET. ```xml {filename:app.config} - ``` - - -Only a subset of the options are exposed via the log4net appender configuration. If you wish to access an [SDK option](/platforms/dotnet/configuration/options/) which is not listed below, you'll need to initialize the SDK via [SentrySdk.Init](/platforms/dotnet/) instead of doing it via this integration as described below. +Other [SDK options](/platforms/dotnet/guides/log4net/configuration/options/) also go in `SentrySdk.Init`. - +The appender drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the appender also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. ### SendIdentity In the example above, the `SendIdentity` flag was switched on. The SDK then will take the log4net `Identity` value and report to Sentry as the user's id. -### DSN - -Also in the example above, you can find the DSN being set. That will instruct the `SentryAppender` to initialize the SDK. - -This is only one of the ways to initialize the SDK. If you wish to configure the SDK programmatically, you could **leave the DSN out** from the appender configuration section. The SDK needs to be initialized only **once** and since other integrations (like ASP.NET) are also able to initialize the SDK, you only need to pass the DSN to one of these integrations. -One common case to not add the DSN to the XML configuration file (which would initialize it via the log4net integration) is to have full access to the [SDK option](/platforms/dotnet/guides/log4net/configuration/options/). - ## Verify This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. diff --git a/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx b/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx index 4d0fe3d5432780..e71c57206fcc9b 100644 --- a/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx +++ b/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx @@ -10,7 +10,32 @@ For more information on how to dynamically set event data via `NLog.config`, see -The SDK can be configured via `NLog.config` XML file: +The Sentry target doesn't initialize the SDK, so initialize Sentry in code first. SDK options, such as the environment and release, go here: + +```csharp +SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; + options.Environment = "Development"; + options.Release = "my-project-name@2.3.12"; + options.AttachStacktrace = true; + options.SendDefaultPii = true; // Send Personal Identifiable information like the username of the user logged in to the device + options.ShutdownTimeout = TimeSpan.FromSeconds(5); +}); +``` + +```fsharp +SentrySdk.Init(fun options -> + options.Dsn <- "___PUBLIC_DSN___" + options.Environment <- "Development" + options.Release <- "my-project-name@2.3.12" + options.AttachStacktrace <- true + options.SendDefaultPii <- true // Send Personal Identifiable information like the username of the user logged in to the device + options.ShutdownTimeout <- TimeSpan.FromSeconds 5.0) +|> ignore +``` + +Then configure the Sentry target in an `NLog.config` XML file: ```xml {tabTitle:NLog.config} @@ -26,29 +51,15 @@ The SDK can be configured via `NLog.config` XML file: - - - - true - - ``` -Or the SDK can be configured via code: +Or configure the target in code: ```csharp -// Other overloads exist, for example, configure the SDK with only the DSN or no parameters at all. LogManager.Configuration.AddSentry(o => { o.Layout = "${message}"; @@ -89,15 +99,7 @@ LogManager.Configuration.AddSentry(o => o.MinimumBreadcrumbLevel = LogLevel.Debug; // Debug and higher are stored as breadcrumbs (default is Info) o.MinimumEventLevel = LogLevel.Error; // Error and higher is sent as event (default is Error) - // If DSN is not set, the SDK will look for an environment variable called SENTRY_DSN. If - // nothing is found, SDK is disabled. - o.Dsn = DsnSample; - - o.AttachStacktrace = true; - o.SendDefaultPii = true; // Send Personal Identifiable information like the username of the user logged in to the device - o.IncludeEventDataOnBreadcrumbs = true; // Optionally include event properties with breadcrumbs - o.ShutdownTimeoutSeconds = 5; //Optionally specify user properties via NLog (here using MappedDiagnosticsLogicalContext as an example) o.User = new SentryNLogUser @@ -119,7 +121,6 @@ LogManager.Configuration.AddSentry(o => ``` ```fsharp -// Other overloads exist, for example, configure the SDK with only the DSN or no parameters at all. LogManager.Configuration.AddSentry( fun o -> o.Layout <- "${message}" @@ -128,15 +129,7 @@ LogManager.Configuration.AddSentry( o.MinimumBreadcrumbLevel <- LogLevel.Debug // Debug and higher are stored as breadcrumbs (default is Info) o.MinimumEventLevel <- LogLevel.Error // Error and higher is sent as event (default is Error) - // If DSN is not set, the SDK will look for an environment variable called SENTRY_DSN. If - // nothing is found, SDK is disabled. - o.Dsn <- DsnSample - - o.AttachStacktrace <- true - o.SendDefaultPii <- true // Send Personal Identifiable information like the username of the user logged in to the device - o.IncludeEventDataOnBreadcrumbs <- true // Optionally include event properties with breadcrumbs - o.ShutdownTimeoutSeconds <- 5 //Optionally specify user properties via NLog (here using MappedDiagnosticsLogicalContext as an example) o.User <- diff --git a/docs/platforms/dotnet/guides/nlog/index.mdx b/docs/platforms/dotnet/guides/nlog/index.mdx index facf08751b2a79..f9a6efff1bfc11 100644 --- a/docs/platforms/dotnet/guides/nlog/index.mdx +++ b/docs/platforms/dotnet/guides/nlog/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 `Error` call will create an `Event` which will include all log messages of level `Info`, `Warn` and also `Error` and `Critical`. -Additionally, when enabled, log messages are sent to Sentry as [Structured Logs](logs/). +Log messages are also sent to Sentry as [Structured Logs](logs/). ## Install @@ -50,55 +50,40 @@ For more information on how to dynamically set event data via `NLog.config`, see -You can configure the Sentry NLog target via code as follows: +The Sentry target doesn't initialize the SDK. Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/), then add the target. You can add it in code: ```csharp -LogManager.Configuration = new LoggingConfiguration(); -LogManager.Configuration - .AddSentry(options => - { - // Optionally specify a separate format for message - options.Layout = "${message}"; - // Optionally specify a separate format for breadcrumbs - options.BreadcrumbLayout = "${logger}: ${message}"; - - // Debug and higher are stored as breadcrumbs (default is Info) - options.MinimumBreadcrumbLevel = LogLevel.Debug; - // Error and higher is sent as event (default is Error) - options.MinimumEventLevel = LogLevel.Error; - - // Send the logger name as a tag - options.AddTag("logger", "${logger}"); - - // All Sentry Options are accessible here. - }); +SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; +}); + +var config = new LoggingConfiguration(); +config.AddSentry(options => +{ + // Optionally specify a separate format for message + options.Layout = "${message}"; + // Optionally specify a separate format for breadcrumbs + options.BreadcrumbLayout = "${logger}: ${message}"; + + // Debug and higher are stored as breadcrumbs (default is Info) + options.MinimumBreadcrumbLevel = LogLevel.Debug; + // Error and higher is sent as event (default is Error) + options.MinimumEventLevel = LogLevel.Error; + + // Send the logger name as a tag + options.AddTag("logger", "${logger}"); +}); +LogManager.Configuration = config; ``` -It's also possible to initialize the SDK through the NLog integration (as opposed to using `SentrySdk.Init`). -This is useful when NLog is the only integration being used in your application. To initialize the Sentry SDK through the NLog integration, provide it with the DSN: - - -```csharp -LogManager.Configuration = new LoggingConfiguration(); -LogManager.Configuration - .AddSentry(o => - { - // The NLog integration will initialize the SDK if DSN is set: - o.Dsn = "___PUBLIC_DSN___"; - }); -``` - - - -The SDK needs to be initialized only once. If a `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 integration, set the `InitializeSdk` flag to **false**. Not providing a DSN or leaving it as `null` instructs the integration not to initialize the SDK and unless another integration initializes it or you call `SentrySdk.Init`, the SDK will stay disabled. - - +The target drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the target also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. ### Minimum log level Two log levels are used to configure this integration (see options below). One will configure the lowest level required for a log message to become an event (`MinimumEventLevel`) sent to Sentry. The other option (`MinimumBreadcrumbLevel`) configures the lowest level a message has to be to become a breadcrumb. Breadcrumbs are kept in memory (by default the last 100 records) and are sent with events. For example, by default, if you log 100 entries with `logger.Info` or `logger.Warn`, no event is sent to Sentry. If you then log with `logger.Error`, an event is sent to Sentry which includes those 100 `Info` or `Warn` messages. For this to work, `SentryTarget` needs to receive **all** log entries in order to decide what to keep as breadcrumb or sent as event. Make sure to set the `NLog` `LogLevel` configuration to a value lower than what you set for the `MinimumBreadcrumbLevel` and `MinimumEventLevel` to make sure `SentryTarget` receives these log messages. -The SDK can also be configured via `NLog.config` XML file: +The target can also be configured in an `NLog.config` XML file. Sentry itself is still initialized in code: ```xml {tabTitle:NLog.config} @@ -112,23 +97,11 @@ The SDK can also be configured via `NLog.config` XML file: - - - - - true - + minimumEventLevel="Error" + includeEventDataOnBreadcrumbs="true"> @@ -154,10 +127,6 @@ A `LogLevel` that indicates the minimum level a log message needs to be in order 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 - -Whether or not this integration should initialize the SDK. If you intend to call `SentrySdk.Init` yourself you should set this flag to `false`. - #### IgnoreEventsWithNoException To ignore log messages that don't contain an exception. diff --git a/docs/platforms/dotnet/guides/serilog/index.mdx b/docs/platforms/dotnet/guides/serilog/index.mdx index be1d4e29a9ed2d..7b9ecd96da850f 100644 --- a/docs/platforms/dotnet/guides/serilog/index.mdx +++ b/docs/platforms/dotnet/guides/serilog/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/). You can control which logs are captured using the [Serilog MinimumLogLevel](https://github.com/serilog/serilog/wiki/Configuration-Basics#minimum-level). +Log messages are also sent to Sentry as [Structured Logs](logs/). You can control which logs are captured using the [Serilog MinimumLogLevel](https://github.com/serilog/serilog/wiki/Configuration-Basics#minimum-level). ## Install @@ -44,9 +44,20 @@ Messages logged from assemblies with the name starting with `Sentry` will not ge ## Configure -You can configure the Sentry Serilog sink as follows: +The Sentry sink doesn't initialize the SDK. Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/), then add the sink: ```csharp +using Sentry.Serilog; +using Serilog; +using Serilog.Events; + +SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; + // Adds properties from the Serilog LogContext to Sentry events + options.UseSerilog(); +}); + Log.Logger = new LoggerConfiguration() .WriteTo.Sentry(o => { @@ -58,6 +69,8 @@ Log.Logger = new LoggerConfiguration() .CreateLogger(); ``` +You can also configure the sink in `appsettings.json`: + ```json {filename:appsettings.json} { "Serilog": { @@ -78,36 +91,13 @@ Log.Logger = new LoggerConfiguration() } ``` -It's also possible to initialize the SDK through the Serilog integration. This is useful when the Serilog is the only integration being used in your application. To initialize the Sentry SDK through the Serilog integration, provide it with the DSN: - - -```csharp -Log.Logger = new LoggerConfiguration() - .WriteTo.Sentry(o => o.Dsn = "___PUBLIC_DSN___") - .CreateLogger(); -``` - -```json {filename:appsettings.json} -{ - "Serilog": { - "Using": [ "Sentry.Serilog" ], - "WriteTo": [ - { - "Name": "Sentry", - "Args": { - "dsn": "___PUBLIC_DSN___" - } - } - ] - } -} -``` +The sink drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the sink also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. - +### Serilog Properties on Events -The SDK only needs to be initialized once. If a `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 integration, set the `InitializeSdk` flag to **false**. Not providing a DSN or leaving it as `null` instructs the integration not to initialize the SDK and unless another integration initializes it or you call `SentrySdk.Init`, the SDK will stay disabled. +`UseSerilog()` copies the properties in Serilog's `LogContext` onto Sentry events as tags. If you initialize Sentry through a host integration, call it on that integration's options, for example in `UseSentry(options => options.UseSerilog())`. - +If you don't call it, the sink does this for you once it's running, so only events captured before then miss the properties. ### Options @@ -119,10 +109,6 @@ 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 - -Whether or not this integration should initialize the SDK. If you intend to call `SentrySdk.Init` yourself you should set this flag to `false`. - #### RestrictedToMinimumLevel `MinimumBreadcrumbLevel` and `MinimumEventLevel` determine what the sink does with a log event, but every log event the logger captures still reaches the sink. If your logger's minimum level is verbose — for example, because another sink writes debug logs to a file — you can use Serilog's [per-sink minimum level](https://github.com/serilog/serilog/wiki/Configuration-Basics#overriding-per-sink) to stop lower-level log events from reaching Sentry entirely. diff --git a/platform-includes/configuration/config-intro/dotnet.nlog.mdx b/platform-includes/configuration/config-intro/dotnet.nlog.mdx deleted file mode 100644 index fcde9145aad182..00000000000000 --- a/platform-includes/configuration/config-intro/dotnet.nlog.mdx +++ /dev/null @@ -1,87 +0,0 @@ - - -For more information on how to dynamically set event data via `NLog.config`, see NLog's [layout renderer documentation](https://nlog-project.org/config/?tab=layout-renderers). - - - -You can configure the Sentry NLog target via `NLog.config` or by code as follows: - - -```xml {tabTitle:NLog.config} - - - - - - - - - - - - - - - - - - - -``` - -```csharp -using NLog; -using Sentry.NLog; - -LogManager.Configuration.AddSentry(o => -{ - // Optionally specify a separate format for message - o.Layout = "${message}"; - // Optionally specify a separate format for breadcrumbs - o.BreadcrumbLayout = "${logger}: ${message}"; - - // Debug and higher are stored as breadcrumbs (default is Info) - o.MinimumBreadcrumbLevel = LogLevel.Debug; - - // Error and higher is sent as event (default is Error) - o.MinimumEventLevel = LogLevel.Error; - - // Send the logger name as a tag - o.AddTag("logger", "${logger}"); - - // All Sentry Options are accessible here. -}); -``` - -```fsharp -open NLog -open Sentry.NLog - -LogManager.Configuration.AddSentry( - fun o -> - // Optionally specify a separate format for message - o.Layout <- "${message}" - // Optionally specify a separate format for breadcrumbs - o.BreadcrumbLayout <- "${logger}: ${message}" - - // Debug and higher are stored as breadcrumbs (default is Info) - o.MinimumBreadcrumbLevel <- LogLevel.Debug - - // Error and higher is sent as event (default is Error) - o.MinimumEventLevel <- LogLevel.Error - - // Send the logger name as a tag - o.AddTag("logger", "${logger}") - - // All Sentry Options are accessible here. -) -``` diff --git a/platform-includes/enriching-events/set-tag/dotnet.nlog.mdx b/platform-includes/enriching-events/set-tag/dotnet.nlog.mdx index 991ca6dd8a0f40..5bcfc9716868f2 100644 --- a/platform-includes/enriching-events/set-tag/dotnet.nlog.mdx +++ b/platform-includes/enriching-events/set-tag/dotnet.nlog.mdx @@ -15,7 +15,7 @@ For more information on how to dynamically set event tags via `NLog.config`, see - + diff --git a/platform-includes/enriching-events/set-user/dotnet.nlog.mdx b/platform-includes/enriching-events/set-user/dotnet.nlog.mdx index 28ec6343db210c..5a0a64254a568e 100644 --- a/platform-includes/enriching-events/set-user/dotnet.nlog.mdx +++ b/platform-includes/enriching-events/set-user/dotnet.nlog.mdx @@ -15,7 +15,7 @@ - + @@ -29,7 +29,7 @@ ```csharp SentrySdk.ConfigureScope(scope => { - scope.User = new User + scope.User = new SentryUser { Email = "john.doe@example.com" }; @@ -39,7 +39,7 @@ SentrySdk.ConfigureScope(scope => ```fsharp SentrySdk.ConfigureScope( fun scope -> - scope.User <- User(Email = "john.doe@example.com") + scope.User <- SentryUser(Email = "john.doe@example.com") () ) ``` diff --git a/platform-includes/logs/options/dotnet.mdx b/platform-includes/logs/options/dotnet.mdx index ed7e850819e0d3..fa759802cd52e0 100644 --- a/platform-includes/logs/options/dotnet.mdx +++ b/platform-includes/logs/options/dotnet.mdx @@ -1,33 +1,18 @@ -#### EnableLogs - - -Set to `true` to send logs captured by logging integrations, such as `Microsoft.Extensions.Logging`, Serilog, NLog, and log4net. Defaults to `false`. - -Since version 6.10.0, this option doesn't apply to logs sent through the `SentrySdk.Logger` APIs. Those logs are always sent. - + - -Set to `true` in order to enable the logging integration via the `ILogger` API. - +#### EnableLogs - -Set to `true` in order to enable the logging integration via the `Log`/`Logger` APIs. - +Set to `true` to send the entries your app writes through the `ILogger` API to Sentry as logs. Defaults to `false`. - -Set to `true` in order to enable the logging integration via the NLog `Logger` APIs. - +This option doesn't apply to logs sent through the `SentrySdk.Logger` APIs or, since version 7.0.0, through the Serilog, NLog, and log4net integrations. Those logs are always sent. - -Set to `true` in order to enable the logging integration via the log4net `ILog` APIs. - + #### Configure Microsoft.Extensions.Logging Filters -In apps that use `Microsoft.Extensions.Logging`, setting `EnableLogs = true` enables Sentry's `Microsoft.Extensions.Logging` integration. -Sentry's provider defines the alias `Sentry`. +Sentry's `Microsoft.Extensions.Logging` provider defines the alias `Sentry`. Logs emitted through `ILogger` are sent to Sentry according to your configured provider/category filters and log levels. @@ -51,7 +36,7 @@ Use standard `Microsoft.Extensions.Logging` filtering to reduce noisy categories Setting `Logging:Sentry:LogLevel:Default` to `None` disables logs sent through the `Microsoft.Extensions.Logging` provider for all categories. Logs sent through the `SentrySdk.Logger` APIs aren't affected by these filters and are still sent. -Example with `EnableLogs = true` and `Logging:Sentry:LogLevel:Default = None`: +Example with `Logging:Sentry:LogLevel:Default = None`: ```csharp logger.LogInformation("Will not be sent to Sentry through Microsoft.Extensions.Logging"); @@ -80,7 +65,6 @@ To filter logs or update them before they are sent to Sentry, you can use the `S options => { options.Dsn = "___PUBLIC_DSN___"; - options.EnableLogs = true; // a callback that is invoked before sending a log to Sentry options.SetBeforeSendLog(static log => { diff --git a/platform-includes/logs/setup/dotnet.mdx b/platform-includes/logs/setup/dotnet.mdx index 8cbc3217063c18..5af46ae880e194 100644 --- a/platform-includes/logs/setup/dotnet.mdx +++ b/platform-includes/logs/setup/dotnet.mdx @@ -1,6 +1,6 @@ -Logs sent through the `SentrySdk.Logger` APIs are always sent, so they don't need any extra configuration. To send logs captured by logging integrations, initialize the SDK with the `EnableLogs` option set to `true`. +Logs sent through the `SentrySdk.Logger` APIs are always sent, so they don't need any extra configuration. - + ```csharp SentrySdk.Init(options => @@ -9,99 +9,122 @@ SentrySdk.Init(options => }); ``` -You don't need a logs-specific option to use the `SentrySdk.Logger` APIs. Set `EnableLogs = true` only if you also send logs through a logging integration. +Since version 7.0.0, the Serilog, NLog, log4net, and `Microsoft.Extensions.Logging` integrations also send logs without a logs-specific option. - + + +To also send the entries your app writes through `ILogger`, set `EnableLogs` to `true`: ```csharp {tabTitle:Builder} .UseSentry(options => { options.Dsn = "___PUBLIC_DSN___"; - // Enable logs to be sent to Sentry + // Send ILogger entries to Sentry as logs options.EnableLogs = true; }); ``` + -This enables the `Microsoft.Extensions.Logging` integration. The `SentrySdk.Logger` APIs don't depend on `EnableLogs`. + + +```json {tabTitle:Configuration} {filename:appsettings.json} +{ + "Sentry": { + "Dsn": "___PUBLIC_DSN___", + "EnableLogs": true + } +} +``` - + + +If your `ILogger` entries also go to Serilog, NLog, or log4net, leave `EnableLogs` off. That framework's Sentry integration already sends them as logs, so turning on `EnableLogs` can send each entry twice. -```csharp {tabTitle:Factory} -.AddSentry(options => + + + + +Initialize the SDK with `SentrySdk.Init`, then add Sentry to your logging builder. Entries your app writes through `ILogger` are then sent as logs, without a logs-specific option. + +```csharp +SentrySdk.Init(options => { options.Dsn = "___PUBLIC_DSN___"; - // Enable logs to be sent to Sentry - options.EnableLogs = true; }); + +builder.Logging.AddSentry(); ``` - + - +Before version 7.0.0, `AddSentry` initializes the SDK itself and only sends logs when `EnableLogs` is `true`. Set the DSN and `EnableLogs` in `AddSentry(options => ...)` instead of calling `SentrySdk.Init`. -```json {tabTitle:Configuration} {filename:appsettings.json} -{ - "Sentry": { - "Dsn": "___PUBLIC_DSN___", - "EnableLogs": true - } -} -``` + +Initialize the SDK, then add the Sentry sink. The sink sends logs as soon as you add it. + ```csharp -.WriteTo.Sentry(options => +SentrySdk.Init(options => { options.Dsn = "___PUBLIC_DSN___"; - // Enable logs to be sent to Sentry - options.EnableLogs = true; }); -``` +Log.Logger = new LoggerConfiguration() + .WriteTo.Sentry() + .CreateLogger(); +``` +Initialize the SDK, then add the Sentry target, in code or in your `NLog.config`. The target sends logs as soon as you add it. + ```csharp -LogManager.Configuration = new LoggingConfiguration(); -LogManager.Configuration - .AddSentry(options => - { - options.Dsn = "___PUBLIC_DSN___"; - // Enable logs to be sent to Sentry - options.EnableLogs = true; - }); -``` +SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; +}); -If the SDK is initialized elsewhere (for example, through ASP.NET Core), enable `EnableLogs` on those options instead. The NLog target then captures logs without initializing the SDK itself. +var config = new LoggingConfiguration(); +config.AddSentry(); +LogManager.Configuration = config; +``` -`EnableLogs` isn't exposed as a log4net appender setting, so initialize the SDK with `SentrySdk.Init` and leave the DSN out of your log4net appender configuration. +Initialize the SDK. The `SentryAppender` in your log4net configuration then sends logs. ```csharp SentrySdk.Init(options => { options.Dsn = "___PUBLIC_DSN___"; - // Enable logs to be sent to Sentry - options.EnableLogs = true; }); ``` -The `SentryAppender` configured in your log4net configuration then captures logs without initializing the SDK itself. If the SDK is initialized elsewhere (for example, through ASP.NET Core), enable `EnableLogs` on those options instead. + + + + +If the SDK is initialized elsewhere, for example through ASP.NET Core, skip `SentrySdk.Init`. If your `ILogger` entries also go through this logging framework, leave that integration's `EnableLogs` option off, or they can be sent twice. + + + +Before version 7.0.0, this integration only sends logs when `EnableLogs` is set to `true` on the options used to initialize the SDK. + + It does _not_ capture the `Console.WriteLine()` standard output stream. - diff --git a/platform-includes/logs/usage/dotnet.mdx b/platform-includes/logs/usage/dotnet.mdx index 794c46b4a8ee3c..3aed820772a0bd 100644 --- a/platform-includes/logs/usage/dotnet.mdx +++ b/platform-includes/logs/usage/dotnet.mdx @@ -53,7 +53,7 @@ Sentry Structured Logs also work with [High-performance logging in .NET](https:/ -Once the feature is enabled on the SDK and the SDK is initialized, you can send logs using the _Serilog_ APIs. +Once the SDK is initialized and the Sentry sink is added, you can send logs using the _Serilog_ APIs. The static `Log` and instance `Logger` types expose various methods that you can use to log messages at six different log levels automatically mapped to Sentry's severity: @@ -83,7 +83,7 @@ The _Enrichments_ of _log events_ are attached as attributes to the logs, alongs -Once the feature is enabled on the SDK and the SDK is initialized, you can send logs using the _NLog_ APIs. +Once the SDK is initialized and the Sentry target is added, you can send logs using the _NLog_ APIs. The `Logger` type exposes various methods that you can use to log messages at six different log levels automatically mapped to Sentry's severity: @@ -112,7 +112,7 @@ The _properties_ of _log events_ are attached as attributes to the logs, alongsi -Once the feature is enabled on the SDK and the SDK is initialized, you can send logs using the _log4net_ APIs, for example through the `ILog` methods (`Debug`, `Info`, `Warn`, `Error`, and `Fatal`). +Once the SDK is initialized and the `SentryAppender` is configured, you can send logs using the _log4net_ APIs, for example through the `ILog` methods (`Debug`, `Info`, `Warn`, `Error`, and `Fatal`). log4net levels are automatically mapped to Sentry's severity: @@ -139,7 +139,7 @@ Log.Warn("Message with a custom property"); The log4net _properties_ (from the log event, `ThreadContext`, and `GlobalContext`) are attached as `property.` attributes to the logs, alongside a set of default attributes automatically provided by the SDK. The logger name is attached as the `category.name` attribute. -The `SentryAppender`'s `Environment` and `SendIdentity` settings also apply to structured logs: when configured, `Environment` sets the log's environment and `SendIdentity` attaches the log4net identity as the user. +The `SentryAppender`'s `SendIdentity` setting also applies to structured logs: when configured, it attaches the log4net identity as the user. Because log4net renders each message before it reaches the appender, structured logs from log4net carry the fully-formatted message but no message template or parameters. diff --git a/platform-includes/metrics/options/dotnet.mdx b/platform-includes/metrics/options/dotnet.mdx index 66cf538065ca1a..dcfd20e16f1803 100644 --- a/platform-includes/metrics/options/dotnet.mdx +++ b/platform-includes/metrics/options/dotnet.mdx @@ -1,6 +1,6 @@ #### EnableMetrics -This option is obsolete and ignored since version 6.10.0, and will be removed in version 7.0.0. Metrics sent through the `SentrySdk.Metrics` APIs are always sent, even if you set `EnableMetrics` to `false`. To drop metrics, use `SetBeforeSendMetric` and return `null`. +This option was removed in version 7.0.0, and has been ignored since version 6.10.0. Metrics sent through the `SentrySdk.Metrics` APIs are always sent. To drop metrics, use `SetBeforeSendMetric` and return `null`. #### SetBeforeSendMetric diff --git a/platform-includes/set-environment/dotnet.nlog.mdx b/platform-includes/set-environment/dotnet.nlog.mdx deleted file mode 100644 index 9b31a70582387f..00000000000000 --- a/platform-includes/set-environment/dotnet.nlog.mdx +++ /dev/null @@ -1,40 +0,0 @@ - - -For more information on how to dynamically set event data via `NLog.config`, see NLog's [layout renderer documentation](https://nlog-project.org/config/?tab=layout-renderers). - - - - -```xml {tabTitle:NLog.config} - - - - - - - - - - - - - - - -``` - -```csharp -// Add this to the SDK initialization callback -options.Environment = "production"; -``` - -```fsharp -// Add this to the SDK initialization callback -options.Environment <- "production" -``` diff --git a/platform-includes/set-release/dotnet.nlog.mdx b/platform-includes/set-release/dotnet.nlog.mdx deleted file mode 100644 index 7972d4f355bd39..00000000000000 --- a/platform-includes/set-release/dotnet.nlog.mdx +++ /dev/null @@ -1,46 +0,0 @@ - - -For more information on how to dynamically set event data via `NLog.config`, see NLog's [layout renderer documentation](https://nlog-project.org/config/?tab=layout-renderers). - - - - -```xml {tabTitle:NLog.config} - - - - - - - - - - - - - - -``` - -```csharp -// Add this to the SDK initialization callback -options.Release = "my-project-name@2.3.12"; -``` - -```fsharp -// Add this to the SDK initialization callback -options.Release <- "my-project-name@2.3.12" -``` - -The SDK attempts to locate the release to add to events sent to Sentry. - -The SDK will first look at the [entry assembly's]() `AssemblyInformationalVersionAttribute`, which accepts a string as -value and is often used to set a GIT commit hash. - -If that returns null, it'll look at the default `AssemblyVersionAttribute` which accepts the numeric version number. From 66ff347562f1a415b8977f2b8e32a9161619a71f Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 13 Oct 2026 16:22:10 +1300 Subject: [PATCH 02/11] docs(dotnet): Use the OTLP exporter in the Azure Functions guide UseOpenTelemetry() and TracerProviderBuilder.AddSentry() have been obsolete since 6.12.0. Use UseOtlp() and AddSentryOtlpExporter from Sentry.OpenTelemetry.Exporter, as the version7 sample does. Co-Authored-By: Claude Opus 5.5 --- .../guides/azure-functions-worker/index.mdx | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx index 02e8ed59799a97..389de36ffe4535 100644 --- a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx +++ b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx @@ -4,7 +4,7 @@ sdk: sentry.dotnet.azure.functions.worker description: "Learn about Sentry's .NET integration with Azure Functions." --- -Sentry provides an integration with Azure Functions through the [Sentry.Extensions.Logging](https://www.nuget.org/packages/Sentry.Extensions.Logging) and [Sentry.OpenTelemetry](https://www.nuget.org/packages/Sentry.OpenTelemetry) NuGet packages. +Sentry provides an integration with Azure Functions through the [Sentry.Extensions.Logging](https://www.nuget.org/packages/Sentry.Extensions.Logging) and [Sentry.OpenTelemetry.Exporter](https://www.nuget.org/packages/Sentry.OpenTelemetry.Exporter) NuGet packages. ## Features @@ -21,8 +21,7 @@ Add the Sentry dependencies to your Azure Functions application: ```shell {tabTitle:.NET Core CLI} dotnet add package Sentry.Extensions.Logging -v {{@inject packages.version('sentry.dotnet.extensions.logging') }} // ___PRODUCT_OPTION_START___ performance -dotnet add package Sentry.OpenTelemetry -v {{@inject packages.version('sentry.dotnet.opentelemetry') }} -dotnet add package OpenTelemetry +dotnet add package Sentry.OpenTelemetry.Exporter -v {{@inject packages.version('sentry.dotnet') }} dotnet add package OpenTelemetry.Extensions.Hosting dotnet add package OpenTelemetry.Instrumentation.Http @@ -32,7 +31,9 @@ dotnet add package OpenTelemetry.Instrumentation.Http ```powershell {tabTitle:Package Manager} Install-Package Sentry.Extensions.Logging -Version {{@inject packages.version('sentry.dotnet.extensions.logging') }} // ___PRODUCT_OPTION_START___ performance -Install-Package Sentry.OpenTelemetry -Version {{@inject packages.version('sentry.dotnet.opentelemetry') }} +Install-Package Sentry.OpenTelemetry.Exporter -Version {{@inject packages.version('sentry.dotnet') }} +Install-Package OpenTelemetry.Extensions.Hosting +Install-Package OpenTelemetry.Instrumentation.Http // ___PRODUCT_OPTION_END___ ``` @@ -43,7 +44,7 @@ The [Sentry.Extensions.Logging](/platforms/dotnet/guides/extensions-logging/) pa Initialize Sentry with `SentrySdk.Init`, then call `AddSentry` when configuring logging to capture log messages. -Performance tracing can be enabled by adding Sentry to the OpenTelemetry `TracerProviderBuilder` and then configuring Sentry itself to use OpenTelemetry. +Tracing is done with OpenTelemetry: add Sentry's OTLP exporter to the OpenTelemetry `TracerProviderBuilder`, and call `UseOtlp()` on the Sentry options. See OpenTelemetry (OTLP) for sampling and trace propagation. For example: @@ -51,19 +52,16 @@ For example: ```csharp using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using OpenTelemetry; // ___PRODUCT_OPTION_START___ performance +using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Trace; // ___PRODUCT_OPTION_END___ -using Sentry.OpenTelemetry; -SentrySdk.Init(options => +using var sentry = SentrySdk.Init(options => { options.Dsn = "___PUBLIC_DSN___"; // ___PRODUCT_OPTION_START___ performance - options.TracesSampleRate = 1.0; - options.UseOpenTelemetry(); // <-- Configure Sentry to use open telemetry - options.DisableSentryHttpMessageHandler = true; // So Sentry doesn't also create spans for outbound HTTP requests + options.UseOtlp(); // <-- Configure Sentry to use OpenTelemetry for tracing // ___PRODUCT_OPTION_END___ options.Debug = true; }); @@ -76,7 +74,7 @@ var host = new HostBuilder() services.AddOpenTelemetry().WithTracing(builder => { builder - .AddSentry() // <-- Configure OpenTelemetry to send traces to Sentry + .AddSentryOtlpExporter("___PUBLIC_DSN___") // <-- Send traces to Sentry over OTLP .AddHttpClientInstrumentation(); // From OpenTelemetry.Instrumentation.Http, instruments outgoing HTTP requests }); }) @@ -84,7 +82,6 @@ var host = new HostBuilder() .ConfigureLogging(logging => logging.AddSentry()) .Build(); - await host.RunAsync(); ``` From 808d76e1c7450e3609784a1ee72297404a9b77c4 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 13 Oct 2026 16:48:56 +1300 Subject: [PATCH 03/11] docs(dotnet): Say when EnableLogs sends logs twice It happens only when Serilog, NLog or log4net is also registered as an ILogger provider, so name that case instead of "ILogger entries also go to" the framework. Co-Authored-By: Claude Opus 5.5 --- platform-includes/logs/setup/dotnet.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-includes/logs/setup/dotnet.mdx b/platform-includes/logs/setup/dotnet.mdx index 5af46ae880e194..ca85a88ff1553f 100644 --- a/platform-includes/logs/setup/dotnet.mdx +++ b/platform-includes/logs/setup/dotnet.mdx @@ -43,7 +43,7 @@ To also send the entries your app writes through `ILogger`, set `EnableLogs` to -If your `ILogger` entries also go to Serilog, NLog, or log4net, leave `EnableLogs` off. That framework's Sentry integration already sends them as logs, so turning on `EnableLogs` can send each entry twice. +If you also register Serilog, NLog, or log4net as an `ILogger` provider (for example with `builder.Logging.AddSerilog()`), leave `EnableLogs` off. That framework's Sentry integration already sends those entries as logs, so `EnableLogs` would send each one twice. @@ -117,7 +117,7 @@ SentrySdk.Init(options => -If the SDK is initialized elsewhere, for example through ASP.NET Core, skip `SentrySdk.Init`. If your `ILogger` entries also go through this logging framework, leave that integration's `EnableLogs` option off, or they can be sent twice. +If the SDK is initialized elsewhere, for example through ASP.NET Core, skip `SentrySdk.Init`. If you also register this framework as an `ILogger` provider (for example with `AddSerilog()`, `AddNLog()`, or `AddLog4Net()`), leave `EnableLogs` off in the options you pass to `UseSentry`. This integration already sends those entries as logs, so `EnableLogs` would send each one twice. From 68f7cf82fd84534c10845033e6c03d945d290b91 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 13 Oct 2026 16:51:37 +1300 Subject: [PATCH 04/11] Tweak copy Co-authored-by: James Crosswell --- .../dotnet/guides/azure-functions-worker/index.mdx | 6 ------ docs/platforms/dotnet/guides/log4net/index.mdx | 4 ++-- .../nlog/configuration/advanced-configuration-example.mdx | 2 +- docs/platforms/dotnet/guides/nlog/index.mdx | 4 ++-- docs/platforms/dotnet/guides/serilog/index.mdx | 2 +- platform-includes/metrics/options/dotnet.mdx | 2 +- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx index 389de36ffe4535..5a7656056f5376 100644 --- a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx +++ b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx @@ -85,12 +85,6 @@ var host = new HostBuilder() await host.RunAsync(); ``` - - -Before version 7.0.0, `AddSentry` initializes the SDK itself. Pass the options to `logging.AddSentry(options => ...)` instead of calling `SentrySdk.Init`. - - - ## Verify This snippet includes an intentional error, so you can test that everything is working as soon as you set it up. diff --git a/docs/platforms/dotnet/guides/log4net/index.mdx b/docs/platforms/dotnet/guides/log4net/index.mdx index 54408d8d04159a..37c8d9c5a9c6bb 100644 --- a/docs/platforms/dotnet/guides/log4net/index.mdx +++ b/docs/platforms/dotnet/guides/log4net/index.mdx @@ -27,7 +27,7 @@ This package extends `Sentry` main SDK. That means besides the log4net `Appender ## Configure -The appender doesn't initialize the SDK. Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/): +Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/): ```csharp SentrySdk.Init(options => @@ -48,7 +48,7 @@ This can be done, for example, via the `app.config` for console and desktop apps ``` -Other [SDK options](/platforms/dotnet/guides/log4net/configuration/options/) also go in `SentrySdk.Init`. +Other [SDK options](/platforms/dotnet/guides/log4net/configuration/options/) can also be configured when calling `SentrySdk.Init`. The appender drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the appender also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. diff --git a/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx b/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx index e71c57206fcc9b..9a701a3340089a 100644 --- a/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx +++ b/docs/platforms/dotnet/guides/nlog/configuration/advanced-configuration-example.mdx @@ -10,7 +10,7 @@ For more information on how to dynamically set event data via `NLog.config`, see -The Sentry target doesn't initialize the SDK, so initialize Sentry in code first. SDK options, such as the environment and release, go here: +Call `SentrySdk.Init` to initialize the SDK first. SDK options, such as the environment and release, go here: ```csharp SentrySdk.Init(options => diff --git a/docs/platforms/dotnet/guides/nlog/index.mdx b/docs/platforms/dotnet/guides/nlog/index.mdx index f9a6efff1bfc11..691507085bb412 100644 --- a/docs/platforms/dotnet/guides/nlog/index.mdx +++ b/docs/platforms/dotnet/guides/nlog/index.mdx @@ -50,7 +50,7 @@ For more information on how to dynamically set event data via `NLog.config`, see -The Sentry target doesn't initialize the SDK. Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/), then add the target. You can add it in code: +Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/), then add the target. You can add it in code: ```csharp SentrySdk.Init(options => @@ -83,7 +83,7 @@ The target drops log events while Sentry isn't initialized. If a DSN can be foun Two log levels are used to configure this integration (see options below). One will configure the lowest level required for a log message to become an event (`MinimumEventLevel`) sent to Sentry. The other option (`MinimumBreadcrumbLevel`) configures the lowest level a message has to be to become a breadcrumb. Breadcrumbs are kept in memory (by default the last 100 records) and are sent with events. For example, by default, if you log 100 entries with `logger.Info` or `logger.Warn`, no event is sent to Sentry. If you then log with `logger.Error`, an event is sent to Sentry which includes those 100 `Info` or `Warn` messages. For this to work, `SentryTarget` needs to receive **all** log entries in order to decide what to keep as breadcrumb or sent as event. Make sure to set the `NLog` `LogLevel` configuration to a value lower than what you set for the `MinimumBreadcrumbLevel` and `MinimumEventLevel` to make sure `SentryTarget` receives these log messages. -The target can also be configured in an `NLog.config` XML file. Sentry itself is still initialized in code: +The target can also be configured in an `NLog.config` XML file: ```xml {tabTitle:NLog.config} diff --git a/docs/platforms/dotnet/guides/serilog/index.mdx b/docs/platforms/dotnet/guides/serilog/index.mdx index 7b9ecd96da850f..d9ce5d91233a73 100644 --- a/docs/platforms/dotnet/guides/serilog/index.mdx +++ b/docs/platforms/dotnet/guides/serilog/index.mdx @@ -44,7 +44,7 @@ Messages logged from assemblies with the name starting with `Sentry` will not ge ## Configure -The Sentry sink doesn't initialize the SDK. Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/), then add the sink: +Initialize Sentry first, with `SentrySdk.Init` or a host integration such as [ASP.NET Core](/platforms/dotnet/guides/aspnetcore/), then add the sink: ```csharp using Sentry.Serilog; diff --git a/platform-includes/metrics/options/dotnet.mdx b/platform-includes/metrics/options/dotnet.mdx index dcfd20e16f1803..b895616385f389 100644 --- a/platform-includes/metrics/options/dotnet.mdx +++ b/platform-includes/metrics/options/dotnet.mdx @@ -1,6 +1,6 @@ #### EnableMetrics -This option was removed in version 7.0.0, and has been ignored since version 6.10.0. Metrics sent through the `SentrySdk.Metrics` APIs are always sent. To drop metrics, use `SetBeforeSendMetric` and return `null`. +This option was removed in version 7.0.0, and has been ignored since version 6.10.0. Metrics sent through the `SentrySdk.Metrics` APIs are now always sent. To drop metrics, use `SetBeforeSendMetric` and return `null`. #### SetBeforeSendMetric From 6a6fa90536378c79a3f3535ca713e6ab09aa2f30 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 14 Oct 2026 14:15:37 +1300 Subject: [PATCH 05/11] docs(dotnet): Format the 7.0.0 behaviour changes as notes Co-Authored-By: Claude Opus 5.5 --- platform-includes/logs/options/dotnet.mdx | 8 +++++++- platform-includes/logs/setup/dotnet.mdx | 16 +++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/platform-includes/logs/options/dotnet.mdx b/platform-includes/logs/options/dotnet.mdx index fa759802cd52e0..c2ef96cd95a79c 100644 --- a/platform-includes/logs/options/dotnet.mdx +++ b/platform-includes/logs/options/dotnet.mdx @@ -4,7 +4,13 @@ Set to `true` to send the entries your app writes through the `ILogger` API to Sentry as logs. Defaults to `false`. -This option doesn't apply to logs sent through the `SentrySdk.Logger` APIs or, since version 7.0.0, through the Serilog, NLog, and log4net integrations. Those logs are always sent. +This option doesn't apply to logs sent through the `SentrySdk.Logger` APIs or through the Serilog, NLog, and log4net integrations. Those logs are always sent. + + + +In earlier versions, `EnableLogs` was an option on `SentryOptions`, and the Serilog, NLog, and log4net integrations only sent logs when it was `true`. + + diff --git a/platform-includes/logs/setup/dotnet.mdx b/platform-includes/logs/setup/dotnet.mdx index ca85a88ff1553f..5c6eb88e0922d3 100644 --- a/platform-includes/logs/setup/dotnet.mdx +++ b/platform-includes/logs/setup/dotnet.mdx @@ -9,7 +9,13 @@ SentrySdk.Init(options => }); ``` -Since version 7.0.0, the Serilog, NLog, log4net, and `Microsoft.Extensions.Logging` integrations also send logs without a logs-specific option. +The Serilog, NLog, log4net, and `Microsoft.Extensions.Logging` integrations also send logs without a logs-specific option. + + + +In earlier versions, these integrations only sent logs when `EnableLogs` was `true`. + + @@ -60,9 +66,9 @@ SentrySdk.Init(options => builder.Logging.AddSentry(); ``` - + -Before version 7.0.0, `AddSentry` initializes the SDK itself and only sends logs when `EnableLogs` is `true`. Set the DSN and `EnableLogs` in `AddSentry(options => ...)` instead of calling `SentrySdk.Init`. +In earlier versions, `AddSentry` initialized the SDK itself and only sent logs when `EnableLogs` was `true`. On those versions, set the DSN and `EnableLogs` in `AddSentry(options => ...)` instead of calling `SentrySdk.Init`. @@ -119,9 +125,9 @@ SentrySdk.Init(options => If the SDK is initialized elsewhere, for example through ASP.NET Core, skip `SentrySdk.Init`. If you also register this framework as an `ILogger` provider (for example with `AddSerilog()`, `AddNLog()`, or `AddLog4Net()`), leave `EnableLogs` off in the options you pass to `UseSentry`. This integration already sends those entries as logs, so `EnableLogs` would send each one twice. - + -Before version 7.0.0, this integration only sends logs when `EnableLogs` is set to `true` on the options used to initialize the SDK. +In earlier versions, this integration only sent logs when `EnableLogs` was set to `true` on the options used to initialize the SDK. From 83f69ae8711893258a7de2e45e91ca1d0c20361b Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 28 Oct 2026 15:44:48 +1300 Subject: [PATCH 06/11] docs(dotnet): Show how to use Serilog, NLog and log4net with UseSentry without duplicates Co-Authored-By: Claude Opus 5.5 --- .../platforms/dotnet/guides/log4net/index.mdx | 16 ++++++++++++++ docs/platforms/dotnet/guides/nlog/index.mdx | 21 +++++++++++++++++++ .../platforms/dotnet/guides/serilog/index.mdx | 17 +++++++++++++++ platform-includes/logs/setup/dotnet.mdx | 4 ++-- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/docs/platforms/dotnet/guides/log4net/index.mdx b/docs/platforms/dotnet/guides/log4net/index.mdx index 37c8d9c5a9c6bb..00e0fde7617643 100644 --- a/docs/platforms/dotnet/guides/log4net/index.mdx +++ b/docs/platforms/dotnet/guides/log4net/index.mdx @@ -52,6 +52,22 @@ Other [SDK options](/platforms/dotnet/guides/log4net/configuration/options/) can The appender drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the appender also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. +### ASP.NET Core + +If an app that calls `UseSentry` also sends `ILogger` entries to log4net, for example with `AddLog4Net()` from the `Microsoft.Extensions.Logging.Log4Net.AspNetCore` package, both the appender and the `ILogger` integration that `UseSentry` adds capture each entry. Turn off events and breadcrumbs from the `ILogger` integration and leave `EnableLogs` off, so each entry reaches Sentry once, through the appender: + +```json {filename:appsettings.json} +{ + "Sentry": { + "Dsn": "___PUBLIC_DSN___", + "MinimumBreadcrumbLevel": "None", + "MinimumEventLevel": "None" + } +} +``` + +Levels set in code, in `UseSentry(options => ...)`, override these settings. + ### SendIdentity In the example above, the `SendIdentity` flag was switched on. The SDK then will take the log4net `Identity` value and report to Sentry as the user's id. diff --git a/docs/platforms/dotnet/guides/nlog/index.mdx b/docs/platforms/dotnet/guides/nlog/index.mdx index 84b435be1a45c8..e8cf1473fb2be5 100644 --- a/docs/platforms/dotnet/guides/nlog/index.mdx +++ b/docs/platforms/dotnet/guides/nlog/index.mdx @@ -117,6 +117,26 @@ The target can also be configured in an `NLog.config` XML file: ``` +### ASP.NET Core + +In an app that calls `UseSentry`, add NLog with `UseNLog` from the `NLog.Web.AspNetCore` package, and set `ReplaceLoggerFactory`: + +```csharp {filename:Program.cs} +var config = new LoggingConfiguration(); +config.AddSentry(); +LogManager.Configuration = config; + +var builder = WebApplication.CreateBuilder(args); + +builder.Host.UseNLog(new NLogAspNetCoreOptions { ReplaceLoggerFactory = true }); +builder.UseSentry(options => +{ + options.Dsn = "___PUBLIC_DSN___"; +}); +``` + +`ReplaceLoggerFactory` replaces the app's `ILogger` factory with NLog's, so each `ILogger` entry reaches Sentry once, through the target. Without it, `UseNLog()` adds NLog alongside the `ILogger` integration that `UseSentry` adds, and Sentry receives every entry twice. NLog's rules then decide which entries are logged, instead of the `Logging` section of `appsettings.json`. + ### Options #### MinimumBreadcrumbLevel @@ -178,6 +198,7 @@ This snippet includes an intentional error, so you can test that everything is w ## Samples - A [simple example](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.NLog). +- An [example with ASP.NET Core](https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.AspNetCore.NLog). - Example of [advanced configuration](configuration/advanced-configuration-example/) ## Next Steps diff --git a/docs/platforms/dotnet/guides/serilog/index.mdx b/docs/platforms/dotnet/guides/serilog/index.mdx index d9ce5d91233a73..a0980bc38527fe 100644 --- a/docs/platforms/dotnet/guides/serilog/index.mdx +++ b/docs/platforms/dotnet/guides/serilog/index.mdx @@ -93,6 +93,23 @@ You can also configure the sink in `appsettings.json`: The sink drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the sink also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. +### ASP.NET Core + +In an app that calls `UseSentry`, add Serilog with `UseSerilog` and add the sink there: + +```csharp {filename:Program.cs} +var builder = WebApplication.CreateBuilder(args); + +builder.Host.UseSerilog((_, config) => config.WriteTo.Sentry()); +builder.UseSentry(options => +{ + options.Dsn = "___PUBLIC_DSN___"; + options.UseSerilog(); +}); +``` + +`UseSerilog` replaces the app's `ILogger` factory with Serilog's, so each `ILogger` entry reaches Sentry once, through the sink. Don't add Serilog with `builder.Logging.AddSerilog()` or `UseSerilog(..., writeToProviders: true)`. Both also send each entry through the `ILogger` integration that `UseSentry` adds, so Sentry receives it twice. + ### Serilog Properties on Events `UseSerilog()` copies the properties in Serilog's `LogContext` onto Sentry events as tags. If you initialize Sentry through a host integration, call it on that integration's options, for example in `UseSentry(options => options.UseSerilog())`. diff --git a/platform-includes/logs/setup/dotnet.mdx b/platform-includes/logs/setup/dotnet.mdx index 5c6eb88e0922d3..b8913cbef332a7 100644 --- a/platform-includes/logs/setup/dotnet.mdx +++ b/platform-includes/logs/setup/dotnet.mdx @@ -49,7 +49,7 @@ To also send the entries your app writes through `ILogger`, set `EnableLogs` to -If you also register Serilog, NLog, or log4net as an `ILogger` provider (for example with `builder.Logging.AddSerilog()`), leave `EnableLogs` off. That framework's Sentry integration already sends those entries as logs, so `EnableLogs` would send each one twice. +If your app sends `ILogger` entries through Serilog, NLog, or log4net, leave `EnableLogs` off, and set up that framework as described in the ASP.NET Core section of the [Serilog](/platforms/dotnet/guides/serilog/#aspnet-core), [NLog](/platforms/dotnet/guides/nlog/#aspnet-core), or [log4net](/platforms/dotnet/guides/log4net/#aspnet-core) guide. That framework's Sentry integration then sends each entry to Sentry once. @@ -123,7 +123,7 @@ SentrySdk.Init(options => -If the SDK is initialized elsewhere, for example through ASP.NET Core, skip `SentrySdk.Init`. If you also register this framework as an `ILogger` provider (for example with `AddSerilog()`, `AddNLog()`, or `AddLog4Net()`), leave `EnableLogs` off in the options you pass to `UseSentry`. This integration already sends those entries as logs, so `EnableLogs` would send each one twice. +If the SDK is initialized elsewhere, for example through ASP.NET Core, skip `SentrySdk.Init`. To send `ILogger` entries through this integration in an app that calls `UseSentry`, see [ASP.NET Core](#aspnet-core). From d91e17ed13765ffbda81ce835042fe6d6369443b Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 28 Oct 2026 16:09:38 +1300 Subject: [PATCH 07/11] docs(dotnet): Share the UseSentry setup for Serilog, NLog and log4net across host apps Co-Authored-By: Claude Opus 5.5 --- .../platforms/dotnet/guides/log4net/index.mdx | 16 +------- docs/platforms/dotnet/guides/nlog/index.mdx | 20 +--------- .../platforms/dotnet/guides/serilog/index.mdx | 17 +------- includes/dotnet-usesentry-logging/log4net.mdx | 10 +++++ includes/dotnet-usesentry-logging/nlog.mdx | 15 +++++++ includes/dotnet-usesentry-logging/serilog.mdx | 12 ++++++ platform-includes/logs/setup/dotnet.mdx | 40 ++++++++++++++++++- 7 files changed, 81 insertions(+), 49 deletions(-) create mode 100644 includes/dotnet-usesentry-logging/log4net.mdx create mode 100644 includes/dotnet-usesentry-logging/nlog.mdx create mode 100644 includes/dotnet-usesentry-logging/serilog.mdx diff --git a/docs/platforms/dotnet/guides/log4net/index.mdx b/docs/platforms/dotnet/guides/log4net/index.mdx index 00e0fde7617643..238a7ed4acf965 100644 --- a/docs/platforms/dotnet/guides/log4net/index.mdx +++ b/docs/platforms/dotnet/guides/log4net/index.mdx @@ -52,21 +52,9 @@ Other [SDK options](/platforms/dotnet/guides/log4net/configuration/options/) can The appender drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the appender also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. -### ASP.NET Core +### Apps That Call UseSentry -If an app that calls `UseSentry` also sends `ILogger` entries to log4net, for example with `AddLog4Net()` from the `Microsoft.Extensions.Logging.Log4Net.AspNetCore` package, both the appender and the `ILogger` integration that `UseSentry` adds capture each entry. Turn off events and breadcrumbs from the `ILogger` integration and leave `EnableLogs` off, so each entry reaches Sentry once, through the appender: - -```json {filename:appsettings.json} -{ - "Sentry": { - "Dsn": "___PUBLIC_DSN___", - "MinimumBreadcrumbLevel": "None", - "MinimumEventLevel": "None" - } -} -``` - -Levels set in code, in `UseSentry(options => ...)`, override these settings. + ### SendIdentity diff --git a/docs/platforms/dotnet/guides/nlog/index.mdx b/docs/platforms/dotnet/guides/nlog/index.mdx index e8cf1473fb2be5..b28a4bd51dbb6f 100644 --- a/docs/platforms/dotnet/guides/nlog/index.mdx +++ b/docs/platforms/dotnet/guides/nlog/index.mdx @@ -117,25 +117,9 @@ The target can also be configured in an `NLog.config` XML file: ``` -### ASP.NET Core +### Apps That Call UseSentry -In an app that calls `UseSentry`, add NLog with `UseNLog` from the `NLog.Web.AspNetCore` package, and set `ReplaceLoggerFactory`: - -```csharp {filename:Program.cs} -var config = new LoggingConfiguration(); -config.AddSentry(); -LogManager.Configuration = config; - -var builder = WebApplication.CreateBuilder(args); - -builder.Host.UseNLog(new NLogAspNetCoreOptions { ReplaceLoggerFactory = true }); -builder.UseSentry(options => -{ - options.Dsn = "___PUBLIC_DSN___"; -}); -``` - -`ReplaceLoggerFactory` replaces the app's `ILogger` factory with NLog's, so each `ILogger` entry reaches Sentry once, through the target. Without it, `UseNLog()` adds NLog alongside the `ILogger` integration that `UseSentry` adds, and Sentry receives every entry twice. NLog's rules then decide which entries are logged, instead of the `Logging` section of `appsettings.json`. + ### Options diff --git a/docs/platforms/dotnet/guides/serilog/index.mdx b/docs/platforms/dotnet/guides/serilog/index.mdx index a0980bc38527fe..e8cfcfbb25182a 100644 --- a/docs/platforms/dotnet/guides/serilog/index.mdx +++ b/docs/platforms/dotnet/guides/serilog/index.mdx @@ -93,22 +93,9 @@ You can also configure the sink in `appsettings.json`: The sink drops log events while Sentry isn't initialized. If a DSN can be found anyway, for example in the `SENTRY_DSN` environment variable, the sink also writes a warning to standard error the first time it drops an event. To fix it, initialize Sentry at startup as shown above. -### ASP.NET Core +### Apps That Call UseSentry -In an app that calls `UseSentry`, add Serilog with `UseSerilog` and add the sink there: - -```csharp {filename:Program.cs} -var builder = WebApplication.CreateBuilder(args); - -builder.Host.UseSerilog((_, config) => config.WriteTo.Sentry()); -builder.UseSentry(options => -{ - options.Dsn = "___PUBLIC_DSN___"; - options.UseSerilog(); -}); -``` - -`UseSerilog` replaces the app's `ILogger` factory with Serilog's, so each `ILogger` entry reaches Sentry once, through the sink. Don't add Serilog with `builder.Logging.AddSerilog()` or `UseSerilog(..., writeToProviders: true)`. Both also send each entry through the `ILogger` integration that `UseSentry` adds, so Sentry receives it twice. + ### Serilog Properties on Events diff --git a/includes/dotnet-usesentry-logging/log4net.mdx b/includes/dotnet-usesentry-logging/log4net.mdx new file mode 100644 index 00000000000000..3da0550448848b --- /dev/null +++ b/includes/dotnet-usesentry-logging/log4net.mdx @@ -0,0 +1,10 @@ +If an app that calls `UseSentry` also sends `ILogger` entries to log4net, for example with `AddLog4Net()` from the `Microsoft.Extensions.Logging.Log4Net.AspNetCore` package, both the appender and the `ILogger` integration that `UseSentry` adds capture each entry. Turn off events and breadcrumbs from the `ILogger` integration and leave `EnableLogs` off, so each entry reaches Sentry once, through the appender: + +```csharp {filename:Program.cs} +builder.UseSentry(options => +{ + options.Dsn = "___PUBLIC_DSN___"; + options.MinimumBreadcrumbLevel = LogLevel.None; + options.MinimumEventLevel = LogLevel.None; +}); +``` diff --git a/includes/dotnet-usesentry-logging/nlog.mdx b/includes/dotnet-usesentry-logging/nlog.mdx new file mode 100644 index 00000000000000..6872599cff13eb --- /dev/null +++ b/includes/dotnet-usesentry-logging/nlog.mdx @@ -0,0 +1,15 @@ +In an app that calls `UseSentry`, add NLog with `AddNLog` from the `NLog.Extensions.Logging` package, and set `ReplaceLoggerFactory`: + +```csharp {filename:Program.cs} +var config = new LoggingConfiguration(); +config.AddSentry(); +LogManager.Configuration = config; + +builder.Logging.AddNLog(new NLogProviderOptions { ReplaceLoggerFactory = true }); +builder.UseSentry(options => +{ + options.Dsn = "___PUBLIC_DSN___"; +}); +``` + +`ReplaceLoggerFactory` replaces the app's `ILogger` factory with NLog's, so each `ILogger` entry reaches Sentry once, through the target. Without it, NLog runs alongside the `ILogger` integration that `UseSentry` adds, and Sentry receives every entry twice. NLog's rules then decide which entries are logged, instead of the `Logging` section of your configuration. In ASP.NET Core, `UseNLog` from the `NLog.Web.AspNetCore` package takes the same option. diff --git a/includes/dotnet-usesentry-logging/serilog.mdx b/includes/dotnet-usesentry-logging/serilog.mdx new file mode 100644 index 00000000000000..b3217b95ba4b58 --- /dev/null +++ b/includes/dotnet-usesentry-logging/serilog.mdx @@ -0,0 +1,12 @@ +In an app that calls `UseSentry`, add Serilog to the builder's services with `AddSerilog` from the `Serilog.Extensions.Hosting` package, and add the sink there: + +```csharp {filename:Program.cs} +builder.Services.AddSerilog(config => config.WriteTo.Sentry()); +builder.UseSentry(options => +{ + options.Dsn = "___PUBLIC_DSN___"; + options.UseSerilog(); +}); +``` + +`AddSerilog` replaces the app's `ILogger` factory with Serilog's, so each `ILogger` entry reaches Sentry once, through the sink. Don't use `builder.Logging.AddSerilog()` or `writeToProviders: true` instead. Both also send each entry through the `ILogger` integration that `UseSentry` adds, so Sentry receives it twice. diff --git a/platform-includes/logs/setup/dotnet.mdx b/platform-includes/logs/setup/dotnet.mdx index b8913cbef332a7..66d380478e0d44 100644 --- a/platform-includes/logs/setup/dotnet.mdx +++ b/platform-includes/logs/setup/dotnet.mdx @@ -49,7 +49,25 @@ To also send the entries your app writes through `ILogger`, set `EnableLogs` to -If your app sends `ILogger` entries through Serilog, NLog, or log4net, leave `EnableLogs` off, and set up that framework as described in the ASP.NET Core section of the [Serilog](/platforms/dotnet/guides/serilog/#aspnet-core), [NLog](/platforms/dotnet/guides/nlog/#aspnet-core), or [log4net](/platforms/dotnet/guides/log4net/#aspnet-core) guide. That framework's Sentry integration then sends each entry to Sentry once. +If your app also sends `ILogger` entries through Serilog, NLog, or log4net, leave `EnableLogs` off and set up the framework as shown below, so each entry reaches Sentry once. + + + + + + + + + + + + + + + + + + @@ -123,7 +141,7 @@ SentrySdk.Init(options => -If the SDK is initialized elsewhere, for example through ASP.NET Core, skip `SentrySdk.Init`. To send `ILogger` entries through this integration in an app that calls `UseSentry`, see [ASP.NET Core](#aspnet-core). +If the SDK is initialized elsewhere, for example by `UseSentry`, skip `SentrySdk.Init`. @@ -133,4 +151,22 @@ In earlier versions, this integration only sent logs when `EnableLogs` was set t + + + + + + + + + + + + + + + + + + It does _not_ capture the `Console.WriteLine()` standard output stream. From dfe7afbe76469b1d9bc2720077e31d0552f257d3 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 29 Oct 2026 19:20:49 +1300 Subject: [PATCH 08/11] docs(dotnet): Start Sentry with UseSentry in Azure Functions sentry-dotnet 7.0.0 adds Sentry.Extensions.Hosting, whose UseSentry on IHostBuilder is how Azure Functions (isolated) apps start Sentry, also with the ASP.NET Core integration. Install that package, call UseSentry on the HostBuilder chain, and set EnableLogs to send ILogger entries as logs, as on the other host integrations. Remove SentrySdk.Init and logging.AddSentry() from the snippet. On the logs setup and options includes, move dotnet.azure-functions-worker into the UseSentry + EnableLogs sections and add dotnet.extensions-hosting to them, for the generic-host guide. The Microsoft.Extensions.Logging section now says that generic-host apps use UseSentry from Sentry.Extensions.Hosting instead. Co-Authored-By: Claude Opus 5.5 --- .../guides/azure-functions-worker/index.mdx | 36 ++++++++++--------- platform-includes/logs/options/dotnet.mdx | 4 +-- platform-includes/logs/setup/dotnet.mdx | 12 ++++--- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx index 1e40f7c768552b..68f77532bd81d2 100644 --- a/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx +++ b/docs/platforms/dotnet/guides/azure-functions-worker/index.mdx @@ -4,56 +4,57 @@ sdk: sentry.dotnet.azure.functions.worker description: "Learn about Sentry's .NET integration with Azure Functions." --- -Sentry provides an integration with Azure Functions through the [Sentry.Extensions.Logging](https://www.nuget.org/packages/Sentry.Extensions.Logging) and [Sentry.OpenTelemetry.Exporter](https://www.nuget.org/packages/Sentry.OpenTelemetry.Exporter) NuGet packages. +Sentry provides an integration with Azure Functions through the [Sentry.Extensions.Hosting](https://www.nuget.org/packages/Sentry.Extensions.Hosting) and [Sentry.OpenTelemetry.Exporter](https://www.nuget.org/packages/Sentry.OpenTelemetry.Exporter) NuGet packages. ## Install Add the Sentry dependencies to your Azure Functions application: ```shell {tabTitle:.NET Core CLI} -dotnet add package Sentry.Extensions.Logging -v {{@inject packages.version('sentry.dotnet.extensions.logging') }} +dotnet add package Sentry.Extensions.Hosting -v {{@inject packages.version('sentry.dotnet') }} dotnet add package Sentry.OpenTelemetry.Exporter -v {{@inject packages.version('sentry.dotnet') }} dotnet add package OpenTelemetry.Extensions.Hosting dotnet add package OpenTelemetry.Instrumentation.Http ``` ```powershell {tabTitle:Package Manager} -Install-Package Sentry.Extensions.Logging -Version {{@inject packages.version('sentry.dotnet.extensions.logging') }} +Install-Package Sentry.Extensions.Hosting -Version {{@inject packages.version('sentry.dotnet') }} Install-Package Sentry.OpenTelemetry.Exporter -Version {{@inject packages.version('sentry.dotnet') }} Install-Package OpenTelemetry.Extensions.Hosting Install-Package OpenTelemetry.Instrumentation.Http ``` -The [Sentry.Extensions.Logging](/platforms/dotnet/guides/extensions-logging/) package also provides access to the `ILogger` integration and the other core features available in the [Sentry](/platforms/dotnet/) SDK. +This package extends [Sentry.Extensions.Logging](/platforms/dotnet/guides/extensions-logging/). This means you also get the `ILogger` integration and the other core features available in the [Sentry](/platforms/dotnet/) SDK. ## Configure -**Error Monitoring** starts working as soon as you initialize the SDK with `SentrySdk.Init`. **Logs** written through `Microsoft.Extensions.Logging` are sent as soon as you call `AddSentry` when configuring logging, and **Application Metrics** need no extra configuration. You'll learn how to send them in [Send Logs](#send-logs) and [Send Application Metrics](#send-application-metrics-). +**Error Monitoring** starts working as soon as you call `UseSentry` on the host builder. **Logs** sent through `Microsoft.Extensions.Logging` need `EnableLogs = true`, and **Application Metrics** need no extra configuration. You'll learn how to send them in [Send Logs](#send-logs) and [Send Application Metrics](#send-application-metrics-). + +`UseSentry` starts Sentry when the host is built and closes it when the host stops. It also adds Sentry's `ILogger` integration, which captures `LogError` and higher as events. This guide also enables **Tracing** through OpenTelemetry. Sentry's OTLP exporter is added to the OpenTelemetry `TracerProviderBuilder`, and `UseOtlp()` tells the Sentry SDK to use OpenTelemetry for tracing. The snippet also turns on: - Tracing: via `AddSentryOtlpExporter` and `UseOtlp()`. Don't also set `TracesSampleRate`; OpenTelemetry handles tracing. See OpenTelemetry (OTLP) for sampling and trace propagation. -- Logs: via `AddSentry` when configuring logging +- Logs: via `EnableLogs` Don't need a feature? Remove its options from the snippet. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using OpenTelemetry.Trace; -using var sentry = SentrySdk.Init(options => -{ - options.Dsn = "___PUBLIC_DSN___"; - options.UseOtlp(); // <-- Configure Sentry to use OpenTelemetry for tracing - options.Debug = true; -}); - var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() + .UseSentry(options => + { + options.Dsn = "___PUBLIC_DSN___"; + options.EnableLogs = true; + options.UseOtlp(); // <-- Configure Sentry to use OpenTelemetry for tracing + options.Debug = true; + }) .ConfigureServices(services => { services.AddOpenTelemetry().WithTracing(builder => @@ -63,21 +64,22 @@ var host = new HostBuilder() .AddHttpClientInstrumentation(); // From OpenTelemetry.Instrumentation.Http, instruments outgoing HTTP requests }); }) - .ConfigureLogging(logging => logging.AddSentry()) .Build(); await host.RunAsync(); ``` +Apps that use the ASP.NET Core integration, with `ConfigureFunctionsWebApplication()` instead of `ConfigureFunctionsWorkerDefaults()`, call the same `UseSentry`, not the one from `Sentry.AspNetCore`. + -In earlier versions, `AddSentry` initialized the SDK itself and only sent logs when `EnableLogs` was `true`. On those versions, pass the options to `logging.AddSentry(options => ...)`, including `EnableLogs = true`, instead of calling `SentrySdk.Init`. +In earlier versions, there was no `Sentry.Extensions.Hosting` package. On those versions, install `Sentry.Extensions.Logging` and pass the same options to `logging.AddSentry(options => ...)` in `ConfigureLogging`, instead of calling `UseSentry`. ## Send Logs -Use `Microsoft.Extensions.Logging` to send structured logs from your application. The entries your app writes through `ILogger` are sent to Sentry as logs, without a logs-specific option. +Use `Microsoft.Extensions.Logging` to send structured logs from your application. Set `EnableLogs = true` in the options you pass to `UseSentry`. See [Microsoft.Extensions.Logging](/platforms/dotnet/guides/extensions-logging/) for setup details. diff --git a/platform-includes/logs/options/dotnet.mdx b/platform-includes/logs/options/dotnet.mdx index c2ef96cd95a79c..f62c4077bbdd86 100644 --- a/platform-includes/logs/options/dotnet.mdx +++ b/platform-includes/logs/options/dotnet.mdx @@ -1,4 +1,4 @@ - + #### EnableLogs @@ -14,7 +14,7 @@ In earlier versions, `EnableLogs` was an option on `SentryOptions`, and the Seri - + #### Configure Microsoft.Extensions.Logging Filters diff --git a/platform-includes/logs/setup/dotnet.mdx b/platform-includes/logs/setup/dotnet.mdx index 66d380478e0d44..275669da8f82b6 100644 --- a/platform-includes/logs/setup/dotnet.mdx +++ b/platform-includes/logs/setup/dotnet.mdx @@ -1,6 +1,6 @@ Logs sent through the `SentrySdk.Logger` APIs are always sent, so they don't need any extra configuration. - + ```csharp SentrySdk.Init(options => @@ -19,7 +19,7 @@ In earlier versions, these integrations only sent logs when `EnableLogs` was `tr - + To also send the entries your app writes through `ILogger`, set `EnableLogs` to `true`: @@ -34,7 +34,7 @@ To also send the entries your app writes through `ILogger`, set `EnableLogs` to - + ```json {tabTitle:Configuration} {filename:appsettings.json} { @@ -47,7 +47,7 @@ To also send the entries your app writes through `ILogger`, set `EnableLogs` to - + If your app also sends `ILogger` entries through Serilog, NLog, or log4net, leave `EnableLogs` off and set up the framework as shown below, so each entry reaches Sentry once. @@ -71,7 +71,7 @@ If your app also sends `ILogger` entries through Serilog, NLog, or log4net, leav - + Initialize the SDK with `SentrySdk.Init`, then add Sentry to your logging builder. Entries your app writes through `ILogger` are then sent as logs, without a logs-specific option. @@ -84,6 +84,8 @@ SentrySdk.Init(options => builder.Logging.AddSentry(); ``` +Apps on the .NET Generic Host, such as worker services, use `UseSentry` from the `Sentry.Extensions.Hosting` package instead. + In earlier versions, `AddSentry` initialized the SDK itself and only sent logs when `EnableLogs` was `true`. On those versions, set the DSN and `EnableLogs` in `AddSentry(options => ...)` instead of calling `SentrySdk.Init`. From b452bd46f028b0140995c869d7428ed4018ea4b4 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 29 Oct 2026 19:48:30 +1300 Subject: [PATCH 09/11] docs(dotnet): Show the ILogger logs pages on the Generic Host guide The new Generic Host guide (getsentry/sentry-docs#20311) starts Sentry with UseSentry, so its logs usage page should show the ILogger section like the other host integrations, and its requirements start at 7.0.0. Also say that generic host apps set EnableLogs to send ILogger entries. Co-Authored-By: Claude Opus 5.5 --- platform-includes/logs/requirements/dotnet.mdx | 6 +++++- platform-includes/logs/setup/dotnet.mdx | 2 +- platform-includes/logs/usage/dotnet.mdx | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/platform-includes/logs/requirements/dotnet.mdx b/platform-includes/logs/requirements/dotnet.mdx index 33859401902c3d..082e175707d436 100644 --- a/platform-includes/logs/requirements/dotnet.mdx +++ b/platform-includes/logs/requirements/dotnet.mdx @@ -1,7 +1,11 @@ - + Logs for are supported in Sentry SDK version `5.14.0` and above. + +Logs for are supported in Sentry SDK version `7.0.0` and above. + + Logs for are supported in Sentry SDK version `5.16.0` and above. diff --git a/platform-includes/logs/setup/dotnet.mdx b/platform-includes/logs/setup/dotnet.mdx index 275669da8f82b6..8327cd3f626ff6 100644 --- a/platform-includes/logs/setup/dotnet.mdx +++ b/platform-includes/logs/setup/dotnet.mdx @@ -84,7 +84,7 @@ SentrySdk.Init(options => builder.Logging.AddSentry(); ``` -Apps on the .NET Generic Host, such as worker services, use `UseSentry` from the `Sentry.Extensions.Hosting` package instead. +Apps on the .NET Generic Host, such as worker services, use `UseSentry` from the `Sentry.Extensions.Hosting` package instead, and set `EnableLogs = true` to send their `ILogger` entries as logs. diff --git a/platform-includes/logs/usage/dotnet.mdx b/platform-includes/logs/usage/dotnet.mdx index 3aed820772a0bd..84f61fedc237cc 100644 --- a/platform-includes/logs/usage/dotnet.mdx +++ b/platform-includes/logs/usage/dotnet.mdx @@ -1,4 +1,4 @@ - + Once the SDK is initialized, you can send logs using the `SentrySdk.Logger` APIs. @@ -13,7 +13,7 @@ SentrySdk.Logger.LogError("A {0} log message", "formatted"); - + Once the feature is enabled and the SDK is initialized, you can send logs using instances of the [ILogger](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger-1) interface, resolved through [.NET dependency injection](https://learn.microsoft.com/dotnet/core/extensions/dependency-injection/overview). @@ -145,7 +145,7 @@ Because log4net renders each message before it reaches the appender, structured - + The SDK automatically provides a set of default attributes attached to your logs. Additionally, you can attach custom attributes via a delegate. From 7320c9a71f0169ef9a21d26db3bca955032937ca Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Mon, 2 Nov 2026 13:03:26 +1300 Subject: [PATCH 10/11] docs(dotnet): Document capturing startup crashes with Serilog UseSentry starts Sentry when the host is built, so crashes before then aren't sent. Apps using Serilog's two-stage initialization can also call SentrySdk.Init before creating the builder to send them. Refs getsentry/sentry-dotnet#5844 Co-Authored-By: Claude Opus 5.5 --- .../platforms/dotnet/guides/serilog/index.mdx | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/docs/platforms/dotnet/guides/serilog/index.mdx b/docs/platforms/dotnet/guides/serilog/index.mdx index e8cfcfbb25182a..2656ff3fd98581 100644 --- a/docs/platforms/dotnet/guides/serilog/index.mdx +++ b/docs/platforms/dotnet/guides/serilog/index.mdx @@ -103,6 +103,56 @@ The sink drops log events while Sentry isn't initialized. If a DSN can be found If you don't call it, the sink does this for you once it's running, so only events captured before then miss the properties. +### Capturing Startup Crashes + +`UseSentry` starts Sentry when the host is built or, in ASP.NET Core, when the app starts running. If the app crashes before then, for example while it reads configuration or registers services, the crash isn't sent. + +Apps that use Serilog's [two-stage initialization](https://github.com/serilog/serilog-aspnetcore#two-stage-initialization) log these crashes with a bootstrap logger. To send them to Sentry too, also call `SentrySdk.Init` before you create the builder: + +```csharp {filename:Program.cs} +using Sentry.Serilog; +using Serilog; + +using var sentry = SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; + options.UseSerilog(); +}); + +Log.Logger = new LoggerConfiguration() + .WriteTo.Sentry() + .CreateBootstrapLogger(); + +try +{ + var builder = WebApplication.CreateBuilder(args); + builder.Services.AddSerilog(config => config.WriteTo.Sentry()); + builder.UseSentry(options => + { + options.Dsn = "___PUBLIC_DSN___"; + options.UseSerilog(); + }); + + var app = builder.Build(); + app.Run(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Application terminated unexpectedly"); +} +finally +{ + Log.CloseAndFlush(); +} +``` + +The two initializations don't share anything: + +- `SentrySdk.Init` runs before the app reads `appsettings.json`, so set its DSN in code or with the `SENTRY_DSN` environment variable. +- `UseSentry` doesn't reuse those options. Give it a DSN as well, in its callback or the `Sentry` section, and call `UseSerilog()` again. +- Once `UseSentry` starts Sentry, it replaces the first initialization. Crashes before then are sent with the first initialization's options, such as its release and environment. Breadcrumbs logged before then aren't carried over. +- Crashes after then, such as a port that's already in use, are sent by `UseSentry`. `Log.Fatal` doesn't send them a second time. + ### Options #### MinimumBreadcrumbLevel From 147c6ea1ee85a9e7c5e9b7d997ff7b3336e2ba2c Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 4 Nov 2026 11:25:22 +1300 Subject: [PATCH 11/11] docs(dotnet): Document capturing startup crashes with NLog and log4net As for Serilog: UseSentry starts Sentry when the host is built, so crashes before then aren't sent. Calling SentrySdk.Init before creating the builder, and logging the crash if startup fails, sends them. Refs getsentry/sentry-dotnet#5844 Co-Authored-By: Claude Opus 5.5 --- .../platforms/dotnet/guides/log4net/index.mdx | 45 ++++++++++++++++ docs/platforms/dotnet/guides/nlog/index.mdx | 51 +++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/docs/platforms/dotnet/guides/log4net/index.mdx b/docs/platforms/dotnet/guides/log4net/index.mdx index 238a7ed4acf965..c963aa208978d6 100644 --- a/docs/platforms/dotnet/guides/log4net/index.mdx +++ b/docs/platforms/dotnet/guides/log4net/index.mdx @@ -56,6 +56,51 @@ The appender drops log events while Sentry isn't initialized. If a DSN can be fo +### Capturing Startup Crashes + +`UseSentry` starts Sentry when the host is built or, in ASP.NET Core, when the app starts running. If the app crashes before then, the appender drops the crash. + +To send these crashes, also call `SentrySdk.Init` before you create the builder, and log the crash if startup fails: + +```csharp {filename:Program.cs} +using log4net; + +using var sentry = SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; +}); + +var logger = LogManager.GetLogger(typeof(Program)); + +try +{ + var builder = WebApplication.CreateBuilder(args); + builder.UseSentry(options => + { + options.Dsn = "___PUBLIC_DSN___"; + }); + + var app = builder.Build(); + app.Run(); +} +catch (Exception ex) +{ + logger.Fatal("Application terminated unexpectedly", ex); + throw; +} +finally +{ + LogManager.Shutdown(); +} +``` + +The two initializations don't share anything: + +- `SentrySdk.Init` runs before the app reads `appsettings.json`, so set its DSN in code or with the `SENTRY_DSN` environment variable. +- `UseSentry` doesn't reuse those options. Give it a DSN as well, in its callback or the `Sentry` section. +- Once `UseSentry` starts Sentry, it replaces the first initialization. Crashes before then are sent with the first initialization's options, such as its release and environment. Breadcrumbs logged before then aren't carried over. +- Crashes after then, such as a port that's already in use, are sent by `UseSentry`. `logger.Fatal` doesn't send them a second time. + ### SendIdentity In the example above, the `SendIdentity` flag was switched on. The SDK then will take the log4net `Identity` value and report to Sentry as the user's id. diff --git a/docs/platforms/dotnet/guides/nlog/index.mdx b/docs/platforms/dotnet/guides/nlog/index.mdx index b28a4bd51dbb6f..af6576f3d263de 100644 --- a/docs/platforms/dotnet/guides/nlog/index.mdx +++ b/docs/platforms/dotnet/guides/nlog/index.mdx @@ -121,6 +121,57 @@ The target can also be configured in an `NLog.config` XML file: +### Capturing Startup Crashes + +`UseSentry` starts Sentry when the host is built or, in ASP.NET Core, when the app starts running. If the app crashes before then, for example while it reads configuration or registers services, the crash isn't sent. + +To send these crashes, also call `SentrySdk.Init` before you create the builder, and log the crash if startup fails: + +```csharp {filename:Program.cs} +using NLog; +using NLog.Config; +using NLog.Extensions.Logging; + +using var sentry = SentrySdk.Init(options => +{ + options.Dsn = "___PUBLIC_DSN___"; +}); + +var config = new LoggingConfiguration(); +config.AddSentry(); +LogManager.Configuration = config; +var logger = LogManager.GetCurrentClassLogger(); + +try +{ + var builder = WebApplication.CreateBuilder(args); + builder.Logging.AddNLog(new NLogProviderOptions { ReplaceLoggerFactory = true }); + builder.UseSentry(options => + { + options.Dsn = "___PUBLIC_DSN___"; + }); + + var app = builder.Build(); + app.Run(); +} +catch (Exception ex) +{ + logger.Fatal(ex, "Application terminated unexpectedly"); + throw; +} +finally +{ + LogManager.Shutdown(); +} +``` + +The two initializations don't share anything: + +- `SentrySdk.Init` runs before the app reads `appsettings.json`, so set its DSN in code or with the `SENTRY_DSN` environment variable. +- `UseSentry` doesn't reuse those options. Give it a DSN as well, in its callback or the `Sentry` section. +- Once `UseSentry` starts Sentry, it replaces the first initialization. Crashes before then are sent with the first initialization's options, such as its release and environment. Breadcrumbs logged before then aren't carried over. +- Crashes after then, such as a port that's already in use, are sent by `UseSentry`. `logger.Fatal` doesn't send them a second time. + ### Options #### MinimumBreadcrumbLevel