diff --git a/.generated.NoMobile.slnx b/.generated.NoMobile.slnx
index 4a47f6ecab..4742240f65 100644
--- a/.generated.NoMobile.slnx
+++ b/.generated.NoMobile.slnx
@@ -89,6 +89,7 @@
+
diff --git a/Sentry-CI-Build-Linux-NoMobile.slnf b/Sentry-CI-Build-Linux-NoMobile.slnf
index ce4e8725db..1e150ccacc 100644
--- a/Sentry-CI-Build-Linux-NoMobile.slnf
+++ b/Sentry-CI-Build-Linux-NoMobile.slnf
@@ -9,6 +9,7 @@
"samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj",
"samples\\Sentry.Samples.AspNetCore.Grpc\\Sentry.Samples.AspNetCore.Grpc.csproj",
"samples\\Sentry.Samples.AspNetCore.Mvc\\Sentry.Samples.AspNetCore.Mvc.csproj",
+ "samples\\Sentry.Samples.AspNetCore.NLog\\Sentry.Samples.AspNetCore.NLog.csproj",
"samples\\Sentry.Samples.AspNetCore.Serilog\\Sentry.Samples.AspNetCore.Serilog.csproj",
"samples\\Sentry.Samples.AspNetCore.WebAPI.Profiling\\Sentry.Samples.AspNetCore.WebAPI.Profiling.csproj",
"samples\\Sentry.Samples.Aws.Lambda.AspNetCoreServer\\Sentry.Samples.Aws.Lambda.AspNetCoreServer.csproj",
diff --git a/Sentry-CI-Build-Linux.slnf b/Sentry-CI-Build-Linux.slnf
index 843d20b98f..51e1b0f221 100644
--- a/Sentry-CI-Build-Linux.slnf
+++ b/Sentry-CI-Build-Linux.slnf
@@ -10,6 +10,7 @@
"samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj",
"samples\\Sentry.Samples.AspNetCore.Grpc\\Sentry.Samples.AspNetCore.Grpc.csproj",
"samples\\Sentry.Samples.AspNetCore.Mvc\\Sentry.Samples.AspNetCore.Mvc.csproj",
+ "samples\\Sentry.Samples.AspNetCore.NLog\\Sentry.Samples.AspNetCore.NLog.csproj",
"samples\\Sentry.Samples.AspNetCore.Serilog\\Sentry.Samples.AspNetCore.Serilog.csproj",
"samples\\Sentry.Samples.AspNetCore.WebAPI.Profiling\\Sentry.Samples.AspNetCore.WebAPI.Profiling.csproj",
"samples\\Sentry.Samples.Aws.Lambda.AspNetCoreServer\\Sentry.Samples.Aws.Lambda.AspNetCoreServer.csproj",
diff --git a/Sentry-CI-Build-Windows-arm64.slnf b/Sentry-CI-Build-Windows-arm64.slnf
index 164adcf65d..e57d3e4d8b 100644
--- a/Sentry-CI-Build-Windows-arm64.slnf
+++ b/Sentry-CI-Build-Windows-arm64.slnf
@@ -11,6 +11,7 @@
"samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj",
"samples\\Sentry.Samples.AspNetCore.Grpc\\Sentry.Samples.AspNetCore.Grpc.csproj",
"samples\\Sentry.Samples.AspNetCore.Mvc\\Sentry.Samples.AspNetCore.Mvc.csproj",
+ "samples\\Sentry.Samples.AspNetCore.NLog\\Sentry.Samples.AspNetCore.NLog.csproj",
"samples\\Sentry.Samples.AspNetCore.Serilog\\Sentry.Samples.AspNetCore.Serilog.csproj",
"samples\\Sentry.Samples.AspNetCore.WebAPI.Profiling\\Sentry.Samples.AspNetCore.WebAPI.Profiling.csproj",
"samples\\Sentry.Samples.Aws.Lambda.AspNetCoreServer\\Sentry.Samples.Aws.Lambda.AspNetCoreServer.csproj",
diff --git a/Sentry-CI-Build-Windows.slnf b/Sentry-CI-Build-Windows.slnf
index b14e45d2c4..66699079f9 100644
--- a/Sentry-CI-Build-Windows.slnf
+++ b/Sentry-CI-Build-Windows.slnf
@@ -11,6 +11,7 @@
"samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj",
"samples\\Sentry.Samples.AspNetCore.Grpc\\Sentry.Samples.AspNetCore.Grpc.csproj",
"samples\\Sentry.Samples.AspNetCore.Mvc\\Sentry.Samples.AspNetCore.Mvc.csproj",
+ "samples\\Sentry.Samples.AspNetCore.NLog\\Sentry.Samples.AspNetCore.NLog.csproj",
"samples\\Sentry.Samples.AspNetCore.Serilog\\Sentry.Samples.AspNetCore.Serilog.csproj",
"samples\\Sentry.Samples.AspNetCore.WebAPI.Profiling\\Sentry.Samples.AspNetCore.WebAPI.Profiling.csproj",
"samples\\Sentry.Samples.Aws.Lambda.AspNetCoreServer\\Sentry.Samples.Aws.Lambda.AspNetCoreServer.csproj",
diff --git a/Sentry-CI-Build-macOS.slnf b/Sentry-CI-Build-macOS.slnf
index bce6cf8fec..5a418b6c8c 100644
--- a/Sentry-CI-Build-macOS.slnf
+++ b/Sentry-CI-Build-macOS.slnf
@@ -12,6 +12,7 @@
"samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj",
"samples\\Sentry.Samples.AspNetCore.Grpc\\Sentry.Samples.AspNetCore.Grpc.csproj",
"samples\\Sentry.Samples.AspNetCore.Mvc\\Sentry.Samples.AspNetCore.Mvc.csproj",
+ "samples\\Sentry.Samples.AspNetCore.NLog\\Sentry.Samples.AspNetCore.NLog.csproj",
"samples\\Sentry.Samples.AspNetCore.Serilog\\Sentry.Samples.AspNetCore.Serilog.csproj",
"samples\\Sentry.Samples.AspNetCore.WebAPI.Profiling\\Sentry.Samples.AspNetCore.WebAPI.Profiling.csproj",
"samples\\Sentry.Samples.Aws.Lambda.AspNetCoreServer\\Sentry.Samples.Aws.Lambda.AspNetCoreServer.csproj",
diff --git a/Sentry.slnx b/Sentry.slnx
index 4a47f6ecab..4742240f65 100644
--- a/Sentry.slnx
+++ b/Sentry.slnx
@@ -89,6 +89,7 @@
+
diff --git a/SentryAspNetCore.slnf b/SentryAspNetCore.slnf
index ccd8904461..b64b079722 100644
--- a/SentryAspNetCore.slnf
+++ b/SentryAspNetCore.slnf
@@ -7,6 +7,7 @@
"samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj",
"samples\\Sentry.Samples.AspNetCore.Grpc\\Sentry.Samples.AspNetCore.Grpc.csproj",
"samples\\Sentry.Samples.AspNetCore.Mvc\\Sentry.Samples.AspNetCore.Mvc.csproj",
+ "samples\\Sentry.Samples.AspNetCore.NLog\\Sentry.Samples.AspNetCore.NLog.csproj",
"samples\\Sentry.Samples.AspNetCore.Serilog\\Sentry.Samples.AspNetCore.Serilog.csproj",
"samples\\Sentry.Samples.AspNetCore.WebAPI.Profiling\\Sentry.Samples.AspNetCore.WebAPI.Profiling.csproj",
"samples\\Sentry.Samples.Aws.Lambda.AspNetCoreServer\\Sentry.Samples.Aws.Lambda.AspNetCoreServer.csproj",
diff --git a/SentryNoMobile.slnf b/SentryNoMobile.slnf
index 206615ce08..9e2060f47b 100644
--- a/SentryNoMobile.slnf
+++ b/SentryNoMobile.slnf
@@ -9,6 +9,7 @@
"samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj",
"samples\\Sentry.Samples.AspNetCore.Grpc\\Sentry.Samples.AspNetCore.Grpc.csproj",
"samples\\Sentry.Samples.AspNetCore.Mvc\\Sentry.Samples.AspNetCore.Mvc.csproj",
+ "samples\\Sentry.Samples.AspNetCore.NLog\\Sentry.Samples.AspNetCore.NLog.csproj",
"samples\\Sentry.Samples.AspNetCore.Serilog\\Sentry.Samples.AspNetCore.Serilog.csproj",
"samples\\Sentry.Samples.AspNetCore.WebAPI.Profiling\\Sentry.Samples.AspNetCore.WebAPI.Profiling.csproj",
"samples\\Sentry.Samples.Aws.Lambda.AspNetCoreServer\\Sentry.Samples.Aws.Lambda.AspNetCoreServer.csproj",
diff --git a/samples/Sentry.Samples.AspNetCore.NLog/Program.cs b/samples/Sentry.Samples.AspNetCore.NLog/Program.cs
new file mode 100644
index 0000000000..ca75222ccf
--- /dev/null
+++ b/samples/Sentry.Samples.AspNetCore.NLog/Program.cs
@@ -0,0 +1,55 @@
+using NLog;
+using NLog.Config;
+using NLog.Targets;
+using NLog.Web;
+using Sentry.NLog;
+
+// Configure NLog to send logs to Sentry. This only adds the Sentry target: the SDK is initialized by UseSentry below.
+var sentryTarget = new SentryTarget(new SentryNLogOptions
+{
+ // Warn and higher are added as breadcrumbs (default is Info)
+ MinimumBreadcrumbLevel = NLog.LogLevel.Warn,
+ // Error and higher are sent as events (default is Error)
+ MinimumEventLevel = NLog.LogLevel.Error,
+});
+
+var nlogConfig = new LoggingConfiguration();
+nlogConfig.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, new ColoredConsoleTarget("console"));
+// Every entry that reaches the Sentry target is sent as a structured log, so this rule sets the minimum level for logs.
+// Info and higher are sent as logs. Breadcrumbs and events can only use entries that pass this rule.
+nlogConfig.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, sentryTarget);
+LogManager.Configuration = nlogConfig;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Send ILogger entries through NLog. ReplaceLoggerFactory stops the ILogger providers that UseSentry adds from also
+// capturing every entry, so each one reaches Sentry once, through the NLog target, whatever order these calls are in.
+builder.Host.UseNLog(new NLogAspNetCoreOptions { ReplaceLoggerFactory = true });
+
+builder.UseSentry(options =>
+{
+#if !SENTRY_DSN_DEFINED_IN_ENV
+ // A DSN is required. You can set here in code, or you can set it in the SENTRY_DSN environment variable.
+ // See https://docs.sentry.io/product/sentry-basics/dsn-explainer/
+ options.Dsn = SamplesShared.Dsn;
+#else
+ options.Dsn = EnvironmentVariables.Dsn;
+#endif
+});
+
+var app = builder.Build();
+
+app.MapGet("/", (ILogger logger) =>
+{
+ logger.LogDebug("Below the Sentry rule's minimum level, so not sent to Sentry");
+ logger.LogInformation("Sent as a log");
+ logger.LogWarning("Sent as a log and added as a breadcrumb");
+ logger.LogError("Sent as a log and as an event, which includes the breadcrumb above");
+ return "Logged through ILogger at each level. Check Sentry for the logs and the event.";
+});
+
+app.MapGet("/throw", () => { throw new Exception("An exception thrown from the ASP.NET Core pipeline"); });
+
+app.Run();
+
+LogManager.Shutdown();
diff --git a/samples/Sentry.Samples.AspNetCore.NLog/Properties/launchSettings.json b/samples/Sentry.Samples.AspNetCore.NLog/Properties/launchSettings.json
new file mode 100644
index 0000000000..a13893590a
--- /dev/null
+++ b/samples/Sentry.Samples.AspNetCore.NLog/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "Sentry.Samples.AspNetCore.NLog": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:5164"
+ }
+ }
+}
diff --git a/samples/Sentry.Samples.AspNetCore.NLog/Sentry.Samples.AspNetCore.NLog.csproj b/samples/Sentry.Samples.AspNetCore.NLog/Sentry.Samples.AspNetCore.NLog.csproj
new file mode 100644
index 0000000000..629da0c982
--- /dev/null
+++ b/samples/Sentry.Samples.AspNetCore.NLog/Sentry.Samples.AspNetCore.NLog.csproj
@@ -0,0 +1,16 @@
+
+
+
+ net11.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs b/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs
index 7543721fbf..155e2b3ba3 100644
--- a/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs
+++ b/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs
@@ -21,9 +21,9 @@ public static class LoggingBuilderExtensions
/// Adds the Sentry logging integration.
///
///
- /// In an app that calls UseSentry, which already adds the logging integration, this has no effect unless the
- /// app removed Sentry's logger providers, for example with ClearProviders(). It then adds back the providers
- /// that UseSentry added, which use the host's Sentry options.
+ /// Apps that call UseSentry don't need this, because UseSentry already adds the logging integration.
+ /// If your app calls ClearProviders() after calling UseSentry that would also remove Sentry's logging
+ /// integration - in which case this method can be used to add Sentry's providers back again.
///
/// The builder.
public static ILoggingBuilder AddSentry(this ILoggingBuilder builder)
@@ -44,10 +44,10 @@ public static ILoggingBuilder AddSentry(this ILoggingBuilder builder, string dsn
/// Adds the Sentry logging integration.
///
///
- /// In an app that calls UseSentry, which already adds the logging integration, this has no effect unless the
- /// app removed Sentry's logger providers, for example with ClearProviders(). It then adds back the providers
- /// that UseSentry added, which use the host's Sentry options, so is
- /// ignored.
+ /// Apps that call UseSentry don't need this, because UseSentry already adds the logging integration.
+ /// If your app calls ClearProviders() after calling UseSentry that would also remove Sentry's logging
+ /// integration - in which case this method can be used to add Sentry's providers back again. The providers it adds
+ /// back use the host's Sentry options, so is ignored.
///
/// The builder.
/// The options configuration.
diff --git a/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs b/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs
index 817656d5c6..48284d6d7e 100644
--- a/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs
+++ b/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs
@@ -28,10 +28,10 @@ public class SentryLoggingOptions
"logging through the host's Sentry options.";
internal const string HostLoggerProvidersRemoved =
- "Sentry's logger providers were removed after UseSentry added them, for example by ClearProviders(), so log " +
- "entries from ILogger don't reach Sentry. Call AddSentry() on the logging builder after ClearProviders(), " +
- "for example builder.Logging.AddSentry(), to add them back. If you send logs to Sentry through another " +
- "integration, such as NLog, Serilog or log4net, you can ignore this.";
+ "Sentry's logger providers were removed after UseSentry added them, for example by ClearProviders(). If " +
+ "ILogger entries reach Sentry through another integration, such as NLog, Serilog or log4net, this is " +
+ "expected (it prevents duplicates being sent to Sentry). Otherwise if ILogger entries don't reach Sentry, you can " +
+ "call AddSentry() on the logging builder after ClearProviders().";
///
/// Not supported. The logging integration no longer initializes the SDK.