diff --git a/samples/Sentry.Samples.AspNetCore.NLog/Program.cs b/samples/Sentry.Samples.AspNetCore.NLog/Program.cs index ff0cf7adeb..f871820cb7 100644 --- a/samples/Sentry.Samples.AspNetCore.NLog/Program.cs +++ b/samples/Sentry.Samples.AspNetCore.NLog/Program.cs @@ -2,7 +2,6 @@ using NLog.Config; using NLog.Targets; using NLog.Web; -using Sentry.NLog; // UseSentry below only starts Sentry once the app is running. Initializing it here as well captures crashes during // startup, until UseSentry takes over: https://docs.sentry.io/platforms/dotnet/guides/nlog/#capturing-startup-crashes @@ -15,20 +14,18 @@ #endif }); -// Configure NLog to send logs to Sentry. This only adds the Sentry target: it does not initialize Sentry. -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); +// Configure NLog to send logs to Sentry. This only adds the Sentry target: it does not initialize Sentry. +nlogConfig.AddSentry(options => + { + // Warn and higher are added as breadcrumbs (default is Info) + options.MinimumBreadcrumbLevel = NLog.LogLevel.Warn; + // Error and higher are sent as events (default is Error) + options.MinimumEventLevel = NLog.LogLevel.Error; + // Info and higher are sent as logs (default is Info) + options.MinimumLogLevel = NLog.LogLevel.Info; + }); LogManager.Configuration = nlogConfig; try @@ -54,7 +51,7 @@ app.MapGet("/", (ILogger logger) => { - logger.LogDebug("Below the Sentry rule's minimum level, so not sent to Sentry"); + logger.LogDebug("Below every Sentry 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"); diff --git a/samples/Sentry.Samples.NLog/NLog.config b/samples/Sentry.Samples.NLog/NLog.config index 9e512f40e1..388996132b 100644 --- a/samples/Sentry.Samples.NLog/NLog.config +++ b/samples/Sentry.Samples.NLog/NLog.config @@ -19,7 +19,8 @@ ignoreEventsWithNoException="False" includeEventDataOnBreadcrumbs="False" includeEventPropertiesAsTags="True" - minimumEventLevel="Error"> + minimumEventLevel="Error" + minimumLogLevel="Info"> diff --git a/samples/Sentry.Samples.NLog/Program.cs b/samples/Sentry.Samples.NLog/Program.cs index c2561f69ab..fff6a48411 100644 --- a/samples/Sentry.Samples.NLog/Program.cs +++ b/samples/Sentry.Samples.NLog/Program.cs @@ -119,6 +119,7 @@ private static void UsingCodeConfiguration() options.MinimumBreadcrumbLevel = LogLevel.Debug; // Debug and higher are stored as breadcrumbs (default is Info) options.MinimumEventLevel = LogLevel.Error; // Error and higher are sent as events (default is Error) + options.MinimumLogLevel = LogLevel.Info; // Info and higher are sent as logs (default is Info) options.IncludeEventDataOnBreadcrumbs = true; // Optionally include event properties with breadcrumbs diff --git a/src/Sentry.NLog/ConfigurationExtensions.cs b/src/Sentry.NLog/ConfigurationExtensions.cs index 5fb8e6a3ad..03542ba4b5 100644 --- a/src/Sentry.NLog/ConfigurationExtensions.cs +++ b/src/Sentry.NLog/ConfigurationExtensions.cs @@ -55,6 +55,7 @@ public static LoggingConfiguration AddSentry( /// /// This doesn't initialise Sentry. Initialise Sentry separately, using SentrySdk.Init or another Sentry /// integration (such as ASP.NET Core or MAUI). + /// The rule it adds starts at the lowest of the target's minimum levels. /// /// The NLog configuration. /// An optional action for configuring the Sentry target options. @@ -89,11 +90,17 @@ public static LoggingConfiguration AddSentry( configuration.AddTarget(targetName, target); - configuration.AddRuleForAllLevels(targetName); + configuration.AddRule(LowestMinimumLevel(options), LogLevel.Fatal, targetName); return configuration; } + private static LogLevel LowestMinimumLevel(SentryNLogOptions options) + { + LogLevel?[] levels = [options.MinimumEventLevel, options.MinimumBreadcrumbLevel, options.MinimumLogLevel]; + return levels.OfType().DefaultIfEmpty(LogLevel.Off).Min()!; + } + /// /// Add additional tags that will be sent with every message. /// diff --git a/src/Sentry.NLog/SentryNLogOptions.cs b/src/Sentry.NLog/SentryNLogOptions.cs index 99ec14a79b..d2eaa87abd 100644 --- a/src/Sentry.NLog/SentryNLogOptions.cs +++ b/src/Sentry.NLog/SentryNLogOptions.cs @@ -20,6 +20,11 @@ public class SentryNLogOptions /// public LogLevel? MinimumBreadcrumbLevel { get; set; } = LogLevel.Info; + /// + /// Minimum log level to be sent to Sentry as a structured log. Defaults to . + /// + public LogLevel? MinimumLogLevel { get; set; } = LogLevel.Info; + /// /// Set this to to ignore log messages that don't contain an exception. /// diff --git a/src/Sentry.NLog/SentryTarget.cs b/src/Sentry.NLog/SentryTarget.cs index 29aa61f297..5b5cb43259 100644 --- a/src/Sentry.NLog/SentryTarget.cs +++ b/src/Sentry.NLog/SentryTarget.cs @@ -137,32 +137,34 @@ public string MinimumBreadcrumbLevel set => Options.MinimumBreadcrumbLevel = LogLevel.FromString(value); } - internal const string ObsoleteEnableLogs = - "The Sentry target always sends logs. This option is ignored and will be removed in a future major version. " + - "To drop logs, use SetBeforeSendLog on the options passed to SentrySdk.Init and return null."; + /// + /// Minimum log level to be sent to Sentry as a structured log. Defaults to . + /// + public string MinimumLogLevel + { + get => Options.MinimumLogLevel?.ToString() ?? LogLevel.Off.ToString(); + set => Options.MinimumLogLevel = LogLevel.FromString(value); + } - internal const string EnableLogsFalseIgnored = - "The Sentry target always sends logs, so enableLogs=\"false\" no longer turns them off. " + - "Remove enableLogs from the target configuration. " + - "To drop logs, use SetBeforeSendLog on the options passed to SentrySdk.Init and return null."; + internal const string ObsoleteEnableLogs = + "Use MinimumLogLevel instead. Setting this to false is the same as setting MinimumLogLevel to Off. " + + "This option will be removed in a future major version."; /// - /// Logs are always generated and sent. + /// Setting this to sets to Off. /// /// - /// This option no longer has any effect. The getter always returns . - /// Setting it to only writes a warning to standard error. - /// To filter or drop logs, use and return . + /// Setting it to has no effect. Use instead. /// [Obsolete(ObsoleteEnableLogs)] public bool EnableLogs { - get => true; + get => Options.MinimumLogLevel is { } level && level != LogLevel.Off; set { if (!value) { - WriteToStandardError("Sentry: " + EnableLogsFalseIgnored); + Options.MinimumLogLevel = LogLevel.Off; } } } @@ -253,6 +255,9 @@ protected override void FlushAsync(AsyncContinuation asyncContinuation) /// as a breadcrumb to the Sentry Sdk. /// /// + /// If the event level is >= the , the event is sent as a structured log. + /// + /// /// If sentry is not enabled, this is a No-op. /// /// @@ -337,7 +342,7 @@ private void InnerWrite(LogEventInfo logEvent) } var sentryOptions = hub.GetSentryOptions(); - if (sentryOptions is not null) + if (sentryOptions is not null && logEvent.Level >= Options.MinimumLogLevel) { try { diff --git a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt index 898643e61a..76f89570ec 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt @@ -28,6 +28,7 @@ namespace Sentry.NLog public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } + public NLog.LogLevel? MinimumLogLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] @@ -54,9 +55,8 @@ namespace Sentry.NLog public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } [System.Obsolete(@"The Sentry target no longer initializes the SDK, so a DSN can no longer be supplied to it. Initialize Sentry with SentrySdk.Init (or UseSentry via one of the integrations), and remove 'dsn', 'initializeSdk' and any other core SDK settings from the target configuration.", true)] public NLog.Layouts.Layout? Dsn { get; set; } - [System.Obsolete("The Sentry target always sends logs. This option is ignored and will be removed i" + - "n a future major version. To drop logs, use SetBeforeSendLog on the options pass" + - "ed to SentrySdk.Init and return null.")] + [System.Obsolete("Use MinimumLogLevel instead. Setting this to false is the same as setting Minimum" + + "LogLevel to Off. This option will be removed in a future major version.")] public bool EnableLogs { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } @@ -65,6 +65,7 @@ namespace Sentry.NLog public bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } + public string MinimumLogLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } diff --git a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt index 898643e61a..76f89570ec 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt @@ -28,6 +28,7 @@ namespace Sentry.NLog public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } + public NLog.LogLevel? MinimumLogLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] @@ -54,9 +55,8 @@ namespace Sentry.NLog public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } [System.Obsolete(@"The Sentry target no longer initializes the SDK, so a DSN can no longer be supplied to it. Initialize Sentry with SentrySdk.Init (or UseSentry via one of the integrations), and remove 'dsn', 'initializeSdk' and any other core SDK settings from the target configuration.", true)] public NLog.Layouts.Layout? Dsn { get; set; } - [System.Obsolete("The Sentry target always sends logs. This option is ignored and will be removed i" + - "n a future major version. To drop logs, use SetBeforeSendLog on the options pass" + - "ed to SentrySdk.Init and return null.")] + [System.Obsolete("Use MinimumLogLevel instead. Setting this to false is the same as setting Minimum" + + "LogLevel to Off. This option will be removed in a future major version.")] public bool EnableLogs { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } @@ -65,6 +65,7 @@ namespace Sentry.NLog public bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } + public string MinimumLogLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } diff --git a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt index 898643e61a..76f89570ec 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt @@ -28,6 +28,7 @@ namespace Sentry.NLog public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } + public NLog.LogLevel? MinimumLogLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] @@ -54,9 +55,8 @@ namespace Sentry.NLog public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } [System.Obsolete(@"The Sentry target no longer initializes the SDK, so a DSN can no longer be supplied to it. Initialize Sentry with SentrySdk.Init (or UseSentry via one of the integrations), and remove 'dsn', 'initializeSdk' and any other core SDK settings from the target configuration.", true)] public NLog.Layouts.Layout? Dsn { get; set; } - [System.Obsolete("The Sentry target always sends logs. This option is ignored and will be removed i" + - "n a future major version. To drop logs, use SetBeforeSendLog on the options pass" + - "ed to SentrySdk.Init and return null.")] + [System.Obsolete("Use MinimumLogLevel instead. Setting this to false is the same as setting Minimum" + + "LogLevel to Off. This option will be removed in a future major version.")] public bool EnableLogs { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } @@ -65,6 +65,7 @@ namespace Sentry.NLog public bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } + public string MinimumLogLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } diff --git a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt index 898643e61a..76f89570ec 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt @@ -28,6 +28,7 @@ namespace Sentry.NLog public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } + public NLog.LogLevel? MinimumLogLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] @@ -54,9 +55,8 @@ namespace Sentry.NLog public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } [System.Obsolete(@"The Sentry target no longer initializes the SDK, so a DSN can no longer be supplied to it. Initialize Sentry with SentrySdk.Init (or UseSentry via one of the integrations), and remove 'dsn', 'initializeSdk' and any other core SDK settings from the target configuration.", true)] public NLog.Layouts.Layout? Dsn { get; set; } - [System.Obsolete("The Sentry target always sends logs. This option is ignored and will be removed i" + - "n a future major version. To drop logs, use SetBeforeSendLog on the options pass" + - "ed to SentrySdk.Init and return null.")] + [System.Obsolete("Use MinimumLogLevel instead. Setting this to false is the same as setting Minimum" + + "LogLevel to Off. This option will be removed in a future major version.")] public bool EnableLogs { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } @@ -65,6 +65,7 @@ namespace Sentry.NLog public bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } + public string MinimumLogLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } diff --git a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.Net4_8.verified.txt b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.Net4_8.verified.txt index 898643e61a..76f89570ec 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.Net4_8.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.Net4_8.verified.txt @@ -28,6 +28,7 @@ namespace Sentry.NLog public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } + public NLog.LogLevel? MinimumLogLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] @@ -54,9 +55,8 @@ namespace Sentry.NLog public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } [System.Obsolete(@"The Sentry target no longer initializes the SDK, so a DSN can no longer be supplied to it. Initialize Sentry with SentrySdk.Init (or UseSentry via one of the integrations), and remove 'dsn', 'initializeSdk' and any other core SDK settings from the target configuration.", true)] public NLog.Layouts.Layout? Dsn { get; set; } - [System.Obsolete("The Sentry target always sends logs. This option is ignored and will be removed i" + - "n a future major version. To drop logs, use SetBeforeSendLog on the options pass" + - "ed to SentrySdk.Init and return null.")] + [System.Obsolete("Use MinimumLogLevel instead. Setting this to false is the same as setting Minimum" + + "LogLevel to Off. This option will be removed in a future major version.")] public bool EnableLogs { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } @@ -65,6 +65,7 @@ namespace Sentry.NLog public bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } + public string MinimumLogLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } diff --git a/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs b/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs index 4a1efcb3a9..ab78b64d58 100644 --- a/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs +++ b/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs @@ -24,6 +24,45 @@ public void AddSentry_TargetName_TargetNamed() Assert.Equal("custom", actual.AllTargets[0].Name); } + [Fact] + public void AddSentry_DefaultOptions_RuleStartsAtInfo() + { + var actual = new LoggingConfiguration().AddSentry(); + + Assert.Equal(new[] { LogLevel.Info, LogLevel.Warn, LogLevel.Error, LogLevel.Fatal }, + Assert.Single(actual.LoggingRules).Levels); + } + + [Theory] + [InlineData("Trace", "Info", "Info", "Trace")] + [InlineData("Info", "Debug", "Info", "Debug")] + [InlineData("Info", "Info", "Trace", "Trace")] + [InlineData("Off", "Off", "Warn", "Warn")] + public void AddSentry_RuleStartsAtLowestMinimumLevel(string eventLevel, string breadcrumbLevel, string logLevel, string expected) + { + var actual = new LoggingConfiguration().AddSentry(o => + { + o.MinimumEventLevel = LogLevel.FromString(eventLevel); + o.MinimumBreadcrumbLevel = LogLevel.FromString(breadcrumbLevel); + o.MinimumLogLevel = LogLevel.FromString(logLevel); + }); + + Assert.Equal(LogLevel.FromString(expected), Assert.Single(actual.LoggingRules).Levels.Min()); + } + + [Fact] + public void AddSentry_AllMinimumLevelsNull_RuleHasNoLevels() + { + var actual = new LoggingConfiguration().AddSentry(o => + { + o.MinimumEventLevel = null; + o.MinimumBreadcrumbLevel = null; + o.MinimumLogLevel = null; + }); + + Assert.Empty(Assert.Single(actual.LoggingRules).Levels); + } + [Fact] public void AddTag_SetToTarget() { diff --git a/test/Sentry.NLog.Tests/SentryNLogOptionsTests.cs b/test/Sentry.NLog.Tests/SentryNLogOptionsTests.cs index 7b13df9a80..4ab91f7b03 100644 --- a/test/Sentry.NLog.Tests/SentryNLogOptionsTests.cs +++ b/test/Sentry.NLog.Tests/SentryNLogOptionsTests.cs @@ -15,4 +15,11 @@ public void Ctor_MinimumEventLevel_Error() var options = new SentryNLogOptions(); Assert.Equal(LogLevel.Error, options.MinimumEventLevel); } + + [Fact] + public void Ctor_MinimumLogLevel_Info() + { + var options = new SentryNLogOptions(); + Assert.Equal(LogLevel.Info, options.MinimumLogLevel); + } } diff --git a/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs b/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs index 8c67671c6c..ee32a0479c 100644 --- a/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs +++ b/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs @@ -123,22 +123,14 @@ public void ReportUnsupportedSdkSetting_BothSettingsOnOneTarget_WritesOnce() Assert.Single(standardError); } - [Fact] - public void EnableLogs_WhenSetToFalse_WritesMessageToStandardError() - { - var standardError = new List(); - - Set(GetTarget(standardError), "EnableLogs", false); - - Assert.Contains(SentryTarget.EnableLogsFalseIgnored, Assert.Single(standardError)); - } - - [Fact] - public void EnableLogs_WhenSetToTrue_WritesNothing() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void EnableLogs_WhenSet_WritesNothing(bool value) { var standardError = new List(); - Set(GetTarget(standardError), "EnableLogs", true); + Set(GetTarget(standardError), "EnableLogs", value); Assert.Empty(standardError); } diff --git a/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs b/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs index 1318e01ef7..3454cf8f41 100644 --- a/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs +++ b/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs @@ -40,6 +40,7 @@ public void Write_StructuredLogging_LogLevel(LogLevel level, SentryLogLevel expe { InMemorySentryStructuredLogger capturer = new(); _fixture.Hub.Logger.Returns(capturer); + _fixture.Options.MinimumLogLevel = LogLevel.Trace; var logger = _fixture.GetLogger(); @@ -48,6 +49,49 @@ public void Write_StructuredLogging_LogLevel(LogLevel level, SentryLogLevel expe capturer.Logs.Should().ContainSingle().Which.Level.Should().Be(expected); } + public static TheoryData MinimumLogLevelData => new() + { + { null, ["Info message"] }, + { "Debug", ["Debug message", "Info message"] }, + { "Warn", [] }, + { "Off", [] }, + }; + + [Theory] + [MemberData(nameof(MinimumLogLevelData))] + public void Write_StructuredLogging_MinimumLogLevel(string? minimumLogLevel, string[] expectedMessages) + { + InMemorySentryStructuredLogger capturer = new(); + _fixture.Hub.Logger.Returns(capturer); + if (minimumLogLevel is not null) + { + _fixture.Options.MinimumLogLevel = LogLevel.FromString(minimumLogLevel); + } + + var logger = _fixture.GetLogger(); + + logger.Debug("Debug message"); + logger.Info("Info message"); + + capturer.Logs.Select(log => log.Message).Should().Equal(expectedMessages); + } + + [Fact] + public void Write_BelowMinimumLogLevel_StillAddsBreadcrumb() + { + InMemorySentryStructuredLogger capturer = new(); + _fixture.Hub.Logger.Returns(capturer); + _fixture.Options.MinimumBreadcrumbLevel = LogLevel.Trace; + _fixture.Options.MinimumLogLevel = LogLevel.Info; + + var logger = _fixture.GetLogger(); + + logger.Trace(DefaultMessage); + + capturer.Logs.Should().BeEmpty(); + _fixture.Scope.Breadcrumbs.Should().ContainSingle().Which.Message.Should().Be(DefaultMessage); + } + [Theory] [InlineData(true)] [InlineData(false)] diff --git a/test/Sentry.NLog.Tests/SentryTargetTests.cs b/test/Sentry.NLog.Tests/SentryTargetTests.cs index 5c92edb16d..bd7626946d 100644 --- a/test/Sentry.NLog.Tests/SentryTargetTests.cs +++ b/test/Sentry.NLog.Tests/SentryTargetTests.cs @@ -75,7 +75,7 @@ public void Can_configure_from_xml_file() - + True @@ -91,10 +91,23 @@ public void Can_configure_from_xml_file() var t = logFactory.Configuration.FindTargetByName("sentry") as SentryTarget; Assert.NotNull(t); Assert.Equal(LogLevel.Warn, t.Options.MinimumEventLevel); + Assert.Equal(LogLevel.Debug, t.Options.MinimumLogLevel); Assert.True(t.Options.IgnoreEventsWithNoException); Assert.True(t.Options.IncludeEventPropertiesAsTags); } + [Theory] + [InlineData("Debug", "Debug")] + [InlineData(null, "Off")] + public void MinimumLogLevel_Get_ReturnsOptionsLevel(string optionsLevel, string expected) + { + _fixture.Options.MinimumLogLevel = optionsLevel is null ? null : LogLevel.FromString(optionsLevel); + + var target = (SentryTarget)_fixture.GetTarget(); + + Assert.Equal(expected, target.MinimumLogLevel); + } + [Fact] public void Can_configure_user_from_xml_file() { @@ -564,7 +577,7 @@ public void MinimumBreadcrumbLevel_SetterReplacesOptions() } [Fact] - public void EnableLogs_IsObsoleteAndAlwaysEnabled() + public void EnableLogs_SetFalse_SetsMinimumLogLevelOff() { var target = (SentryTarget)_fixture.GetTarget(); @@ -573,8 +586,22 @@ public void EnableLogs_IsObsoleteAndAlwaysEnabled() target.EnableLogs = false; - Assert.True(target.EnableLogs); + Assert.False(target.EnableLogs); #pragma warning restore CS0618 + Assert.Equal(LogLevel.Off, target.Options.MinimumLogLevel); + } + + [Fact] + public void EnableLogs_SetTrue_KeepsMinimumLogLevel() + { + _fixture.Options.MinimumLogLevel = LogLevel.Warn; + var target = (SentryTarget)_fixture.GetTarget(); + +#pragma warning disable CS0618 // Type or member is obsolete + target.EnableLogs = true; +#pragma warning restore CS0618 + + Assert.Equal(LogLevel.Warn, target.Options.MinimumLogLevel); } [Fact]