diff --git a/src/Sentry.NLog/SentryTarget.cs b/src/Sentry.NLog/SentryTarget.cs index 596c895d4a..d2a2eaf6c8 100644 --- a/src/Sentry.NLog/SentryTarget.cs +++ b/src/Sentry.NLog/SentryTarget.cs @@ -11,6 +11,7 @@ public sealed partial class SentryTarget : TargetWithContext private readonly ISystemClock _clock; private readonly UninitializedSdkWarning _uninitializedSdkWarning; + private bool _reportedUnsupportedSdkSetting; internal static readonly string AdditionalGroupingKeyProperty = "AdditionalGroupingKey"; @@ -76,7 +77,7 @@ internal SentryTarget( public Layout? Dsn { get => null; - set => throw new NotSupportedException(ConfigurationExtensions.ObsoleteDsnOverload); + set => throw ReportUnsupportedSdkSetting(); } /// @@ -87,7 +88,13 @@ public Layout? Dsn public bool InitializeSdk { get => false; - set => throw new NotSupportedException(ConfigurationExtensions.ObsoleteDsnOverload); + set + { + if (value) + { + throw ReportUnsupportedSdkSetting(); + } + } } /// @@ -181,6 +188,18 @@ public SentryNLogUser? User set => Options.User = value; } + // NLog discards the exception unless throwConfigExceptions is on. Report once: a v6 config may set both. + private NotSupportedException ReportUnsupportedSdkSetting() + { + if (!_reportedUnsupportedSdkSetting) + { + _reportedUnsupportedSdkSetting = true; + _uninitializedSdkWarning.WriteToStandardError("Sentry: " + ConfigurationExtensions.ObsoleteDsnOverload); + } + + return new NotSupportedException(ConfigurationExtensions.ObsoleteDsnOverload); + } + /// protected override void InitializeTarget() { diff --git a/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs b/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs index a25df0ed93..b367f2b9e4 100644 --- a/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs +++ b/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs @@ -33,6 +33,12 @@ public void LoadConfiguration_WithTargetSettings_DoesNotThrow() Assert.Null(LoadConfiguration("minimumEventLevel='Warn' includeEventPropertiesAsTags='true'")); } + [Fact] + public void LoadConfiguration_WithInitializeSdkFalse_DoesNotThrow() + { + Assert.Null(LoadConfiguration("initializeSdk='false'")); + } + [Theory] [InlineData(2)] [InlineData(3)] @@ -67,6 +73,55 @@ public void AddSentry_DsnOverload_IsObsoleteAsError(int parameterCount) Assert.True(obsolete!.IsError); } + [Fact] + public void Dsn_WhenSet_WritesMigrationMessageToStandardError() + { + var standardError = new List(); + + Set(GetTarget(standardError), "Dsn", (Layout)ValidDsn); + + Assert.Contains(ConfigurationExtensions.ObsoleteDsnOverload, Assert.Single(standardError)); + } + + [Fact] + public void InitializeSdk_WhenSetToTrue_WritesMigrationMessageToStandardError() + { + var standardError = new List(); + + Set(GetTarget(standardError), "InitializeSdk", true); + + Assert.Contains(ConfigurationExtensions.ObsoleteDsnOverload, Assert.Single(standardError)); + } + + [Fact] + public void InitializeSdk_WhenSetToFalse_WritesNothing() + { + var standardError = new List(); + + Set(GetTarget(standardError), "InitializeSdk", false); + + Assert.Empty(standardError); + } + + [Fact] + public void ReportUnsupportedSdkSetting_BothSettingsOnOneTarget_WritesOnce() + { + var standardError = new List(); + var target = GetTarget(standardError); + + Set(target, "Dsn", (Layout)ValidDsn); + Set(target, "InitializeSdk", true); + + Assert.Single(standardError); + } + + private static SentryTarget GetTarget(List standardError) => + new(new SentryNLogOptions(), () => Substitute.For(), new MockClock(), + new UninitializedSdkWarning { WriteToStandardError = standardError.Add }); + + private static void Set(SentryTarget target, string property, object value) => + Record.Exception(() => typeof(SentryTarget).GetProperty(property)!.SetValue(target, value)); + private static MethodInfo DsnOverload(int parameterCount) => typeof(ConfigurationExtensions) .GetMethods(BindingFlags.Public | BindingFlags.Static) .Single(m => m.Name == nameof(ConfigurationExtensions.AddSentry)