diff --git a/samples/Sentry.Samples.NLog/NLog.config b/samples/Sentry.Samples.NLog/NLog.config index 5022aa23bb..9e512f40e1 100644 --- a/samples/Sentry.Samples.NLog/NLog.config +++ b/samples/Sentry.Samples.NLog/NLog.config @@ -10,11 +10,8 @@ - - + - - - diff --git a/samples/Sentry.Samples.NLog/Program.cs b/samples/Sentry.Samples.NLog/Program.cs index 93d1a56397..c2561f69ab 100644 --- a/samples/Sentry.Samples.NLog/Program.cs +++ b/samples/Sentry.Samples.NLog/Program.cs @@ -12,6 +12,18 @@ public static class Program private static void Main() { + // Initialise the Sentry SDK + using var _ = SentrySdk.Init(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; +#endif + options.AttachStacktrace = true; + options.SendDefaultPii = true; // Send Personal Identifiable information like the username of the user logged in to the device + }); + try { // You can configure your logger using a configuration file: @@ -97,28 +109,18 @@ private static void UsingNLogConfigFile() private static void UsingCodeConfiguration() { - // Other overloads exist, for example, configure the SDK with only the DSN or no parameters at all. + // Configure NLog to send logs to Sentry var config = LogManager.Configuration = new LoggingConfiguration(); _ = config .AddSentry(options => { -#if !SENTRY_DSN_DEFINED_IN_ENV - // A DSN is required. You can set here in code, in the SENTRY_DSN environment variable or in the - // NLog.config file. - // See https://docs.sentry.io/product/sentry-basics/dsn-explainer/ - options.Dsn = SamplesShared.Dsn; -#endif options.Layout = "${message}"; options.BreadcrumbLayout = "${logger}: ${message}"; // Optionally specify a separate format for breadcrumbs options.MinimumBreadcrumbLevel = LogLevel.Debug; // Debug and higher are stored as breadcrumbs (default is Info) - options.MinimumEventLevel = LogLevel.Error; // Error and higher is sent as event (default is Error) - - options.AttachStacktrace = true; - options.SendDefaultPii = true; // Send Personal Identifiable information like the username of the user logged in to the device + options.MinimumEventLevel = LogLevel.Error; // Error and higher are sent as events (default is Error) options.IncludeEventDataOnBreadcrumbs = true; // Optionally include event properties with breadcrumbs - options.ShutdownTimeoutSeconds = 5; //Optionally specify user properties via NLog (here using MappedDiagnosticsLogicalContext as an example) options.User = new SentryNLogUser @@ -134,8 +136,6 @@ private static void UsingCodeConfiguration() }; options.AddTag("logger", "${logger}"); // Send the logger name as a tag - - // Other configuration }); config.AddTarget(new DebuggerTarget("debugger")); diff --git a/samples/Sentry.Samples.NLog/README.md b/samples/Sentry.Samples.NLog/README.md index 6cf4e027d2..78c1932a77 100644 --- a/samples/Sentry.Samples.NLog/README.md +++ b/samples/Sentry.Samples.NLog/README.md @@ -2,20 +2,17 @@ This is a simple console application that demonstrates how you can add Sentry to your application using NLog. -This project attempts to sample the integration by using code only and also via the configuration file. -In both cases **you need to add your own DSN** so you can see the events sent in your Sentry project. +This project demonstrates configuring Sentry and NLog via code and configuration. +The Sentry target configures NLog to send logs to Sentry. The Sentry SDK itself is initialised via the call to `SentrySdk.Init` +in `Program.cs`, so **you need to add your own DSN** there to see the events sent in your Sentry project. You can get your [Sentry DSN at sentry.io](https://sentry.io). -Make sure to add it to both `NLog.config` and `Program.cs` in this directory. ## Configuration of NLog.config The following options are available for the NLog Sentry Target: ```xml - - ``` -* **dsn** - Sentry Data Source Name Address. See also https://sentry.io -* **initializeSdk** - Whether the NLog target should initialize the Sentry SDK (Using Dsn). Default: _True_ -* **environment** - Application Environment sent to Sentry -* **release** - Application Release Version sent to Sentry * **layout** - NLog Layout for rendering SentryEvent message. Default: _${message}_ * **includeEventProperties** - Include LogEvent properties as Data on SentryEvent. Default: _True_ * **includeEventPropertiesAsTags** - Include LogEvent properties as extra Tags on SentryEvent. Default: _False_ @@ -61,17 +46,12 @@ The following options are available for the NLog Sentry Target: * **minimumEventLevel** - Send NLog LogEvents as SentryEvent when matching severity (or worse). Default: _Error_ * **minimumBreadcrumbLevel** - Send NLog LogEvents as Breadcrumbs when matching severity (or worse). Default: _Info_ * **ignoreEventsWithNoException** - Ignore NLog LogEvents without an exception. Default: _False_ -* **flushTimeoutSeconds** - Flush timeout in seconds before aborting flush to Sentry. Default: _15_ * **user** * **id** * **username** * **email** * **ipAddress** * **other** - Any arbitrary key-value pairs to be included as properties for a user on every event. -* **options** - * **sendDefaultPii** - Whether to include default Personal Identifiable information (UserName / IP-Address). Default: _False_ - * **isEnvironmentUser** - Lookup Environment.User if having enabled **sendDefaultPii**. Default: _True_ - * **attachStacktrace** - Whether to send the stack trace of a event captured without an exception. Default: _False_ There is filtering logic in the Sentry Target that is usually handled by NLog Logging Rules and Filters. Mostly because the same Sentry Target is writing both breadcrumbs and actual SentryEvents. diff --git a/src/Sentry.NLog/ConfigurationExtensions.cs b/src/Sentry.NLog/ConfigurationExtensions.cs index 596fb9bca0..5fb8e6a3ad 100644 --- a/src/Sentry.NLog/ConfigurationExtensions.cs +++ b/src/Sentry.NLog/ConfigurationExtensions.cs @@ -12,66 +12,58 @@ public static class ConfigurationExtensions // Internal for testability internal const string DefaultTargetName = "sentry"; + internal const string ObsoleteDsnOverload = + "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."; + /// - /// Adds a target for Sentry to the NLog configuration. + /// Not supported. The Sentry target no longer initializes the SDK. /// - /// - /// If DSN is not set, the SDK will look for an environment variable called SENTRY_DSN. If nothing is - /// found, SDK is disabled. - /// /// The NLog configuration. + /// No longer supported. /// An optional action for configuring the Sentry target options. - /// The configuration. + /// Never returns. + /// Always. + [Obsolete(ObsoleteDsnOverload, error: true)] public static LoggingConfiguration AddSentry( this LoggingConfiguration configuration, + string? dsn, Action? optionsConfig = null) - { - // Not to throw on code that ignores nullability warnings. - if (configuration.IsNull()) - { - return configuration!; - } - - return configuration.AddSentry(null, DefaultTargetName, optionsConfig); - } + => throw new NotSupportedException(ObsoleteDsnOverload); /// - /// Adds a target for Sentry to the NLog configuration. + /// Not supported. The Sentry target no longer initializes the SDK. /// /// The NLog configuration. - /// - /// The sentry DSN. If DSN is not set, the SDK will look for an environment variable called SENTRY_DSN. - /// If nothing is found, SDK is disabled. - /// + /// No longer supported. + /// The name to give the new target. /// An optional action for configuring the Sentry target options. - /// The configuration. + /// Never returns. + /// Always. + [Obsolete(ObsoleteDsnOverload, error: true)] public static LoggingConfiguration AddSentry( this LoggingConfiguration configuration, string? dsn, + string targetName, Action? optionsConfig = null) - { - // Not to throw on code that ignores nullability warnings. - if (configuration.IsNull()) - { - return configuration!; - } - - return configuration.AddSentry(dsn, DefaultTargetName, optionsConfig); - } + => throw new NotSupportedException(ObsoleteDsnOverload); /// /// Adds a target for Sentry to the NLog configuration. /// + /// + /// This doesn't initialise Sentry. Initialise Sentry separately, using SentrySdk.Init or another Sentry + /// integration (such as ASP.NET Core or MAUI). + /// /// The NLog configuration. - /// The sentry DSN. - /// The name to give the new target. /// An optional action for configuring the Sentry target options. + /// The name to give the new target. /// The configuration. public static LoggingConfiguration AddSentry( this LoggingConfiguration configuration, - string? dsn, - string targetName, - Action? optionsConfig = null) + Action? optionsConfig = null, + string targetName = DefaultTargetName) { // Not to throw on code that ignores nullability warnings. if (configuration.IsNull()) @@ -95,11 +87,6 @@ public static LoggingConfiguration AddSentry( Layout = "${message}", }; - if (dsn != null && string.IsNullOrWhiteSpace(options.Dsn)) - { - options.Dsn = dsn; - } - configuration.AddTarget(targetName, target); configuration.AddRuleForAllLevels(targetName); diff --git a/src/Sentry.NLog/Constants.cs b/src/Sentry.NLog/Constants.cs deleted file mode 100644 index 65df808c29..0000000000 --- a/src/Sentry.NLog/Constants.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Sentry.NLog; - -/// -/// NLog Constant Values. -/// -internal static class Constants -{ - /// - /// NLog SDK name - /// - public const string SdkName = "sentry.dotnet.nlog"; -} diff --git a/src/Sentry.NLog/NLogDiagnosticLogger.cs b/src/Sentry.NLog/NLogDiagnosticLogger.cs deleted file mode 100644 index 493b8ff6a7..0000000000 --- a/src/Sentry.NLog/NLogDiagnosticLogger.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace Sentry.NLog; - -internal class NLogDiagnosticLogger : IDiagnosticLogger -{ - private readonly IDiagnosticLogger? _extraLogger; - - public NLogDiagnosticLogger(IDiagnosticLogger? extraLogger = null) - { - if (!InternalLogger.LogToConsole || extraLogger is not ConsoleDiagnosticLogger) - { - _extraLogger = extraLogger; - } - } - - public bool IsEnabled(SentryLevel level) - { - if (_extraLogger?.IsEnabled(level) == true) - { - return true; - } - - return level switch - { - SentryLevel.Fatal => InternalLogger.IsFatalEnabled, - SentryLevel.Error => InternalLogger.IsErrorEnabled, - SentryLevel.Warning => InternalLogger.IsWarnEnabled, - SentryLevel.Info => InternalLogger.IsInfoEnabled, - _ => InternalLogger.IsDebugEnabled - }; - } - - public void Log(SentryLevel logLevel, string message, Exception? exception = null, params object?[] args) - { - switch (logLevel) - { - case SentryLevel.Fatal: - InternalLogger.Fatal(exception, message, args); - break; - case SentryLevel.Error: - InternalLogger.Error(exception, message, args); - break; - case SentryLevel.Warning: - InternalLogger.Warn(exception, message, args); - break; - case SentryLevel.Info: - InternalLogger.Info(exception, message, args); - break; - default: - InternalLogger.Debug(exception, message, args); - break; - } - - if (_extraLogger?.IsEnabled(logLevel) == true) - { - _extraLogger.Log(logLevel, message, exception, args); - } - } -} diff --git a/src/Sentry.NLog/Sentry.NLog.csproj b/src/Sentry.NLog/Sentry.NLog.csproj index 66aa9ef4b2..c1834bcaac 100644 --- a/src/Sentry.NLog/Sentry.NLog.csproj +++ b/src/Sentry.NLog/Sentry.NLog.csproj @@ -28,6 +28,7 @@ + diff --git a/src/Sentry.NLog/SentryNLogOptions.cs b/src/Sentry.NLog/SentryNLogOptions.cs index e273fb3ddf..99ec14a79b 100644 --- a/src/Sentry.NLog/SentryNLogOptions.cs +++ b/src/Sentry.NLog/SentryNLogOptions.cs @@ -1,29 +1,15 @@ namespace Sentry.NLog; /// -/// Sentry Options for NLog logging. All properties can be configured via code or in NLog.config xml file. +/// Options for the Sentry target for NLog. All properties can be configured via code or the NLog.config file. /// -/// +/// +/// These options only configure the target. The Sentry SDK itself is configured and initialised separately, using +/// SentrySdk.Init or another Sentry integration (such as ASP.NET Core or MAUI). +/// [NLogConfigurationItem] -public class SentryNLogOptions : SentryOptions +public class SentryNLogOptions { - /// - public SentryNLogOptions() - { - // NLog's default flush timeout is 15 seconds, so we will do the same. - FlushTimeout = TimeSpan.FromSeconds(15); - } - - /// - /// How many seconds to wait after triggering before just shutting down the - /// Sentry sdk. - /// - public int ShutdownTimeoutSeconds - { - get => (int)ShutdownTimeout.TotalSeconds; - set => ShutdownTimeout = TimeSpan.FromSeconds(value); - } - /// /// Minimum log level for events to trigger a send to Sentry. Defaults to . /// @@ -68,39 +54,12 @@ public int ShutdownTimeoutSeconds [NLogConfigurationIgnoreProperty] // Configure this directly on the target in XML config. public Layout? Layout { get; set; } - /// - /// Configured layout for Dsn-Address to Sentry - /// - [NLogConfigurationIgnoreProperty] // Configure this directly on the target in XML config. - public Layout? DsnLayout { get; set; } - - /// - /// Configured layout for application Release version to Sentry - /// - [NLogConfigurationIgnoreProperty] // Configure this directly on the target in XML config. - public Layout? ReleaseLayout { get; set; } - - /// - /// Configured layout for application Environment to Sentry - /// - [NLogConfigurationIgnoreProperty] // Configure this directly on the target in XML config. - public Layout? EnvironmentLayout { get; set; } - /// /// Any additional tags to apply to each logged message. /// [NLogConfigurationIgnoreProperty] // Configure this directly on the target in XML config. public IList Tags { get; } = new List(); - /// - /// Whether the NLog integration should initialize the SDK. - /// - /// - /// By default, if a DSN is provided to the NLog integration it will initialize the SDK. - /// This might be not ideal when using multiple integrations in case you want another one doing the Init. - /// - public bool InitializeSdk { get; set; } = true; - /// /// Optionally configure one or more parts of the user information to be rendered dynamically from an NLog layout /// diff --git a/src/Sentry.NLog/SentryTarget.Structured.cs b/src/Sentry.NLog/SentryTarget.Structured.cs index 66de2c3b4d..d8f7c96e98 100644 --- a/src/Sentry.NLog/SentryTarget.Structured.cs +++ b/src/Sentry.NLog/SentryTarget.Structured.cs @@ -15,7 +15,7 @@ private static void CaptureStructuredLog(IHub hub, SentryOptions options, LogEve var log = SentryLog.Create(hub, timestamp, level, logEvent.FormattedMessage, logEvent.Message, parameters); var scope = hub.GetScope(); - log.SetDefaultAttributes(options, scope, Sdk); + log.SetDefaultAttributes(options, scope); log.SetOrigin("auto.log.nlog"); if (logEvent.LoggerName is not null) diff --git a/src/Sentry.NLog/SentryTarget.cs b/src/Sentry.NLog/SentryTarget.cs index 666db15264..d2a2eaf6c8 100644 --- a/src/Sentry.NLog/SentryTarget.cs +++ b/src/Sentry.NLog/SentryTarget.cs @@ -10,19 +10,16 @@ public sealed partial class SentryTarget : TargetWithContext internal Func HubAccessor { get; } private readonly ISystemClock _clock; - private IDisposable? _sdkDisposable; - - internal static readonly SdkVersion NameAndVersion = typeof(SentryTarget).Assembly.GetNameAndVersion(); - - private static readonly SdkVersion Sdk = new() - { - Name = Constants.SdkName, - Version = NameAndVersion.Version, - }; + private readonly UninitializedSdkWarning _uninitializedSdkWarning; + private bool _reportedUnsupportedSdkSetting; internal static readonly string AdditionalGroupingKeyProperty = "AdditionalGroupingKey"; - private static readonly string ProtocolPackageName = "nuget:" + NameAndVersion.Name; + internal const string UninitializedSdkMessage = + "Sentry: the Sentry target for NLog dropped a log event because Sentry is not initialized, but a DSN " + + "was found in the environment or in an assembly attribute. The target no longer initializes the SDK: " + + "call SentrySdk.Init (or UseSentry via one of the integrations) at startup. " + + "See https://docs.sentry.io/platforms/dotnet/guides/nlog/"; /// /// Creates a new instance of . @@ -38,31 +35,31 @@ public SentryTarget(SentryNLogOptions options) : this( options, () => HubAdapter.Instance, - null, SystemClock.Clock) { } - internal SentryTarget(SentryNLogOptions options, Func hubAccessor, IDisposable? sdkInstance, ISystemClock clock) + internal SentryTarget( + SentryNLogOptions options, + Func hubAccessor, + ISystemClock clock, + UninitializedSdkWarning? uninitializedSdkWarning = null) { Options = options; HubAccessor = hubAccessor; _clock = clock; + _uninitializedSdkWarning = uninitializedSdkWarning + ?? new UninitializedSdkWarning(message => InternalLogger.Warn("{0}", message)); // Overrides default layout. Still will be explicitly overwritten if manually configured in the // NLog.config file. Layout = "${message}"; BreadcrumbCategory = Options.BreadcrumbCategoryLayout ?? "${logger}"; IncludeEventProperties = true; - - if (sdkInstance != null) - { - _sdkDisposable = sdkInstance; - } } /// - /// Options for both the and the sentry sdk itself. + /// Options for the . /// public SentryNLogOptions Options { get; } @@ -73,30 +70,31 @@ internal SentryTarget(SentryNLogOptions options, Func hubAccessor, IDispos public IList Tags => Options.Tags; /// - /// Configured layout for Data Source Name of a given project in Sentry + /// Not supported. The Sentry target no longer initializes the SDK. /// + /// When set. + [Obsolete(ConfigurationExtensions.ObsoleteDsnOverload, error: true)] public Layout? Dsn { - get => Options.DsnLayout; - set => Options.DsnLayout = value; + get => null; + set => throw ReportUnsupportedSdkSetting(); } /// - /// Configured layout for application Release version to Sentry + /// Not supported. The Sentry target no longer initializes the SDK. /// - public Layout? Release - { - get => Options.ReleaseLayout; - set => Options.ReleaseLayout = value; - } - - /// - /// Configured layout for application Environment to Sentry - /// - public Layout? Environment + /// When set. + [Obsolete(ConfigurationExtensions.ObsoleteDsnOverload, error: true)] + public bool InitializeSdk { - get => Options.EnvironmentLayout; - set => Options.EnvironmentLayout = value; + get => false; + set + { + if (value) + { + throw ReportUnsupportedSdkSetting(); + } + } } /// @@ -152,19 +150,6 @@ public bool EnableLogs } } - /// - /// Whether the NLog integration should initialize the SDK. - /// - /// - /// By default, if a DSN is provided to the NLog integration it will initialize the SDK. - /// This might be not ideal when using multiple integrations in case you want another one doing the Init. - /// - public bool InitializeSdk - { - get => Options.InitializeSdk; - set => Options.InitializeSdk = value; - } - /// /// Set this to to ignore log messages that don't contain an exception. /// @@ -194,25 +179,6 @@ public bool IncludeEventDataOnBreadcrumbs set => Options.IncludeEventDataOnBreadcrumbs = value; } - /// - /// How many seconds to wait after triggering before just shutting down the - /// Sentry sdk. - /// - public int ShutdownTimeoutSeconds - { - get => Options.ShutdownTimeoutSeconds; - set => Options.ShutdownTimeoutSeconds = value; - } - - /// - /// How long to wait for the flush to finish, in seconds. Defaults to 2 seconds. - /// - public int FlushTimeoutSeconds - { - get => (int)Options.FlushTimeout.TotalSeconds; - set => Options.FlushTimeout = TimeSpan.FromSeconds(value); - } - /// /// Optionally configure one or more parts of the user information to be rendered dynamically from an NLog layout /// @@ -222,11 +188,16 @@ public SentryNLogUser? User set => Options.User = value; } - /// - protected override void CloseTarget() + // NLog discards the exception unless throwConfigExceptions is on. Report once: a v6 config may set both. + private NotSupportedException ReportUnsupportedSdkSetting() { - _sdkDisposable?.Dispose(); - base.CloseTarget(); + if (!_reportedUnsupportedSdkSetting) + { + _reportedUnsupportedSdkSetting = true; + _uninitializedSdkWarning.WriteToStandardError("Sentry: " + ConfigurationExtensions.ObsoleteDsnOverload); + } + + return new NotSupportedException(ConfigurationExtensions.ObsoleteDsnOverload); } /// @@ -240,40 +211,6 @@ protected override void InitializeTarget() base.InitializeTarget(); - if (InternalLogger.IsDebugEnabled || InternalLogger.IsInfoEnabled || InternalLogger.IsWarnEnabled || InternalLogger.IsErrorEnabled || InternalLogger.IsFatalEnabled) - { - var existingLogger = Options.DiagnosticLogger; - if (existingLogger is not NLogDiagnosticLogger) - { - Options.DiagnosticLogger = new NLogDiagnosticLogger(existingLogger); - } - Options.Debug = true; - } - - var customDsn = Dsn?.Render(LogEventInfo.CreateNullEvent()); - if (!string.IsNullOrEmpty(customDsn)) - { - Options.Dsn = customDsn; - } - - var customRelease = Release?.Render(LogEventInfo.CreateNullEvent()); - if (!string.IsNullOrEmpty(customRelease)) - { - Options.Release = customRelease; - } - - var customEnvironment = Environment?.Render(LogEventInfo.CreateNullEvent()); - if (!string.IsNullOrEmpty(customEnvironment)) - { - Options.Environment = customEnvironment; - } - - // If the sdk is not there, set it on up. - if (InitializeSdk && _sdkDisposable == null) - { - _sdkDisposable = SentrySdk.Init(Options); - } - if (!HubAccessor().IsEnabled) { InternalLogger.Info("Sentry(Name={0}): Hub not enabled", Name); @@ -284,7 +221,7 @@ protected override void InitializeTarget() protected override void FlushAsync(AsyncContinuation asyncContinuation) { _ = HubAccessor() - .FlushAsync(Options.FlushTimeout) + .FlushAsync() .ContinueWith(t => asyncContinuation(t.Exception)); } @@ -315,7 +252,7 @@ protected override void Write(LogEventInfo logEvent) if (isReentrant.Value) { - Options.DiagnosticLogger?.LogError($"Reentrant log event detected. Logging when inside the scope of another log event can cause a StackOverflowException. LogEventInfo.Message:{logEvent.Message}"); + HubAccessor()?.GetSentryOptions()?.DiagnosticLogger?.LogError($"Reentrant log event detected. Logging when inside the scope of another log event can cause a StackOverflowException. LogEventInfo.Message:{logEvent.Message}"); return; } @@ -327,7 +264,7 @@ protected override void Write(LogEventInfo logEvent) } catch (Exception exception) { - Options.DiagnosticLogger?.LogError(exception, "Failed to write log event"); + HubAccessor()?.GetSentryOptions()?.DiagnosticLogger?.LogError(exception, "Failed to write log event"); throw; } finally @@ -346,6 +283,11 @@ private void InnerWrite(LogEventInfo logEvent) var hub = HubAccessor(); if (!hub.IsEnabled) { + if (logEvent.Level >= Options.MinimumEventLevel) + { + _uninitializedSdkWarning.WarnOnce(UninitializedSdkMessage); + } + return; } @@ -371,8 +313,6 @@ private void InnerWrite(LogEventInfo logEvent) CreateBreadcrumb(logEvent, exception, shouldIncludeProperties, hub); } - // Read the options from the Hub rather than the Target's NLog-Options. If the NLog-Target is added without a - // DSN (i.e. without initialising the SDK), then base options will only be initialised in the Hub options. var sentryOptions = hub.GetSentryOptions(); if (sentryOptions is not null) { @@ -452,22 +392,9 @@ private void CreateSentryEvent(LogEventInfo logEvent, Exception? exception, bool }, Logger = logEvent.LoggerName, Level = logEvent.Level.ToSentryLevel(), - Release = Options.Release, - Environment = Options.Environment, User = GetUser(logEvent) ?? new SentryUser(), }; - if (evt.Sdk is { } sdk) - { - sdk.Name = Constants.SdkName; - sdk.Version = NameAndVersion.Version; - - if (NameAndVersion.Version is { } version) - { - sdk.AddPackage(ProtocolPackageName, version); - } - } - if (Tags.Count > 0 || IncludeEventPropertiesAsTags && logEvent.HasProperties) { evt.SetTags(GetTagsFromLogEvent(logEvent)); 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 8934fb57a7..aa4f652e7f 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt @@ -3,8 +3,10 @@ namespace NLog { public static class ConfigurationExtensions { - public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null) { } + public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null, string targetName = "sentry") { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, System.Action? optionsConfig = null) { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, string targetName, System.Action? optionsConfig = null) { } public static void AddTag(this Sentry.NLog.SentryNLogOptions options, string name, NLog.Layouts.Layout layout) { } } @@ -12,29 +14,21 @@ namespace NLog namespace Sentry.NLog { [NLog.Config.NLogConfigurationItem] - public class SentryNLogOptions : Sentry.SentryOptions + public class SentryNLogOptions { public SentryNLogOptions() { } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbCategoryLayout { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? DsnLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? EnvironmentLayout { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { get; set; } - public bool InitializeSdk { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? ReleaseLayout { get; set; } - public int ShutdownTimeoutSeconds { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] public Sentry.NLog.SentryNLogUser? User { get; set; } @@ -58,25 +52,22 @@ namespace Sentry.NLog public SentryTarget(Sentry.NLog.SentryNLogOptions options) { } public NLog.Layouts.Layout? BreadcrumbCategory { get; set; } 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("Logs are always enabled. This option is ignored and will be removed in a future m" + "ajor version. To drop logs, use SetBeforeSendLog and return null.")] public bool EnableLogs { get; set; } - public NLog.Layouts.Layout? Environment { get; set; } - public int FlushTimeoutSeconds { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { 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 bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } - public NLog.Layouts.Layout? Release { get; set; } - public int ShutdownTimeoutSeconds { get; set; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } public Sentry.NLog.SentryNLogUser? User { get; set; } - protected override void CloseTarget() { } protected override void FlushAsync(NLog.Common.AsyncContinuation asyncContinuation) { } protected override void InitializeTarget() { } protected override void Write(NLog.LogEventInfo logEvent) { } 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 8934fb57a7..aa4f652e7f 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt @@ -3,8 +3,10 @@ namespace NLog { public static class ConfigurationExtensions { - public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null) { } + public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null, string targetName = "sentry") { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, System.Action? optionsConfig = null) { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, string targetName, System.Action? optionsConfig = null) { } public static void AddTag(this Sentry.NLog.SentryNLogOptions options, string name, NLog.Layouts.Layout layout) { } } @@ -12,29 +14,21 @@ namespace NLog namespace Sentry.NLog { [NLog.Config.NLogConfigurationItem] - public class SentryNLogOptions : Sentry.SentryOptions + public class SentryNLogOptions { public SentryNLogOptions() { } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbCategoryLayout { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? DsnLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? EnvironmentLayout { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { get; set; } - public bool InitializeSdk { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? ReleaseLayout { get; set; } - public int ShutdownTimeoutSeconds { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] public Sentry.NLog.SentryNLogUser? User { get; set; } @@ -58,25 +52,22 @@ namespace Sentry.NLog public SentryTarget(Sentry.NLog.SentryNLogOptions options) { } public NLog.Layouts.Layout? BreadcrumbCategory { get; set; } 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("Logs are always enabled. This option is ignored and will be removed in a future m" + "ajor version. To drop logs, use SetBeforeSendLog and return null.")] public bool EnableLogs { get; set; } - public NLog.Layouts.Layout? Environment { get; set; } - public int FlushTimeoutSeconds { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { 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 bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } - public NLog.Layouts.Layout? Release { get; set; } - public int ShutdownTimeoutSeconds { get; set; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } public Sentry.NLog.SentryNLogUser? User { get; set; } - protected override void CloseTarget() { } protected override void FlushAsync(NLog.Common.AsyncContinuation asyncContinuation) { } protected override void InitializeTarget() { } protected override void Write(NLog.LogEventInfo logEvent) { } 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 8934fb57a7..aa4f652e7f 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt @@ -3,8 +3,10 @@ namespace NLog { public static class ConfigurationExtensions { - public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null) { } + public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null, string targetName = "sentry") { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, System.Action? optionsConfig = null) { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, string targetName, System.Action? optionsConfig = null) { } public static void AddTag(this Sentry.NLog.SentryNLogOptions options, string name, NLog.Layouts.Layout layout) { } } @@ -12,29 +14,21 @@ namespace NLog namespace Sentry.NLog { [NLog.Config.NLogConfigurationItem] - public class SentryNLogOptions : Sentry.SentryOptions + public class SentryNLogOptions { public SentryNLogOptions() { } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbCategoryLayout { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? DsnLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? EnvironmentLayout { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { get; set; } - public bool InitializeSdk { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? ReleaseLayout { get; set; } - public int ShutdownTimeoutSeconds { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] public Sentry.NLog.SentryNLogUser? User { get; set; } @@ -58,25 +52,22 @@ namespace Sentry.NLog public SentryTarget(Sentry.NLog.SentryNLogOptions options) { } public NLog.Layouts.Layout? BreadcrumbCategory { get; set; } 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("Logs are always enabled. This option is ignored and will be removed in a future m" + "ajor version. To drop logs, use SetBeforeSendLog and return null.")] public bool EnableLogs { get; set; } - public NLog.Layouts.Layout? Environment { get; set; } - public int FlushTimeoutSeconds { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { 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 bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } - public NLog.Layouts.Layout? Release { get; set; } - public int ShutdownTimeoutSeconds { get; set; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } public Sentry.NLog.SentryNLogUser? User { get; set; } - protected override void CloseTarget() { } protected override void FlushAsync(NLog.Common.AsyncContinuation asyncContinuation) { } protected override void InitializeTarget() { } protected override void Write(NLog.LogEventInfo logEvent) { } 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 8934fb57a7..aa4f652e7f 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt @@ -3,8 +3,10 @@ namespace NLog { public static class ConfigurationExtensions { - public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null) { } + public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null, string targetName = "sentry") { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, System.Action? optionsConfig = null) { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, string targetName, System.Action? optionsConfig = null) { } public static void AddTag(this Sentry.NLog.SentryNLogOptions options, string name, NLog.Layouts.Layout layout) { } } @@ -12,29 +14,21 @@ namespace NLog namespace Sentry.NLog { [NLog.Config.NLogConfigurationItem] - public class SentryNLogOptions : Sentry.SentryOptions + public class SentryNLogOptions { public SentryNLogOptions() { } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbCategoryLayout { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? DsnLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? EnvironmentLayout { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { get; set; } - public bool InitializeSdk { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? ReleaseLayout { get; set; } - public int ShutdownTimeoutSeconds { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] public Sentry.NLog.SentryNLogUser? User { get; set; } @@ -58,25 +52,22 @@ namespace Sentry.NLog public SentryTarget(Sentry.NLog.SentryNLogOptions options) { } public NLog.Layouts.Layout? BreadcrumbCategory { get; set; } 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("Logs are always enabled. This option is ignored and will be removed in a future m" + "ajor version. To drop logs, use SetBeforeSendLog and return null.")] public bool EnableLogs { get; set; } - public NLog.Layouts.Layout? Environment { get; set; } - public int FlushTimeoutSeconds { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { 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 bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } - public NLog.Layouts.Layout? Release { get; set; } - public int ShutdownTimeoutSeconds { get; set; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } public Sentry.NLog.SentryNLogUser? User { get; set; } - protected override void CloseTarget() { } protected override void FlushAsync(NLog.Common.AsyncContinuation asyncContinuation) { } protected override void InitializeTarget() { } protected override void Write(NLog.LogEventInfo logEvent) { } 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 8934fb57a7..aa4f652e7f 100644 --- a/test/Sentry.NLog.Tests/ApiApprovalTests.Run.Net4_8.verified.txt +++ b/test/Sentry.NLog.Tests/ApiApprovalTests.Run.Net4_8.verified.txt @@ -3,8 +3,10 @@ namespace NLog { public static class ConfigurationExtensions { - public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null) { } + public static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, System.Action? optionsConfig = null, string targetName = "sentry") { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, System.Action? optionsConfig = null) { } + [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 static NLog.Config.LoggingConfiguration AddSentry(this NLog.Config.LoggingConfiguration configuration, string? dsn, string targetName, System.Action? optionsConfig = null) { } public static void AddTag(this Sentry.NLog.SentryNLogOptions options, string name, NLog.Layouts.Layout layout) { } } @@ -12,29 +14,21 @@ namespace NLog namespace Sentry.NLog { [NLog.Config.NLogConfigurationItem] - public class SentryNLogOptions : Sentry.SentryOptions + public class SentryNLogOptions { public SentryNLogOptions() { } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbCategoryLayout { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? BreadcrumbLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? DsnLayout { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? EnvironmentLayout { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { get; set; } - public bool InitializeSdk { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] public NLog.Layouts.Layout? Layout { get; set; } public NLog.LogLevel? MinimumBreadcrumbLevel { get; set; } public NLog.LogLevel? MinimumEventLevel { get; set; } [NLog.Config.NLogConfigurationIgnoreProperty] - public NLog.Layouts.Layout? ReleaseLayout { get; set; } - public int ShutdownTimeoutSeconds { get; set; } - [NLog.Config.NLogConfigurationIgnoreProperty] public System.Collections.Generic.IList Tags { get; } [NLog.Config.NLogConfigurationIgnoreProperty] public Sentry.NLog.SentryNLogUser? User { get; set; } @@ -58,25 +52,22 @@ namespace Sentry.NLog public SentryTarget(Sentry.NLog.SentryNLogOptions options) { } public NLog.Layouts.Layout? BreadcrumbCategory { get; set; } 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("Logs are always enabled. This option is ignored and will be removed in a future m" + "ajor version. To drop logs, use SetBeforeSendLog and return null.")] public bool EnableLogs { get; set; } - public NLog.Layouts.Layout? Environment { get; set; } - public int FlushTimeoutSeconds { get; set; } public bool IgnoreEventsWithNoException { get; set; } public bool IncludeEventDataOnBreadcrumbs { get; set; } public bool IncludeEventPropertiesAsTags { 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 bool InitializeSdk { get; set; } public string MinimumBreadcrumbLevel { get; set; } public string MinimumEventLevel { get; set; } public Sentry.NLog.SentryNLogOptions Options { get; } - public NLog.Layouts.Layout? Release { get; set; } - public int ShutdownTimeoutSeconds { get; set; } [NLog.Config.ArrayParameter(typeof(NLog.Targets.TargetPropertyWithContext), "tag")] public System.Collections.Generic.IList Tags { get; } public Sentry.NLog.SentryNLogUser? User { get; set; } - protected override void CloseTarget() { } protected override void FlushAsync(NLog.Common.AsyncContinuation asyncContinuation) { } protected override void InitializeTarget() { } protected override void Write(NLog.LogEventInfo logEvent) { } diff --git a/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs b/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs index f46f27d593..4a1efcb3a9 100644 --- a/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs +++ b/test/Sentry.NLog.Tests/ConfigurationExtensionsTest.cs @@ -12,21 +12,16 @@ public void AddSentry_Parameterless_DefaultTargetName() [Fact] public void AddSentry_ConfigCallback_CallbackInvoked() { - var expected = TimeSpan.FromDays(1); - var actual = new LoggingConfiguration().AddSentry(o => o.FlushTimeout = expected); + var actual = new LoggingConfiguration().AddSentry(o => o.MinimumEventLevel = LogLevel.Warn); var sentryTarget = Assert.IsType(actual.AllTargets[0]); - Assert.Equal(expected.TotalSeconds, sentryTarget.FlushTimeoutSeconds); + Assert.Equal(LogLevel.Warn.ToString(), sentryTarget.MinimumEventLevel); } [Fact] - public void AddSentry_DsnAndConfigCallback_CallbackInvokedAndDsnUsed() + public void AddSentry_TargetName_TargetNamed() { - var expectedTimeout = TimeSpan.FromDays(1); - var expectedDsn = "https://a@sentry.io/1"; - var actual = new LoggingConfiguration().AddSentry(expectedDsn, o => o.FlushTimeout = expectedTimeout); - var sentryTarget = Assert.IsType(actual.AllTargets[0]); - Assert.Equal(expectedTimeout.TotalSeconds, sentryTarget.FlushTimeoutSeconds); - Assert.Equal(expectedDsn, sentryTarget.Options.Dsn); + var actual = new LoggingConfiguration().AddSentry(targetName: "custom"); + Assert.Equal("custom", actual.AllTargets[0].Name); } [Fact] diff --git a/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet10_0.verified.txt b/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet10_0.verified.txt index 34197eb0e0..f489c6a8fc 100644 --- a/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet10_0.verified.txt +++ b/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet10_0.verified.txt @@ -40,8 +40,8 @@ FileName: IntegrationTests.verify.cs, Function: Task IntegrationTests.Simple(), Module: null, - LineNumber: 52, - ColumnNumber: 17, + LineNumber: 57, + ColumnNumber: 21, AbsolutePath: {ProjectDirectory}IntegrationTests.verify.cs, ContextLine: null, InApp: false, diff --git a/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet8_0.verified.txt b/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet8_0.verified.txt index 34197eb0e0..f489c6a8fc 100644 --- a/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet8_0.verified.txt +++ b/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet8_0.verified.txt @@ -40,8 +40,8 @@ FileName: IntegrationTests.verify.cs, Function: Task IntegrationTests.Simple(), Module: null, - LineNumber: 52, - ColumnNumber: 17, + LineNumber: 57, + ColumnNumber: 21, AbsolutePath: {ProjectDirectory}IntegrationTests.verify.cs, ContextLine: null, InApp: false, diff --git a/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet9_0.verified.txt b/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet9_0.verified.txt index 34197eb0e0..f489c6a8fc 100644 --- a/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet9_0.verified.txt +++ b/test/Sentry.NLog.Tests/IntegrationTests.Simple.DotNet9_0.verified.txt @@ -40,8 +40,8 @@ FileName: IntegrationTests.verify.cs, Function: Task IntegrationTests.Simple(), Module: null, - LineNumber: 52, - ColumnNumber: 17, + LineNumber: 57, + ColumnNumber: 21, AbsolutePath: {ProjectDirectory}IntegrationTests.verify.cs, ContextLine: null, InApp: false, diff --git a/test/Sentry.NLog.Tests/IntegrationTests.Simple.Net4_8.verified.txt b/test/Sentry.NLog.Tests/IntegrationTests.Simple.Net4_8.verified.txt index 34197eb0e0..f489c6a8fc 100644 --- a/test/Sentry.NLog.Tests/IntegrationTests.Simple.Net4_8.verified.txt +++ b/test/Sentry.NLog.Tests/IntegrationTests.Simple.Net4_8.verified.txt @@ -40,8 +40,8 @@ FileName: IntegrationTests.verify.cs, Function: Task IntegrationTests.Simple(), Module: null, - LineNumber: 52, - ColumnNumber: 17, + LineNumber: 57, + ColumnNumber: 21, AbsolutePath: {ProjectDirectory}IntegrationTests.verify.cs, ContextLine: null, InApp: false, diff --git a/test/Sentry.NLog.Tests/IntegrationTests.verify.cs b/test/Sentry.NLog.Tests/IntegrationTests.verify.cs index 887897a3b4..edf97f08f8 100644 --- a/test/Sentry.NLog.Tests/IntegrationTests.verify.cs +++ b/test/Sentry.NLog.Tests/IntegrationTests.verify.cs @@ -12,52 +12,58 @@ public Task Simple() var transport = new RecordingTransport(); - var configuration = new LoggingConfiguration(); + using (SentrySdk.Init( + options => + { + options.TracesSampleRate = 1; + options.Transport = transport; + options.DiagnosticLevel = SentryLevel.Debug; + options.Dsn = ValidDsn; + options.Release = "test-release"; + })) + { + var configuration = new LoggingConfiguration(); - configuration.AddSentry( - options => - { - options.TracesSampleRate = 1; - options.Layout = "${message}"; - options.Transport = transport; - options.DiagnosticLevel = SentryLevel.Debug; - options.IncludeEventDataOnBreadcrumbs = true; - options.MinimumBreadcrumbLevel = LogLevel.Debug; - options.Dsn = ValidDsn; - options.Release = "test-release"; - options.User = new SentryNLogUser + configuration.AddSentry( + options => { - Id = "${scopeproperty:item=id}", - Username = "${scopeproperty:item=username}", - Email = "${scopeproperty:item=email}", - IpAddress = "${scopeproperty:item=ipAddress}", - Segment = "${scopeproperty:item=segment}", - Other = + options.Layout = "${message}"; + options.IncludeEventDataOnBreadcrumbs = true; + options.MinimumBreadcrumbLevel = LogLevel.Debug; + options.User = new SentryNLogUser { - new TargetPropertyWithContext("mood", "joyous") - }, - }; + Id = "${scopeproperty:item=id}", + Username = "${scopeproperty:item=username}", + Email = "${scopeproperty:item=email}", + IpAddress = "${scopeproperty:item=ipAddress}", + Segment = "${scopeproperty:item=segment}", + Other = + { + new TargetPropertyWithContext("mood", "joyous") + }, + }; - options.AddTag("logger", "${logger}"); - }); + options.AddTag("logger", "${logger}"); + }); - LogManager.Configuration = configuration; + LogManager.Configuration = configuration; - var log = LogManager.GetCurrentClassLogger(); + var log = LogManager.GetCurrentClassLogger(); - using (ScopeContext.PushProperty("id", "myId")) - { - try - { - throw new("Exception message"); - } - catch (Exception exception) + using (ScopeContext.PushProperty("id", "myId")) { - log.Error(exception, "message = {arg}", "arg value"); + try + { + throw new("Exception message"); + } + catch (Exception exception) + { + log.Error(exception, "message = {arg}", "arg value"); + } } - } - LogManager.Flush(); + LogManager.Flush(); + } return Verify(transport.Envelopes) .UniqueForRuntimeAndVersion() @@ -68,33 +74,35 @@ public Task Simple() public Task LoggingInsideTheContextOfLogging() { var transport = new RecordingTransport(); - - var configuration = new LoggingConfiguration(); - var diagnosticLogger = new InMemoryDiagnosticLogger(); - configuration.AddSentry( - options => - { - options.TracesSampleRate = 1; - options.Debug = true; - options.DiagnosticLogger = diagnosticLogger; - options.Transport = transport; - options.Dsn = ValidDsn; - options.AttachStacktrace = false; - options.Release = "test-release"; - }); - LogManager.Configuration = configuration; + using (SentrySdk.Init( + options => + { + options.TracesSampleRate = 1; + options.Debug = true; + options.DiagnosticLogger = diagnosticLogger; + options.Transport = transport; + options.Dsn = ValidDsn; + options.AttachStacktrace = false; + options.Release = "test-release"; + })) + { + var configuration = new LoggingConfiguration(); + configuration.AddSentry(); + + LogManager.Configuration = configuration; - var log = LogManager.GetCurrentClassLogger(); + var log = LogManager.GetCurrentClassLogger(); - SentrySdk.ConfigureScope( - scope => - { - scope.OnEvaluating += (_, _) => log.Error("message from OnEvaluating"); - log.Error("message"); - }); - LogManager.Flush(); + SentrySdk.ConfigureScope( + scope => + { + scope.OnEvaluating += (_, _) => log.Error("message from OnEvaluating"); + log.Error("message"); + }); + LogManager.Flush(); + } return Verify( new diff --git a/test/Sentry.NLog.Tests/NLogDiagnosticLoggerTest.cs b/test/Sentry.NLog.Tests/NLogDiagnosticLoggerTest.cs deleted file mode 100644 index d8f7e94e60..0000000000 --- a/test/Sentry.NLog.Tests/NLogDiagnosticLoggerTest.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Sentry.NLog.Tests; - -public class NLogDiagnosticLoggerTest -{ - [Fact] - public void NLogDiagnosticLogger_Levels() - { - var logger = new NLogDiagnosticLogger(); - try - { - InternalLogger.LogLevel = LogLevel.Debug; - foreach (SentryLevel level in Enum.GetValues(typeof(SentryLevel))) - { - var logWriter = new StringWriter(); - InternalLogger.LogWriter = logWriter; - if (logger.IsEnabled(level)) - { - logger.Log(level, level.ToString()); - } - Assert.Contains(level.ToString(), logWriter.ToString()); - } - } - finally - { - InternalLogger.LogWriter = null; - InternalLogger.LogLevel = LogLevel.Off; - } - } -} diff --git a/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs b/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs new file mode 100644 index 0000000000..b367f2b9e4 --- /dev/null +++ b/test/Sentry.NLog.Tests/SentryTargetConfigurationBindingTests.cs @@ -0,0 +1,130 @@ +namespace Sentry.NLog.Tests; + +public class SentryTargetConfigurationBindingTests +{ + private static Exception LoadConfiguration(string targetAttributes) + { + var configXml = $@" + + + + + "; + + var logFactory = new LogFactory(); + return Record.Exception(() => logFactory.Configuration = + new XmlLoggingConfiguration(XmlReader.Create(new StringReader(configXml)), null, logFactory)); + } + + [Theory] + [InlineData("dsn='https://key@sentry.io/1'")] + [InlineData("initializeSdk='true'")] + public void LoadConfiguration_WithSdkSetting_Throws(string targetAttributes) + { + var exception = LoadConfiguration(targetAttributes); + + Assert.NotNull(exception); + Assert.Contains("SentrySdk.Init", exception.ToString()); + } + + [Fact] + 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)] + public void AddSentry_DsnOverload_InvokedByName_Throws(int parameterCount) + { + var method = DsnOverload(parameterCount); + + var arguments = method.GetParameters() + .Select(p => (object)(p.Name switch + { + "configuration" => new LoggingConfiguration(), + "dsn" => ValidDsn, + "targetName" => "sentry", + _ => p.HasDefaultValue ? p.DefaultValue : null + })!) + .ToArray(); + + var exception = Assert.Throws(() => method.Invoke(null, arguments)); + + Assert.IsType(exception.InnerException); + Assert.Contains("SentrySdk.Init", exception.InnerException!.Message); + } + + [Theory] + [InlineData(2)] + [InlineData(3)] + public void AddSentry_DsnOverload_IsObsoleteAsError(int parameterCount) + { + var obsolete = DsnOverload(parameterCount).GetCustomAttribute(); + + Assert.NotNull(obsolete); + 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) + && m.GetParameters().Any(p => p.Name == "dsn") + && m.GetParameters().Length == parameterCount + 1); +} diff --git a/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs b/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs index 1faf731b88..1318e01ef7 100644 --- a/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs +++ b/test/Sentry.NLog.Tests/SentryTargetTests.Structured.cs @@ -7,7 +7,7 @@ public partial class SentryTargetTests [Theory] [InlineData(false)] [InlineData(true)] - public void Write_StructuredLogging_UseHubOptionsOverTargetOptions(bool isEnabled) + public void Write_StructuredLogging_RequiresHubOptions(bool isEnabled) { InMemorySentryStructuredLogger capturer = new(); _fixture.Hub.Logger.Returns(capturer); @@ -55,8 +55,8 @@ public void Write_StructuredLogging_LogEvent(bool withActiveSpan) { InMemorySentryStructuredLogger capturer = new(); _fixture.Hub.Logger.Returns(capturer); - _fixture.Options.Environment = "test-environment"; - _fixture.Options.Release = "test-release"; + _fixture.SentryOptions.Environment = "test-environment"; + _fixture.SentryOptions.Release = "test-release"; if (withActiveSpan) { @@ -98,8 +98,8 @@ public void Write_StructuredLogging_LogEvent(bool withActiveSpan) log.Attributes.ShouldContain("sentry.environment", "test-environment"); log.Attributes.ShouldContain("sentry.release", "test-release"); log.Attributes.ShouldContain("sentry.origin", "auto.log.nlog"); - log.Attributes.ShouldContain("sentry.sdk.name", Constants.SdkName); - log.Attributes.ShouldContain("sentry.sdk.version", SentryTarget.NameAndVersion.Version); + log.Attributes.ShouldContain("sentry.sdk.name", SdkVersion.Instance.Name!); + log.Attributes.ShouldContain("sentry.sdk.version", SdkVersion.Instance.Version!); log.Attributes.ShouldContain("category.name", "sentry"); log.Attributes.ShouldContain("property.Text-Property-Key", "Text-Property-Value"); diff --git a/test/Sentry.NLog.Tests/SentryTargetTests.cs b/test/Sentry.NLog.Tests/SentryTargetTests.cs index dc456fde82..286093d9c6 100644 --- a/test/Sentry.NLog.Tests/SentryTargetTests.cs +++ b/test/Sentry.NLog.Tests/SentryTargetTests.cs @@ -8,14 +8,14 @@ public partial class SentryTargetTests private class Fixture { - public SentryNLogOptions Options { get; } = new() { Dsn = ValidDsn }; + public SentryNLogOptions Options { get; } = new(); + + public SentryOptions SentryOptions { get; } = new() { Dsn = ValidDsn }; public IHub Hub { get; } = Substitute.For(); public Func HubAccessor { get; set; } - public IDisposable SdkDisposeHandle { get; set; } = Substitute.For(); - public Scope Scope { get; } public Fixture() @@ -24,7 +24,7 @@ public Fixture() HubAccessor = () => Hub; Scope = new Scope(new SentryOptions()); Hub.SubstituteConfigureScope(Scope); - SentryClientExtensions.SentryOptionsForTestingOnly = Options; + SentryClientExtensions.SentryOptionsForTestingOnly = SentryOptions; } public Target GetTarget(bool asyncTarget = false) @@ -32,11 +32,9 @@ public Target GetTarget(bool asyncTarget = false) var target = new SentryTarget( Options, HubAccessor, - SdkDisposeHandle, new MockClock()) { Name = "sentry", - Dsn = Options.Dsn ?? Options.DsnLayout, }; if (asyncTarget) @@ -77,9 +75,9 @@ public void Can_configure_from_xml_file() - + - True + True @@ -92,14 +90,9 @@ public void Can_configure_from_xml_file() var t = logFactory.Configuration.FindTargetByName("sentry") as SentryTarget; Assert.NotNull(t); - if (t.Options.Dsn != null) - { - Assert.Equal(ValidDsn, t.Options.Dsn); - } - - Assert.Equal("test", t.Options.Environment); - Assert.Equal("1.2.3", t.Options.Release); - Assert.True(t.Options.AttachStacktrace); + Assert.Equal(LogLevel.Warn, t.Options.MinimumEventLevel); + Assert.True(t.Options.IgnoreEventsWithNoException); + Assert.True(t.Options.IncludeEventPropertiesAsTags); } [Fact] @@ -111,7 +104,7 @@ public void Can_configure_user_from_xml_file() - + @@ -126,7 +119,6 @@ public void Can_configure_user_from_xml_file() var t = logFactory.Configuration.FindTargetByName("sentry") as SentryTarget; Assert.NotNull(t); - Assert.Equal(ValidDsn, t.Options.Dsn); Assert.Equal("myUser", t.User?.Username?.ToString()); var other = t.User?.Other; @@ -137,27 +129,8 @@ public void Can_configure_user_from_xml_file() } [Fact] - public void Shutdown_DisposesSdk() + public void Shutdown_DoesNotThrow() { - _fixture.Options.InitializeSdk = false; - var target = _fixture.GetTarget(); - LogManager.Setup().LoadConfiguration(c => c.ForLogger().WriteTo(target)); - - var sut = LogManager.GetCurrentClassLogger(); - - sut.Error(DefaultMessage); - - _fixture.SdkDisposeHandle.DidNotReceive().Dispose(); - - LogManager.Shutdown(); - - _fixture.SdkDisposeHandle.Received(1).Dispose(); - } - - [Fact] - public void Shutdown_NoDisposeHandleProvided_DoesNotThrow() - { - _fixture.Options.InitializeSdk = false; var factory = _fixture.GetLoggerFactory(); var sut = factory.GetCurrentClassLogger(); @@ -249,40 +222,6 @@ public void Log_WithOnlyException_GeneratesBreadcrumbFromException() Assert.Equal(b.Data["exception_message"], expectedException.Message); } - [Fact] - public void Log_NLogSdk_Name() - { - _fixture.Options.MinimumEventLevel = LogLevel.Info; - var logger = _fixture.GetLogger(); - - var expected = typeof(SentryTarget).Assembly.GetNameAndVersion(); - logger.Info(DefaultMessage); - - _fixture.Hub.Received(1) - .CaptureEvent(Arg.Is(e => e.Sdk.Name == Constants.SdkName - && e.Sdk.Version == expected.Version)); - } - - [Fact] - public void Log_NLogSdk_Packages() - { - _fixture.Options.MinimumEventLevel = LogLevel.Info; - var logger = _fixture.GetLogger(); - - SentryEvent actual = null; - _fixture.Hub.When(h => h.CaptureEvent(Arg.Any())) - .Do(c => actual = c.Arg()); - - logger.Info(DefaultMessage); - - var expected = typeof(SentryTarget).Assembly.GetNameAndVersion(); - - Assert.NotNull(actual); - var package = Assert.Single(actual.Sdk.Packages); - Assert.Equal("nuget:" + expected.Name, package.Name); - Assert.Equal(expected.Version, package.Version); - } - [Theory] [ClassData(typeof(LogLevelData))] public void Log_LoggerLevel_Set(LogLevel nlogLevel, SentryLevel? sentryLevel) @@ -461,11 +400,12 @@ public void Log_WithCustomBreadcrumbCategory_RendersCorrectly() } [Fact] - public async Task LogManager_WhenFlushCalled_CallsSentryFlushAsync() + public async Task LogManager_WhenFlushCalled_FlushesHubWithSdkFlushTimeout() { var timeout = TimeSpan.FromSeconds(2); + var sdkFlushTimeout = TimeSpan.FromSeconds(3); - _fixture.Options.FlushTimeout = timeout; + _fixture.SentryOptions.FlushTimeout = sdkFlushTimeout; var factory = _fixture.GetLoggerFactory(asyncTarget: true); // Verify that it's asynchronous @@ -495,69 +435,7 @@ void Continuation(Exception _) Assert.True(tcs.Task.IsCompleted); testDisposable.Received().Dispose(); - await hub.Received().FlushAsync(Arg.Any()); - } - - [SkippableFact] - public void InitializeTarget_InitializesSdk() - { -#if SENTRY_DSN_DEFINED_IN_ENV - Skip.If(true, "This test only works when the DSN is not configured as an environment variable."); -#endif - _fixture.Options.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; - _fixture.SdkDisposeHandle = null; - _fixture.Options.InitializeSdk = true; - - var logWriter = new StringWriter(); - - try - { - InternalLogger.LogWriter = logWriter; - InternalLogger.LogLevel = LogLevel.Debug; - - _fixture.GetLoggerFactory(); - - var logOutput = logWriter.ToString(); - Assert.Contains("Init called with an empty string as the DSN. Sentry SDK will be disabled.", logOutput); - } - finally - { - InternalLogger.LogWriter = null; - InternalLogger.LogLevel = LogLevel.Off; - } - } - - [Fact] - public void Dsn_ReturnsDsnFromOptions_Null() - { - _fixture.Options.Dsn = null; - var target = (SentryTarget)_fixture.GetTarget(); - Assert.Null(target.Dsn); - } - - [Fact] - public void Dsn_ReturnsDsnFromOptions_Instance() - { - var expectedDsn = "https://a@sentry.io/1"; - _fixture.Options.Dsn = expectedDsn; - var target = (SentryTarget)_fixture.GetTarget(); - Assert.Equal(expectedDsn, target.Options.Dsn); - } - - [Fact] - public void Dsn_SupportsNLogLayout_Lookup() - { - var expectedDsn = "https://a@sentry.io/1"; - var target = (SentryTarget)_fixture.GetTarget(); - target.Dsn = "${var:mydsn}"; - var logFactory = new LogFactory(); - var logConfig = new LoggingConfiguration(logFactory) - { - Variables = { ["mydsn"] = expectedDsn } - }; - logConfig.AddRuleForAllLevels(target); - logFactory.Configuration = logConfig; - Assert.Equal(expectedDsn, target.Options.Dsn); + await hub.Received().FlushAsync(sdkFlushTimeout); } [Fact] @@ -683,51 +561,6 @@ public void IncludeEventDataOnBreadcrumbs_SetterReplacesOptions() Assert.False(target.IncludeEventDataOnBreadcrumbs); } - [Fact] - public void ShutdownTimeoutSeconds_ValueFromOptions() - { - const int expected = 60; - _fixture.Options.ShutdownTimeoutSeconds = expected; - var target = (SentryTarget)_fixture.GetTarget(); - Assert.Equal(expected, target.ShutdownTimeoutSeconds); - } - - [Fact] - public void ShutdownTimeoutSeconds_Default_2Seconds() - { - var target = (SentryTarget)_fixture.GetTarget(); - Assert.Equal(2, target.ShutdownTimeoutSeconds); - } - - [Fact] - public void ShutdownTimeoutSeconds_SetterReplacesOptions() - { - var expected = 60; - _fixture.Options.ShutdownTimeoutSeconds = int.MinValue; - var target = (SentryTarget)_fixture.GetTarget(); - target.ShutdownTimeoutSeconds = expected; - Assert.Equal(expected, target.ShutdownTimeoutSeconds); - } - - [Fact] - public void FlushTimeoutSeconds_ValueFromOptions() - { - var expected = 10; - _fixture.Options.FlushTimeout = TimeSpan.FromSeconds(expected); - var target = (SentryTarget)_fixture.GetTarget(); - Assert.Equal(expected, target.FlushTimeoutSeconds); - } - - [Fact] - public void FlushTimeoutSeconds_SetterReplacesOptions() - { - var expected = 100; - _fixture.Options.FlushTimeout = TimeSpan.FromSeconds(expected); - var target = (SentryTarget)_fixture.GetTarget(); - target.FlushTimeoutSeconds = expected; - Assert.Equal(expected, target.FlushTimeoutSeconds); - } - [Fact] public void IgnoreEventsWithNoException_SetterReplacesOptions() { @@ -737,13 +570,6 @@ public void IgnoreEventsWithNoException_SetterReplacesOptions() Assert.True(target.IgnoreEventsWithNoException); } - [Fact] - public void FlushTimeoutSeconds_Default_15Seconds() - { - var target = (SentryTarget)_fixture.GetTarget(); - Assert.Equal(15, target.FlushTimeoutSeconds); - } - [Fact] public void BreadcrumbLayout_Null_FallsBackToLayout() { diff --git a/test/Sentry.NLog.Tests/SentryTargetUninitializedSdkTests.cs b/test/Sentry.NLog.Tests/SentryTargetUninitializedSdkTests.cs new file mode 100644 index 0000000000..9cf269f737 --- /dev/null +++ b/test/Sentry.NLog.Tests/SentryTargetUninitializedSdkTests.cs @@ -0,0 +1,80 @@ +namespace Sentry.NLog.Tests; + +public class SentryTargetUninitializedSdkTests +{ + private readonly List _internalLog = []; + private readonly List _standardError = []; + + private Logger GetLogger(bool sdkEnabled, string dsn = ValidDsn) + { + var hub = Substitute.For(); + hub.IsEnabled.Returns(sdkEnabled); + hub.Logger.Returns(new InMemorySentryStructuredLogger()); + + var warning = new UninitializedSdkWarning(_internalLog.Add) + { + DsnLocator = () => dsn, + WriteToStandardError = _standardError.Add + }; + + var target = new SentryTarget(new SentryNLogOptions(), () => hub, new MockClock(), warning) + { + Name = "sentry" + }; + + var factory = new LogFactory(); + var configuration = new LoggingConfiguration(factory); + configuration.AddTarget("sentry", target); + configuration.AddRule(LogLevel.Trace, LogLevel.Fatal, target); + factory.Configuration = configuration; + + return factory.GetLogger("sentry"); + } + + [Fact] + public void Write_SdkNotInitialized_WarnsToInternalLoggerAndStandardError() + { + GetLogger(sdkEnabled: false).Error("message"); + + Assert.Equal(new[] { SentryTarget.UninitializedSdkMessage }, _internalLog); + Assert.Equal(new[] { SentryTarget.UninitializedSdkMessage }, _standardError); + } + + [Fact] + public void Write_SdkNotInitialized_WarnsOnceForManyEvents() + { + var logger = GetLogger(sdkEnabled: false); + + logger.Error("first"); + logger.Fatal("second"); + + Assert.Single(_standardError); + } + + [Fact] + public void Write_SdkNotInitializedAndBelowMinimumEventLevel_DoesNotWarn() + { + GetLogger(sdkEnabled: false).Warn("message"); + + Assert.Empty(_internalLog); + Assert.Empty(_standardError); + } + + [Fact] + public void Write_SdkNotInitializedAndNoDsnFound_DoesNotWarn() + { + GetLogger(sdkEnabled: false, dsn: null).Error("message"); + + Assert.Empty(_internalLog); + Assert.Empty(_standardError); + } + + [Fact] + public void Write_SdkInitialized_DoesNotWarn() + { + GetLogger(sdkEnabled: true).Error("message"); + + Assert.Empty(_internalLog); + Assert.Empty(_standardError); + } +}