diff --git a/benchmarks/Sentry.Extensions.Logging.Benchmarks/SentryStructuredLoggerBenchmarks.cs b/benchmarks/Sentry.Extensions.Logging.Benchmarks/SentryStructuredLoggerBenchmarks.cs index d7608082df..2ea4c5b9e4 100644 --- a/benchmarks/Sentry.Extensions.Logging.Benchmarks/SentryStructuredLoggerBenchmarks.cs +++ b/benchmarks/Sentry.Extensions.Logging.Benchmarks/SentryStructuredLoggerBenchmarks.cs @@ -16,7 +16,7 @@ public class SentryStructuredLoggerBenchmarks [GlobalSetup] public void Setup() { - SentryLoggingOptions options = new() + SentryOptions options = new() { Dsn = DsnSamples.ValidDsn, }; @@ -34,7 +34,7 @@ public void Setup() }; _hub = new Hub(options, DisabledHub.Instance); - _logger = new SentryStructuredLogger("CategoryName", options, _hub, clock, sdk); + _logger = new SentryStructuredLogger("CategoryName", _hub, clock, sdk); _logRecord = new LogRecord(LogLevel.Information, new EventId(2025, "EventName"), new InvalidOperationException("exception-message"), "Number={Number}, Text={Text}", 2018, "message"); } diff --git a/samples/Sentry.Samples.GenericHost/Program.cs b/samples/Sentry.Samples.GenericHost/Program.cs index 5bad8f3641..ec0d0ab221 100644 --- a/samples/Sentry.Samples.GenericHost/Program.cs +++ b/samples/Sentry.Samples.GenericHost/Program.cs @@ -7,14 +7,19 @@ builder.Logging.AddConfiguration(builder.Configuration); +// Initialise the Sentry SDK. The logging integration added below only forwards log messages to Sentry. +using var sentry = SentrySdk.Init(options => +{ #if !SENTRY_DSN_DEFINED_IN_ENV -// A DSN is required. You can set it here in code, via the SENTRY_DSN environment variable or in your -// appsettings.json file. -// See https://docs.sentry.io/platforms/dotnet/guides/aspnetcore/#configure -builder.Logging.AddSentry(SamplesShared.Dsn); -#else -builder.Logging.AddSentry(); + // 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 + // Send user name and machine name + options.SendDefaultPii = true; +}); + +builder.Logging.AddSentry(); builder.Services.AddHostedService(); diff --git a/samples/Sentry.Samples.GenericHost/appsettings.json b/samples/Sentry.Samples.GenericHost/appsettings.json index 9d20069922..5d9d65349a 100644 --- a/samples/Sentry.Samples.GenericHost/appsettings.json +++ b/samples/Sentry.Samples.GenericHost/appsettings.json @@ -10,9 +10,7 @@ } }, "Sentry": { - //"Dsn": "TODO: Configure your DSN here and uncomment this line", "MinimumBreadcrumbLevel": "Debug", - "MinimumEventLevel": "Warning", - "SendDefaultPii": true // Send user name and machine name + "MinimumEventLevel": "Warning" } } diff --git a/samples/Sentry.Samples.ME.Logging/Program.cs b/samples/Sentry.Samples.ME.Logging/Program.cs index fb2e8aa63d..a80e29cd67 100644 --- a/samples/Sentry.Samples.ME.Logging/Program.cs +++ b/samples/Sentry.Samples.ME.Logging/Program.cs @@ -1,39 +1,43 @@ using Microsoft.Extensions.Logging; using Sentry.Extensions.Logging; -using var loggerFactory = LoggerFactory.Create(builder => +// Initialise the Sentry SDK. The logging integration added below only forwards log messages to Sentry. +using var sentry = SentrySdk.Init(options => { - builder.AddConsole(); - builder.AddSentry(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; + // 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 - // Set to true to SDK debugging to see the internal messages through the logging library. - options.Debug = false; - // Configure the level of Sentry internal logging - options.DiagnosticLevel = SentryLevel.Debug; + // Set to true to SDK debugging to see the internal messages through the logging library. + options.Debug = false; + // Configure the level of Sentry internal logging + options.DiagnosticLevel = SentryLevel.Debug; + + options.MaxBreadcrumbs = 150; // Increasing from default 100 + options.Release = "e386dfd"; // If not set here, SDK looks for it on main assembly's AssemblyInformationalVersion and AssemblyVersion + + options.SetBeforeSendLog(static log => + { + log.SetAttribute("attribute-key", "attribute-value"); + return log; + }); +}); - options.MaxBreadcrumbs = 150; // Increasing from default 100 - options.Release = "e386dfd"; // If not set here, SDK looks for it on main assembly's AssemblyInformationalVersion and AssemblyVersion +SentrySdk.ConfigureScope(s => s.SetTag("RootScope", "sent with all events")); +using var loggerFactory = LoggerFactory.Create(builder => +{ + builder.AddConsole(); + builder.AddSentry(options => + { // Optionally configure options: The default values are: options.MinimumBreadcrumbLevel = LogLevel.Information; // It requires at least this level to store breadcrumb options.MinimumEventLevel = LogLevel.Error; // This level or above will result in event sent to Sentry - options.SetBeforeSendLog(static log => - { - log.SetAttribute("attribute-key", "attribute-value"); - return log; - }); - // Don't keep as a breadcrumb or send events for messages of level less than Critical with exception of type DivideByZeroException options.AddLogEntryFilter((_, level, _, exception) => level < LogLevel.Critical && exception is DivideByZeroException); - - options.ConfigureScope(s => s.SetTag("RootScope", "sent with all events")); }); // Don't send logs for messages of level less than Warning for category Program builder.AddFilter(typeof(Program).FullName, LogLevel.Warning); @@ -86,8 +90,6 @@ Dependency.Work("8 - This unhandled exception is captured and includes Scope (A, B) and crumbs: (2, 4, 5) and event (3) "); } -// Disposing the LoggerFactory will close the SDK since it was initialized through -// the integration while calling .Init() internal static class Dependency { diff --git a/samples/Sentry.Samples.OpenTelemetry.AzureFunctions/Program.cs b/samples/Sentry.Samples.OpenTelemetry.AzureFunctions/Program.cs index 93c91d900f..9342669372 100644 --- a/samples/Sentry.Samples.OpenTelemetry.AzureFunctions/Program.cs +++ b/samples/Sentry.Samples.OpenTelemetry.AzureFunctions/Program.cs @@ -14,6 +14,16 @@ var dsn = SamplesShared.Dsn; #endif +// Initialise the Sentry SDK. The logging integration added below only forwards log messages to Sentry. +using var sentry = SentrySdk.Init(options => +{ + options.Dsn = dsn; + options.TracesSampleRate = 1.0; + options.UseOtlp(); // <-- Configure Sentry to use open telemetry + options.DisableSentryHttpMessageHandler = true; // So Sentry doesn't also create spans for outbound HTTP requests + options.Debug = true; +}); + var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() .ConfigureServices(services => @@ -25,17 +35,7 @@ .AddHttpClientInstrumentation(); // From OpenTelemetry.Instrumentation.Http... adds automatic tracing for outgoing HTTP requests }); }) - .ConfigureLogging(logging => - { - logging.AddSentry(options => - { - options.Dsn = dsn; - options.TracesSampleRate = 1.0; - options.UseOtlp(); // <-- Configure Sentry to use open telemetry - options.DisableSentryHttpMessageHandler = true; // So Sentry doesn't also create spans for outbound HTTP requests - options.Debug = true; - }); - }) + .ConfigureLogging(logging => logging.AddSentry()) .Build(); await host.RunAsync(); diff --git a/src/Sentry.AspNetCore.Blazor.WebAssembly/WebAssemblyHostBuilderExtensions.cs b/src/Sentry.AspNetCore.Blazor.WebAssembly/WebAssemblyHostBuilderExtensions.cs index 25c3070e68..9c1410e981 100644 --- a/src/Sentry.AspNetCore.Blazor.WebAssembly/WebAssemblyHostBuilderExtensions.cs +++ b/src/Sentry.AspNetCore.Blazor.WebAssembly/WebAssemblyHostBuilderExtensions.cs @@ -1,9 +1,12 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Configuration; using Microsoft.Extensions.Options; using Sentry; using Sentry.AspNetCore.Blazor.WebAssembly.Internal; using Sentry.Extensions.Logging; +using Sentry.Extensions.Logging.Extensions.DependencyInjection; +using Sentry.Infrastructure; using Sentry.Internal; // ReSharper disable once CheckNamespace - Discoverability @@ -22,7 +25,15 @@ public static class WebAssemblyHostBuilderExtensions /// public static WebAssemblyHostBuilder UseSentry(this WebAssemblyHostBuilder builder, Action configureOptions) { - builder.Logging.AddSentry(blazorOptions => + builder.Logging.AddSentryBlazor(configureOptions); + return builder; + } + + internal static ILoggingBuilder AddSentryBlazor(this ILoggingBuilder logging, Action configureOptions) + { + logging.AddConfiguration(); + + logging.Services.Configure(blazorOptions => { configureOptions(blazorOptions); @@ -35,16 +46,27 @@ public static WebAssemblyHostBuilder UseSentry(this WebAssemblyHostBuilder build blazorOptions.AddTransactionProcessor(new TraceIgnoreStatusCodeTransactionProcessor(blazorOptions)); }); - builder.Services.AddSingleton, BlazorWasmOptionsSetup>(); + logging.Services.AddSingleton, SentryHostOptionsSetup>(); + logging.Services.AddSingleton, BlazorWasmOptionsSetup>(); - return builder; + logging.Services.AddSingleton(c => new SentryLoggerProvider( + c.GetRequiredService(), + SystemClock.Clock, + c.GetRequiredService>().Value.Logging)); + logging.Services.AddSingleton(c => new SentryStructuredLoggerProvider(c.GetRequiredService())); + logging.Services.AddSentry(); + + logging.AddFilter(_ => true); + logging.AddFilter("Sentry.ISentryClient", LogLevel.None); + + return logging; } } /// /// Sentry Blazor Options /// -public class SentryBlazorOptions : SentryLoggingOptions +public class SentryBlazorOptions : SentryHostOptions { // Awesome Blazor specific options go here } diff --git a/src/Sentry.AspNetCore/BindableSentryAspNetCoreOptions.cs b/src/Sentry.AspNetCore/BindableSentryAspNetCoreOptions.cs index e98a485d9f..c0e48fdc5a 100644 --- a/src/Sentry.AspNetCore/BindableSentryAspNetCoreOptions.cs +++ b/src/Sentry.AspNetCore/BindableSentryAspNetCoreOptions.cs @@ -8,7 +8,7 @@ namespace Sentry.AspNetCore; /// -internal class BindableSentryAspNetCoreOptions : BindableSentryLoggingOptions +internal class BindableSentryAspNetCoreOptions : BindableSentryHostOptions { public bool? IncludeActivityData { get; set; } public RequestSize? MaxRequestBodySize { get; set; } diff --git a/src/Sentry.AspNetCore/SentryAspNetCoreLoggerProvider.cs b/src/Sentry.AspNetCore/SentryAspNetCoreLoggerProvider.cs index 5ad52c8e9b..dd5955c425 100644 --- a/src/Sentry.AspNetCore/SentryAspNetCoreLoggerProvider.cs +++ b/src/Sentry.AspNetCore/SentryAspNetCoreLoggerProvider.cs @@ -15,12 +15,12 @@ internal sealed class SentryAspNetCoreLoggerProvider : SentryLoggerProvider /// Creates a new instance of /// public SentryAspNetCoreLoggerProvider(IOptions options, IHub hub) - : base(options, hub) + : base(hub, SystemClock.Clock, options.Value.Logging) { } internal SentryAspNetCoreLoggerProvider(SentryAspNetCoreOptions options, IHub hub, ISystemClock clock) - : base(hub, clock, options) + : base(hub, clock, options.Logging) { } } diff --git a/src/Sentry.AspNetCore/SentryAspNetCoreOptions.cs b/src/Sentry.AspNetCore/SentryAspNetCoreOptions.cs index f25ebc11ba..e2bd238f9f 100644 --- a/src/Sentry.AspNetCore/SentryAspNetCoreOptions.cs +++ b/src/Sentry.AspNetCore/SentryAspNetCoreOptions.cs @@ -11,7 +11,7 @@ namespace Sentry.AspNetCore; /// An options class for the ASP.NET Core Sentry integration /// /// -public class SentryAspNetCoreOptions : SentryLoggingOptions +public class SentryAspNetCoreOptions : SentryHostOptions { /// /// Gets or sets a value indicating whether [include System.Diagnostic.Activity data] to events. diff --git a/src/Sentry.AspNetCore/SentryAspNetCoreStructuredLoggerProvider.cs b/src/Sentry.AspNetCore/SentryAspNetCoreStructuredLoggerProvider.cs index 42f7cd8cc3..efd242270f 100644 --- a/src/Sentry.AspNetCore/SentryAspNetCoreStructuredLoggerProvider.cs +++ b/src/Sentry.AspNetCore/SentryAspNetCoreStructuredLoggerProvider.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Sentry.Extensions.Logging; using Sentry.Infrastructure; @@ -11,13 +10,13 @@ namespace Sentry.AspNetCore; [ProviderAlias("Sentry")] internal sealed class SentryAspNetCoreStructuredLoggerProvider : SentryStructuredLoggerProvider { - public SentryAspNetCoreStructuredLoggerProvider(IOptions options, IHub hub) - : this(options.Value, hub, SystemClock.Clock, CreateSdkVersion()) + public SentryAspNetCoreStructuredLoggerProvider(IHub hub) + : this(hub, SystemClock.Clock, CreateSdkVersion()) { } - internal SentryAspNetCoreStructuredLoggerProvider(SentryAspNetCoreOptions options, IHub hub, ISystemClock clock, SdkVersion sdk) - : base(options, hub, clock, sdk) + internal SentryAspNetCoreStructuredLoggerProvider(IHub hub, ISystemClock clock, SdkVersion sdk) + : base(hub, clock, sdk) { } diff --git a/src/Sentry.Extensions.Logging/BindableSentryHostOptions.cs b/src/Sentry.Extensions.Logging/BindableSentryHostOptions.cs new file mode 100644 index 0000000000..c0c3482476 --- /dev/null +++ b/src/Sentry.Extensions.Logging/BindableSentryHostOptions.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Logging; + +namespace Sentry.Extensions.Logging; + +/// +internal class BindableSentryHostOptions : BindableSentryOptions +{ + public LogLevel? MinimumBreadcrumbLevel { get; set; } + public LogLevel? MinimumEventLevel { get; set; } + + public void ApplyTo(SentryHostOptions options) + { + base.ApplyTo(options); + options.MinimumBreadcrumbLevel = MinimumBreadcrumbLevel ?? options.MinimumBreadcrumbLevel; + options.MinimumEventLevel = MinimumEventLevel ?? options.MinimumEventLevel; + } +} diff --git a/src/Sentry.Extensions.Logging/BindableSentryLoggingOptions.cs b/src/Sentry.Extensions.Logging/BindableSentryLoggingOptions.cs index 299e61a21c..e7ed493305 100644 --- a/src/Sentry.Extensions.Logging/BindableSentryLoggingOptions.cs +++ b/src/Sentry.Extensions.Logging/BindableSentryLoggingOptions.cs @@ -2,18 +2,14 @@ namespace Sentry.Extensions.Logging; -/// -internal class BindableSentryLoggingOptions : BindableSentryOptions +internal class BindableSentryLoggingOptions { public LogLevel? MinimumBreadcrumbLevel { get; set; } public LogLevel? MinimumEventLevel { get; set; } - public bool? InitializeSdk { get; set; } public void ApplyTo(SentryLoggingOptions options) { - base.ApplyTo(options); options.MinimumBreadcrumbLevel = MinimumBreadcrumbLevel ?? options.MinimumBreadcrumbLevel; options.MinimumEventLevel = MinimumEventLevel ?? options.MinimumEventLevel; - options.InitializeSdk = InitializeSdk ?? options.InitializeSdk; } } diff --git a/src/Sentry.Extensions.Logging/Extensions/DependencyInjection/ServiceCollectionExtensions.cs b/src/Sentry.Extensions.Logging/Extensions/DependencyInjection/ServiceCollectionExtensions.cs index 2c19f126a0..e12fc8f020 100644 --- a/src/Sentry.Extensions.Logging/Extensions/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Sentry.Extensions.Logging/Extensions/DependencyInjection/ServiceCollectionExtensions.cs @@ -13,30 +13,41 @@ namespace Sentry.Extensions.Logging.Extensions.DependencyInjection; public static class ServiceCollectionExtensions { /// - /// Adds Sentry's services to the + /// Adds Sentry's services to the , initializing Sentry with + /// when the hub is first resolved. /// /// The services. public static IServiceCollection AddSentry(this IServiceCollection services) - where TOptions : SentryLoggingOptions, new() + where TOptions : SentryHostOptions, new() + => services.AddSentry(initializeSdk: true); + + internal static IServiceCollection AddSentry(this IServiceCollection services, bool initializeSdk) + where TOptions : SentryHostOptions, new() { services.TryAddSingleton( c => c.GetRequiredService>().Value); - services.TryAddTransient(c => c.GetRequiredService()); - services.TryAddTransient(c => c.GetRequiredService>()()); - - services.TryAddSingleton>(c => + if (initializeSdk) { - var options = c.GetRequiredService>().Value; - - if (options.InitializeSdk) + services.TryAddSingleton>(c => { + var options = c.GetRequiredService>().Value; var hub = SentrySdk.InitHub(options); SentrySdk.UseHub(hub); - } + options.ApplyConfigureScopeCallbacks(hub); + + return () => HubAdapter.Instance; + }); + } - return () => HubAdapter.Instance; - }); + return services.AddSentryHub(); + } + + internal static IServiceCollection AddSentryHub(this IServiceCollection services) + { + services.TryAddTransient(c => c.GetRequiredService()); + services.TryAddTransient(c => c.GetRequiredService>()()); + services.TryAddSingleton>(_ => () => HubAdapter.Instance); // Custom handler for HttpClientFactory. // Must be singleton: https://github.com/getsentry/sentry-dotnet/issues/785 diff --git a/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs b/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs index 7731288078..cf7f7264a8 100644 --- a/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs +++ b/src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs @@ -21,26 +21,12 @@ public static class LoggingBuilderExtensions public static ILoggingBuilder AddSentry(this ILoggingBuilder builder) => builder.AddSentry((Action?)null); - /// - /// Adds the Sentry logging integration. - /// - /// The builder. - /// The DSN. - public static ILoggingBuilder AddSentry(this ILoggingBuilder builder, string dsn) - => builder.AddSentry(o => o.Dsn = dsn); - /// /// Adds the Sentry logging integration. /// /// The builder. /// The options configuration. public static ILoggingBuilder AddSentry(this ILoggingBuilder builder, Action? optionsConfiguration) - => builder.AddSentry(optionsConfiguration); - - internal static ILoggingBuilder AddSentry( - this ILoggingBuilder builder, - Action? optionsConfiguration) - where TOptions : SentryLoggingOptions, new() { builder.AddConfiguration(); @@ -49,14 +35,14 @@ internal static ILoggingBuilder AddSentry( builder.Services.Configure(optionsConfiguration); } - builder.Services.AddSingleton, SentryLoggingOptionsSetup>(); + builder.Services.AddSingleton, SentryLoggingOptionsSetup>(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.Services.AddSentry(); + builder.Services.AddSentryHub(); // All logs should flow to the SentryLogger, regardless of level. - // Filtering of events is handled in SentryLogger, using SentryOptions.MinimumEventLevel - // Filtering of breadcrumbs is handled in SentryLogger, using SentryOptions.MinimumBreadcrumbLevel + // Filtering of events is handled in SentryLogger, using SentryLoggingOptions.MinimumEventLevel + // Filtering of breadcrumbs is handled in SentryLogger, using SentryLoggingOptions.MinimumBreadcrumbLevel builder.AddFilter(_ => true); // Logs from the SentryLogger should not flow to the SentryStructuredLogger as this may cause recursive invocations. diff --git a/src/Sentry.Extensions.Logging/SentryHostOptions.cs b/src/Sentry.Extensions.Logging/SentryHostOptions.cs new file mode 100644 index 0000000000..b6b86266e4 --- /dev/null +++ b/src/Sentry.Extensions.Logging/SentryHostOptions.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.Logging; + +namespace Sentry.Extensions.Logging; + +/// +/// Options for integrations that initialize Sentry and also send log entries to it, such as ASP.NET Core and MAUI. +/// +/// +public abstract class SentryHostOptions : SentryOptions +{ + internal SentryLoggingOptions Logging { get; } = new(); + + /// + public LogLevel MinimumBreadcrumbLevel + { + get => Logging.MinimumBreadcrumbLevel; + set => Logging.MinimumBreadcrumbLevel = value; + } + + /// + public LogLevel MinimumEventLevel + { + get => Logging.MinimumEventLevel; + set => Logging.MinimumEventLevel = value; + } + + /// + /// Add a callback to configure the scope upon SDK initialization + /// + /// The function to invoke when initializing the SDK + public void ConfigureScope(Action action) => ConfigureScopeCallbacks = ConfigureScopeCallbacks.Concat(new[] { action }).ToArray(); + + /// + /// List of callbacks to be invoked when initializing the SDK + /// + internal Action[] ConfigureScopeCallbacks { get; set; } = Array.Empty>(); + + internal void ApplyConfigureScopeCallbacks(IHub hub) + { + foreach (var callback in ConfigureScopeCallbacks) + { + hub.ConfigureScope(callback); + } + } +} diff --git a/src/Sentry.Extensions.Logging/SentryHostOptionsSetup.cs b/src/Sentry.Extensions.Logging/SentryHostOptionsSetup.cs new file mode 100644 index 0000000000..b08091ae3e --- /dev/null +++ b/src/Sentry.Extensions.Logging/SentryHostOptionsSetup.cs @@ -0,0 +1,28 @@ +#if NET6_0_OR_GREATER +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Configuration; +using Microsoft.Extensions.Options; + +namespace Sentry.Extensions.Logging; + +internal sealed class SentryHostOptionsSetup : IConfigureOptions + where TOptions : SentryHostOptions +{ + private readonly IConfiguration _config; + + public SentryHostOptionsSetup(ILoggerProviderConfiguration config) + { + ArgumentNullException.ThrowIfNull(config); + _config = config.Configuration; + } + + public void Configure(TOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + var bindable = new BindableSentryHostOptions(); + _config.Bind(bindable); + bindable.ApplyTo(options); + } +} +#endif diff --git a/src/Sentry.Extensions.Logging/SentryLoggerFactoryExtensions.cs b/src/Sentry.Extensions.Logging/SentryLoggerFactoryExtensions.cs index c2f2fc1e9e..f9fd8fae8d 100644 --- a/src/Sentry.Extensions.Logging/SentryLoggerFactoryExtensions.cs +++ b/src/Sentry.Extensions.Logging/SentryLoggerFactoryExtensions.cs @@ -17,8 +17,8 @@ public static class SentryLoggerFactoryExtensions /// Adds the Sentry logging integration. /// /// - /// This method does not need to be called when calling `UseSentry` with ASP.NET Core - /// since that integrates with the logging framework automatically. + /// This method does not initialize Sentry. Initialize it separately, with + /// or a framework integration such as UseSentry. /// /// The factory. /// The options configuration. @@ -30,34 +30,7 @@ public static ILoggerFactory AddSentry( optionsConfiguration?.Invoke(options); - if (options.DiagnosticLogger == null) - { - var logger = factory.CreateLogger(); - options.DiagnosticLogger = new MelDiagnosticLogger(logger, options.DiagnosticLevel); - } - - IHub hub; - if (options.InitializeSdk) - { - if (SentrySdk.IsEnabled && options.Dsn is null) - { - options.LogWarning("Not calling Init from {0} because SDK is already enabled and no DSN was provided to the integration", nameof(SentryLoggerFactoryExtensions)); - hub = HubAdapter.Instance; - } - else - { - options.LogDebug("Initializing from {0} and swapping current Hub.", nameof(SentryLoggerFactoryExtensions)); - hub = SentrySdk.InitHub(options); - SentrySdk.UseHub(hub); - } - } - else - { - // Access to whatever the SentrySdk points to (disabled or initialized via SentrySdk.Init) - hub = HubAdapter.Instance; - } - - factory.AddProvider(new SentryLoggerProvider(hub, SystemClock.Clock, options)); + factory.AddProvider(new SentryLoggerProvider(HubAdapter.Instance, SystemClock.Clock, options)); return factory; } } diff --git a/src/Sentry.Extensions.Logging/SentryLoggerProvider.cs b/src/Sentry.Extensions.Logging/SentryLoggerProvider.cs index 034e7b4694..ddb50d931b 100644 --- a/src/Sentry.Extensions.Logging/SentryLoggerProvider.cs +++ b/src/Sentry.Extensions.Logging/SentryLoggerProvider.cs @@ -61,12 +61,6 @@ internal SentryLoggerProvider( } } }); - - // Add scope configuration to hub from options - foreach (var callback in options.ConfigureScopeCallbacks) - { - hub.ConfigureScope(callback); - } } } diff --git a/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs b/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs index 3014f7cd0e..cd934d6f68 100644 --- a/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs +++ b/src/Sentry.Extensions.Logging/SentryLoggingOptions.cs @@ -5,8 +5,11 @@ namespace Sentry.Extensions.Logging; /// /// Sentry logging integration options /// -/// -public class SentryLoggingOptions : SentryOptions +/// +/// These only configure which log entries are sent to Sentry. Sentry itself is initialized separately, with +/// or a framework integration such as UseSentry. +/// +public class SentryLoggingOptions { /// /// Gets or sets the minimum breadcrumb level. @@ -30,24 +33,8 @@ public class SentryLoggingOptions : SentryOptions /// public LogLevel MinimumEventLevel { get; set; } = LogLevel.Error; - /// - /// Whether to initialize this SDK through this integration - /// - public bool InitializeSdk { get; set; } = true; - - /// - /// Add a callback to configure the scope upon SDK initialization - /// - /// The function to invoke when initializing the SDK - public void ConfigureScope(Action action) => ConfigureScopeCallbacks = ConfigureScopeCallbacks.Concat(new[] { action }).ToArray(); - /// /// Log entry filters /// internal ILogEntryFilter[] Filters { get; set; } = Array.Empty(); - - /// - /// List of callbacks to be invoked when initializing the SDK - /// - internal Action[] ConfigureScopeCallbacks { get; set; } = Array.Empty>(); } diff --git a/src/Sentry.Extensions.Logging/SentryLoggingOptionsExtensions.cs b/src/Sentry.Extensions.Logging/SentryLoggingOptionsExtensions.cs index a536de7cb8..a89390b4c7 100644 --- a/src/Sentry.Extensions.Logging/SentryLoggingOptionsExtensions.cs +++ b/src/Sentry.Extensions.Logging/SentryLoggingOptionsExtensions.cs @@ -35,4 +35,14 @@ public static void AddLogEntryFilter( this SentryLoggingOptions options, Func filter) => options.AddLogEntryFilter(new DelegateLogEntryFilter(filter)); + + /// + public static void AddLogEntryFilter(this SentryHostOptions options, ILogEntryFilter filter) + => options.Logging.AddLogEntryFilter(filter); + + /// + public static void AddLogEntryFilter( + this SentryHostOptions options, + Func filter) + => options.Logging.AddLogEntryFilter(filter); } diff --git a/src/Sentry.Extensions.Logging/SentryStructuredLogger.cs b/src/Sentry.Extensions.Logging/SentryStructuredLogger.cs index 2b7c2c1aed..6eae15193f 100644 --- a/src/Sentry.Extensions.Logging/SentryStructuredLogger.cs +++ b/src/Sentry.Extensions.Logging/SentryStructuredLogger.cs @@ -7,15 +7,13 @@ namespace Sentry.Extensions.Logging; internal sealed class SentryStructuredLogger : ILogger { private readonly string? _categoryName; - private readonly SentryLoggingOptions _options; private readonly IHub _hub; private readonly ISystemClock _clock; private readonly SdkVersion _sdk; - internal SentryStructuredLogger(string categoryName, SentryLoggingOptions options, IHub hub, ISystemClock clock, SdkVersion sdk) + internal SentryStructuredLogger(string categoryName, IHub hub, ISystemClock clock, SdkVersion sdk) { _categoryName = categoryName; - _options = options; _clock = clock; _hub = hub; _sdk = sdk; @@ -34,7 +32,7 @@ public bool IsEnabled(LogLevel logLevel) public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { - if (!IsEnabled(logLevel)) + if (!IsEnabled(logLevel) || _hub.GetSentryOptions() is not { } options) { return; } @@ -52,7 +50,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } catch (FormatException e) { - _options.DiagnosticLogger?.LogError(e, "Template string does not match the provided argument. The Log will be dropped."); + options.DiagnosticLogger?.LogError(e, "Template string does not match the provided argument. The Log will be dropped."); return; } @@ -87,7 +85,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except }; var scope = _hub.GetScope(); - log.SetDefaultAttributes(_options, scope, _sdk); + log.SetDefaultAttributes(options, scope, _sdk); log.SetOrigin("auto.log.extensions_logging"); if (_categoryName is not null) diff --git a/src/Sentry.Extensions.Logging/SentryStructuredLoggerProvider.cs b/src/Sentry.Extensions.Logging/SentryStructuredLoggerProvider.cs index bf74a36da0..b55c95e15f 100644 --- a/src/Sentry.Extensions.Logging/SentryStructuredLoggerProvider.cs +++ b/src/Sentry.Extensions.Logging/SentryStructuredLoggerProvider.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Sentry.Infrastructure; namespace Sentry.Extensions.Logging; @@ -10,24 +9,17 @@ namespace Sentry.Extensions.Logging; [ProviderAlias("Sentry")] internal class SentryStructuredLoggerProvider : ILoggerProvider { - private readonly SentryLoggingOptions _options; private readonly IHub _hub; private readonly ISystemClock _clock; private readonly SdkVersion _sdk; - public SentryStructuredLoggerProvider(IOptions options, IHub hub) - : this(options.Value, hub, SystemClock.Clock, CreateSdkVersion()) + public SentryStructuredLoggerProvider(IHub hub) + : this(hub, SystemClock.Clock, CreateSdkVersion()) { } - internal SentryStructuredLoggerProvider(IHub hub, ISystemClock clock, SentryLoggingOptions options) - : this(options, hub, clock, CreateSdkVersion()) + internal SentryStructuredLoggerProvider(IHub hub, ISystemClock clock, SdkVersion sdk) { - } - - internal SentryStructuredLoggerProvider(SentryLoggingOptions options, IHub hub, ISystemClock clock, SdkVersion sdk) - { - _options = options; _hub = hub; _clock = clock; _sdk = sdk; @@ -35,7 +27,7 @@ internal SentryStructuredLoggerProvider(SentryLoggingOptions options, IHub hub, public ILogger CreateLogger(string categoryName) { - return new SentryStructuredLogger(categoryName, _options, _hub, _clock, _sdk); + return new SentryStructuredLogger(categoryName, _hub, _clock, _sdk); } public void Dispose() diff --git a/src/Sentry.Maui/BindableSentryMauiOptions.cs b/src/Sentry.Maui/BindableSentryMauiOptions.cs index f4f98e1ad0..3a79156eec 100644 --- a/src/Sentry.Maui/BindableSentryMauiOptions.cs +++ b/src/Sentry.Maui/BindableSentryMauiOptions.cs @@ -3,7 +3,7 @@ namespace Sentry.Maui; /// -internal class BindableSentryMauiOptions : BindableSentryLoggingOptions +internal class BindableSentryMauiOptions : BindableSentryHostOptions { public bool? IncludeTextInBreadcrumbs { get; set; } public bool? IncludeTitleInBreadcrumbs { get; set; } diff --git a/src/Sentry.Maui/Internal/SentryMauiInitializer.cs b/src/Sentry.Maui/Internal/SentryMauiInitializer.cs index 3a59dc4c81..209f3d6948 100644 --- a/src/Sentry.Maui/Internal/SentryMauiInitializer.cs +++ b/src/Sentry.Maui/Internal/SentryMauiInitializer.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Options; +using Sentry.Extensibility; namespace Sentry.Maui.Internal; @@ -14,6 +15,7 @@ public void Initialize(IServiceProvider services) // Initialize the Sentry SDK. var disposable = SentrySdk.Init(options); + options.ApplyConfigureScopeCallbacks(HubAdapter.Instance); // Register the return value from initializing the SDK with the disposer. // This will ensure that it gets disposed when the service provider is disposed. diff --git a/src/Sentry.Maui/Internal/SentryMauiLoggerProvider.cs b/src/Sentry.Maui/Internal/SentryMauiLoggerProvider.cs index dddd59bae2..98f0764438 100644 --- a/src/Sentry.Maui/Internal/SentryMauiLoggerProvider.cs +++ b/src/Sentry.Maui/Internal/SentryMauiLoggerProvider.cs @@ -12,12 +12,12 @@ namespace Sentry.Maui.Internal; internal sealed class SentryMauiLoggerProvider : SentryLoggerProvider { public SentryMauiLoggerProvider(IOptions options, IHub hub) - : base(options, hub) + : base(hub, SystemClock.Clock, options.Value.Logging) { } internal SentryMauiLoggerProvider(SentryMauiOptions options, IHub hub, ISystemClock clock) - : base(hub, clock, options) + : base(hub, clock, options.Logging) { } } diff --git a/src/Sentry.Maui/Internal/SentryMauiOptionsSetup.cs b/src/Sentry.Maui/Internal/SentryMauiOptionsSetup.cs index 7436d0720e..f759e7861d 100644 --- a/src/Sentry.Maui/Internal/SentryMauiOptionsSetup.cs +++ b/src/Sentry.Maui/Internal/SentryMauiOptionsSetup.cs @@ -33,9 +33,6 @@ public void Configure(SentryMauiOptions options) // NOTE: Anything set here will overwrite options set by the user. // For option defaults that can be changed, use the constructor in SentryMauiOptions instead. - // We'll initialize the SDK in SentryMauiInitializer - options.InitializeSdk = false; - // Global Mode makes sense for client apps options.IsGlobalModeEnabled = true; diff --git a/src/Sentry.Maui/Internal/SentryMauiStructuredLoggerProvider.cs b/src/Sentry.Maui/Internal/SentryMauiStructuredLoggerProvider.cs index a72ffafc46..79087cddd5 100644 --- a/src/Sentry.Maui/Internal/SentryMauiStructuredLoggerProvider.cs +++ b/src/Sentry.Maui/Internal/SentryMauiStructuredLoggerProvider.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Sentry.Extensions.Logging; using Sentry.Infrastructure; @@ -11,13 +10,13 @@ namespace Sentry.Maui.Internal; [ProviderAlias("Sentry")] internal sealed class SentryMauiStructuredLoggerProvider : SentryStructuredLoggerProvider { - public SentryMauiStructuredLoggerProvider(IOptions options, IHub hub) - : this(options.Value, hub, SystemClock.Clock, CreateSdkVersion()) + public SentryMauiStructuredLoggerProvider(IHub hub) + : this(hub, SystemClock.Clock, CreateSdkVersion()) { } - internal SentryMauiStructuredLoggerProvider(SentryMauiOptions options, IHub hub, ISystemClock clock, SdkVersion sdk) - : base(options, hub, clock, sdk) + internal SentryMauiStructuredLoggerProvider(IHub hub, ISystemClock clock, SdkVersion sdk) + : base(hub, clock, sdk) { } diff --git a/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs b/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs index 579c2b63e6..647ae61756 100644 --- a/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs +++ b/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs @@ -78,7 +78,7 @@ public static MauiAppBuilder UseSentry(this MauiAppBuilder builder, // This is ultimately the class that enables all the MauiElementEventBinders above services.TryAddSingleton(); - services.AddSentry(); + services.AddSentry(initializeSdk: false); builder.RegisterMauiEventsBinder(); diff --git a/src/Sentry.Maui/SentryMauiOptions.cs b/src/Sentry.Maui/SentryMauiOptions.cs index 17038bf747..5c436afab0 100644 --- a/src/Sentry.Maui/SentryMauiOptions.cs +++ b/src/Sentry.Maui/SentryMauiOptions.cs @@ -7,7 +7,7 @@ namespace Sentry.Maui; /// /// Sentry MAUI integration options /// -public class SentryMauiOptions : SentryLoggingOptions +public class SentryMauiOptions : SentryHostOptions { /// /// Creates a new instance of . diff --git a/test/Sentry.AspNetCore.Blazor.WebAssembly.Tests/WebAssemblyHostBuilderExtensionsTests.cs b/test/Sentry.AspNetCore.Blazor.WebAssembly.Tests/WebAssemblyHostBuilderExtensionsTests.cs new file mode 100644 index 0000000000..6568883fd8 --- /dev/null +++ b/test/Sentry.AspNetCore.Blazor.WebAssembly.Tests/WebAssemblyHostBuilderExtensionsTests.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Sentry.AspNetCore.Blazor.WebAssembly.Tests; + +public class WebAssemblyHostBuilderExtensionsTests : IDisposable +{ + private readonly List _events = new(); + + public void Dispose() => SentrySdk.Close(); + + private ServiceProvider GetSut(Action configureOptions) + { + var services = new ServiceCollection(); + services.AddSingleton(new FakeNavigationManager()); + services.AddLogging(logging => logging.AddSentryBlazor(o => + { + o.Dsn = ValidDsn; + o.BackgroundWorker = Substitute.For(); + o.AutoSessionTracking = false; + o.SetBeforeSend((e, _) => + { + _events.Add(e); + return null; + }); + configureOptions(o); + })); + return services.BuildServiceProvider(); + } + + [Fact] + public void UseSentry_MinimumEventLevel_AppliesToLogger() + { + using var provider = GetSut(o => o.MinimumEventLevel = LogLevel.Critical); + var logger = provider.GetRequiredService().CreateLogger("test_category"); + + logger.LogError("below the configured level"); + logger.LogCritical("at the configured level"); + + _events.Should().ContainSingle().Which.Message!.Message.Should().Be("at the configured level"); + } +} diff --git a/test/Sentry.AspNetCore.Grpc.Tests/allsettings.json b/test/Sentry.AspNetCore.Grpc.Tests/allsettings.json index 4be2835072..880d7ce1e5 100644 --- a/test/Sentry.AspNetCore.Grpc.Tests/allsettings.json +++ b/test/Sentry.AspNetCore.Grpc.Tests/allsettings.json @@ -6,7 +6,6 @@ "IncludeActivityData": true, "MinimumBreadcrumbLevel": "Error", "MinimumEventLevel": "Critical", - "InitializeSdk": "false", "MaxBreadcrumbs": "999", "SampleRate": "1", "Release": "7f5d9a1", diff --git a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt index f6ceb2a3c3..463241570b 100644 --- a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt +++ b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt @@ -39,7 +39,7 @@ namespace Sentry.AspNetCore public static string? TryGetHttpPath(this Sentry.TransactionSamplingContext samplingContext) { } public static string? TryGetHttpRoute(this Sentry.TransactionSamplingContext samplingContext) { } } - public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryLoggingOptions + public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryHostOptions { public SentryAspNetCoreOptions() { } public bool AdjustStandardEnvironmentNameCasing { get; set; } diff --git a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt index f6ceb2a3c3..463241570b 100644 --- a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt +++ b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt @@ -39,7 +39,7 @@ namespace Sentry.AspNetCore public static string? TryGetHttpPath(this Sentry.TransactionSamplingContext samplingContext) { } public static string? TryGetHttpRoute(this Sentry.TransactionSamplingContext samplingContext) { } } - public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryLoggingOptions + public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryHostOptions { public SentryAspNetCoreOptions() { } public bool AdjustStandardEnvironmentNameCasing { get; set; } diff --git a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt index f6ceb2a3c3..463241570b 100644 --- a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt +++ b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt @@ -39,7 +39,7 @@ namespace Sentry.AspNetCore public static string? TryGetHttpPath(this Sentry.TransactionSamplingContext samplingContext) { } public static string? TryGetHttpRoute(this Sentry.TransactionSamplingContext samplingContext) { } } - public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryLoggingOptions + public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryHostOptions { public SentryAspNetCoreOptions() { } public bool AdjustStandardEnvironmentNameCasing { get; set; } diff --git a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt index f6ceb2a3c3..463241570b 100644 --- a/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt +++ b/test/Sentry.AspNetCore.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt @@ -39,7 +39,7 @@ namespace Sentry.AspNetCore public static string? TryGetHttpPath(this Sentry.TransactionSamplingContext samplingContext) { } public static string? TryGetHttpRoute(this Sentry.TransactionSamplingContext samplingContext) { } } - public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryLoggingOptions + public class SentryAspNetCoreOptions : Sentry.Extensions.Logging.SentryHostOptions { public SentryAspNetCoreOptions() { } public bool AdjustStandardEnvironmentNameCasing { get; set; } diff --git a/test/Sentry.AspNetCore.Tests/AspNetCoreSentryWebHostBuilder.IntegrationTests.cs b/test/Sentry.AspNetCore.Tests/AspNetCoreSentryWebHostBuilder.IntegrationTests.cs index 455bf8c0a2..3c38c2471c 100644 --- a/test/Sentry.AspNetCore.Tests/AspNetCoreSentryWebHostBuilder.IntegrationTests.cs +++ b/test/Sentry.AspNetCore.Tests/AspNetCoreSentryWebHostBuilder.IntegrationTests.cs @@ -46,13 +46,4 @@ public void UseSentry_DisableDsnString_DisabledSdk() Assert.False(SentrySdk.IsEnabled); } - - [Fact] - public void UseSentry_OptionsNotInitializeSdk_DisabledSdk() - { - _ = _webHostBuilder.UseSentry(o => o.InitializeSdk = false) - .Build(); - - Assert.False(SentrySdk.IsEnabled); - } } diff --git a/test/Sentry.AspNetCore.Tests/IntegrationMockedBackgroundWorker.cs b/test/Sentry.AspNetCore.Tests/IntegrationMockedBackgroundWorker.cs index 4869455bf4..12abc4aca3 100644 --- a/test/Sentry.AspNetCore.Tests/IntegrationMockedBackgroundWorker.cs +++ b/test/Sentry.AspNetCore.Tests/IntegrationMockedBackgroundWorker.cs @@ -37,7 +37,7 @@ public IntegrationMockedBackgroundWorker(ITestOutputHelper output) [Fact] public async Task DisabledSdk_UnhandledException_NoEventCaptured() { - Configure = o => o.InitializeSdk = false; + Configure = o => o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; Build(); _ = await HttpClient.GetAsync("/throw"); @@ -49,7 +49,7 @@ public async Task DisabledSdk_UnhandledException_NoEventCaptured() [Fact] public void DisabledSdk_WithLogger_NoEventCaptured() { - Configure = o => o.InitializeSdk = false; + Configure = o => o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; Build(); var logger = ServiceProvider.GetRequiredService>(); @@ -262,7 +262,6 @@ public void AllSettingsViaJson() Assert.True(options.IncludeActivityData); Assert.Equal(LogLevel.Error, options.MinimumBreadcrumbLevel); Assert.Equal(LogLevel.Critical, options.MinimumEventLevel); - Assert.False(options.InitializeSdk); Assert.Equal(999, options.MaxBreadcrumbs); Assert.Equal(1, options.SampleRate); Assert.Equal("7f5d9a1", options.Release); diff --git a/test/Sentry.AspNetCore.Tests/MiddlewareLoggerIntegration.cs b/test/Sentry.AspNetCore.Tests/MiddlewareLoggerIntegration.cs index d869be9ff9..fc9d1df61e 100644 --- a/test/Sentry.AspNetCore.Tests/MiddlewareLoggerIntegration.cs +++ b/test/Sentry.AspNetCore.Tests/MiddlewareLoggerIntegration.cs @@ -35,11 +35,7 @@ private class Fixture : IDisposable public Fixture() { HubAccessor = () => Hub; - var loggingOptions = new SentryLoggingOptions - { - InitializeSdk = false, - }; - loggingOptions.InitializeSdk = false; + var loggingOptions = new SentryLoggingOptions(); Client.When(client => client.CaptureEvent(Arg.Any(), Arg.Any(), Arg.Any())) .Do(callback => callback.Arg().Evaluate()); diff --git a/test/Sentry.AspNetCore.Tests/SentryAspNetCoreOptionsSetupTests.cs b/test/Sentry.AspNetCore.Tests/SentryAspNetCoreOptionsSetupTests.cs index 916b2a615d..3aa2722d81 100644 --- a/test/Sentry.AspNetCore.Tests/SentryAspNetCoreOptionsSetupTests.cs +++ b/test/Sentry.AspNetCore.Tests/SentryAspNetCoreOptionsSetupTests.cs @@ -49,7 +49,7 @@ public void Filters_KestrelApplicationEvent_NoException_Filtered() sut.Configure(_target); //Assert - Assert.Contains(_target.Filters, f => f.Filter("Microsoft.AspNetCore.Server.Kestrel", LogLevel.Critical, 13, null)); + Assert.Contains(_target.Logging.Filters, f => f.Filter("Microsoft.AspNetCore.Server.Kestrel", LogLevel.Critical, 13, null)); } [Fact] @@ -62,7 +62,7 @@ public void Filters_KestrelApplicationEvent_WithException_Filtered() sut.Configure(_target); // Assert - Assert.Contains(_target.Filters, f => f.Filter("Microsoft.AspNetCore.Server.Kestrel", LogLevel.Critical, 13, new Exception())); + Assert.Contains(_target.Logging.Filters, f => f.Filter("Microsoft.AspNetCore.Server.Kestrel", LogLevel.Critical, 13, new Exception())); } [Fact] @@ -75,7 +75,7 @@ public void Filters_KestrelEventId1_WithException_NotFiltered() sut.Configure(_target); // Assert - Assert.DoesNotContain(_target.Filters, f => f.Filter("Microsoft.AspNetCore.Server.Kestrel", LogLevel.Trace, 1, null)); + Assert.DoesNotContain(_target.Logging.Filters, f => f.Filter("Microsoft.AspNetCore.Server.Kestrel", LogLevel.Trace, 1, null)); } [Theory] diff --git a/test/Sentry.AspNetCore.Tests/SentryAspNetCoreStructuredLoggerProviderTests.cs b/test/Sentry.AspNetCore.Tests/SentryAspNetCoreStructuredLoggerProviderTests.cs index 18d3092333..5ce57761c3 100644 --- a/test/Sentry.AspNetCore.Tests/SentryAspNetCoreStructuredLoggerProviderTests.cs +++ b/test/Sentry.AspNetCore.Tests/SentryAspNetCoreStructuredLoggerProviderTests.cs @@ -6,21 +6,18 @@ namespace Sentry.AspNetCore.Tests; -public class SentryAspNetCoreStructuredLoggerProviderTests +public class SentryAspNetCoreStructuredLoggerProviderTests : IDisposable { private class Fixture { - public IOptions Options { get; } public IHub Hub { get; } public MockClock Clock { get; } public SdkVersion Sdk { get; } public Fixture() { - var loggingOptions = new SentryAspNetCoreOptions(); - - Options = Microsoft.Extensions.Options.Options.Create(loggingOptions); Hub = Substitute.For(); + SentryClientExtensions.SentryOptionsForTestingOnly = new SentryOptions(); Clock = new MockClock(); Sdk = new SdkVersion { @@ -33,12 +30,14 @@ public Fixture() public SentryAspNetCoreStructuredLoggerProvider GetSut() { - return new SentryAspNetCoreStructuredLoggerProvider(Options.Value, Hub, Clock, Sdk); + return new SentryAspNetCoreStructuredLoggerProvider(Hub, Clock, Sdk); } } private readonly Fixture _fixture = new(); + public void Dispose() => SentryClientExtensions.SentryOptionsForTestingOnly = null; + [Fact] public void Type_CustomAttributes_HasProviderAliasAttribute() { @@ -55,7 +54,6 @@ public void Ctor_DependencyInjection_CanCreate() using var services = new ServiceCollection() .AddLogging() .AddSingleton() - .AddSingleton(_fixture.Options) .AddSingleton(_fixture.Hub) .BuildServiceProvider(); @@ -84,7 +82,6 @@ public void CreateLogger_DependencyInjection_CanLog() using var services = new ServiceCollection() .AddLogging() .AddSingleton() - .AddSingleton(_fixture.Options) .AddSingleton(_fixture.Hub) .BuildServiceProvider(); diff --git a/test/Sentry.AspNetCore.Tests/SentryWebHostBuilderExtensionsTests.cs b/test/Sentry.AspNetCore.Tests/SentryWebHostBuilderExtensionsTests.cs index 6ae6378710..a9c8d9bd29 100644 --- a/test/Sentry.AspNetCore.Tests/SentryWebHostBuilderExtensionsTests.cs +++ b/test/Sentry.AspNetCore.Tests/SentryWebHostBuilderExtensionsTests.cs @@ -61,7 +61,7 @@ public void UseSentry_DisableDsnString_ServicesRegistered(Action assert) { - _ = WebHostBuilder.UseSentry(o => o.InitializeSdk = false); + _ = WebHostBuilder.UseSentry(o => o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue); assert(Services); } @@ -88,7 +88,7 @@ public void UseSentry_Logging_AddLoggerProviders() #endif WebHostBuilder.UseSentry((SentryAspNetCoreOptions options) => { - options.InitializeSdk = false; + options.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; }); using var serviceProvider = Services.BuildServiceProvider(); @@ -104,7 +104,7 @@ public void UseSentry_Logging_AddLoggerFilterRules() { WebHostBuilder.UseSentry((SentryAspNetCoreOptions options) => { - options.InitializeSdk = false; + options.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; }); using var serviceProvider = Services.BuildServiceProvider(); diff --git a/test/Sentry.AspNetCore.Tests/allsettings.json b/test/Sentry.AspNetCore.Tests/allsettings.json index 427091798c..6edd4090f7 100644 --- a/test/Sentry.AspNetCore.Tests/allsettings.json +++ b/test/Sentry.AspNetCore.Tests/allsettings.json @@ -6,7 +6,6 @@ "IncludeActivityData": true, "MinimumBreadcrumbLevel": "Error", "MinimumEventLevel": "Critical", - "InitializeSdk": "false", "MaxBreadcrumbs": "999", "SampleRate": 1.0, "Release": "7f5d9a1", diff --git a/test/Sentry.DiagnosticSource.IntegrationTests/SqlListenerTests.verify.cs b/test/Sentry.DiagnosticSource.IntegrationTests/SqlListenerTests.verify.cs index b9f4250999..20fa73ed45 100644 --- a/test/Sentry.DiagnosticSource.IntegrationTests/SqlListenerTests.verify.cs +++ b/test/Sentry.DiagnosticSource.IntegrationTests/SqlListenerTests.verify.cs @@ -62,7 +62,7 @@ public async Task LoggingAsync() Skip.If(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); var transport = new RecordingTransport(); - void ApplyOptions(SentryLoggingOptions sentryOptions) + void ApplyOptions(SentryOptions sentryOptions) { sentryOptions.AttachStacktrace = false; sentryOptions.TracesSampleRate = 1; @@ -72,7 +72,7 @@ void ApplyOptions(SentryLoggingOptions sentryOptions) sentryOptions.Debug = true; } - var options = new SentryLoggingOptions(); + var options = new SentryOptions(); ApplyOptions(options); await using var database = await _fixture.SqlInstance.Build(); @@ -87,7 +87,7 @@ void ApplyOptions(SentryLoggingOptions sentryOptions) await dbContext.SaveChangesAsync(); } - var loggerFactory = LoggerFactory.Create(_ => _.AddSentry(ApplyOptions)); + var loggerFactory = LoggerFactory.Create(_ => _.AddSentry()); using (var hub = new Hub(options)) { var transaction = hub.StartTransaction("my transaction", "my operation"); diff --git a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt index 8650a342f4..26b02c5b85 100644 --- a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt +++ b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt @@ -4,7 +4,6 @@ { public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { } public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action? optionsConfiguration) { } - public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, string dsn) { } } public static class SentryLoggerFactoryExtensions { @@ -28,16 +27,23 @@ namespace Sentry.Extensions.Logging public bool IsEnabled(Sentry.SentryLevel level) { } public void Log(Sentry.SentryLevel logLevel, string message, System.Exception? exception = null, params object?[] args) { } } - public class SentryLoggingOptions : Sentry.SentryOptions + public abstract class SentryHostOptions : Sentry.SentryOptions { - public SentryLoggingOptions() { } - public bool InitializeSdk { get; set; } + protected SentryHostOptions() { } public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } public void ConfigureScope(System.Action action) { } } + public class SentryLoggingOptions + { + public SentryLoggingOptions() { } + public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } + public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } + } public static class SentryLoggingOptionsExtensions { + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, System.Func filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, System.Func filter) { } } @@ -47,6 +53,6 @@ namespace Sentry.Extensions.Logging.Extensions.DependencyInjection public static class ServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSentry(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) - where TOptions : Sentry.Extensions.Logging.SentryLoggingOptions, new () { } + where TOptions : Sentry.Extensions.Logging.SentryHostOptions, new () { } } } \ No newline at end of file diff --git a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt index 8650a342f4..26b02c5b85 100644 --- a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt +++ b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt @@ -4,7 +4,6 @@ { public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { } public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action? optionsConfiguration) { } - public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, string dsn) { } } public static class SentryLoggerFactoryExtensions { @@ -28,16 +27,23 @@ namespace Sentry.Extensions.Logging public bool IsEnabled(Sentry.SentryLevel level) { } public void Log(Sentry.SentryLevel logLevel, string message, System.Exception? exception = null, params object?[] args) { } } - public class SentryLoggingOptions : Sentry.SentryOptions + public abstract class SentryHostOptions : Sentry.SentryOptions { - public SentryLoggingOptions() { } - public bool InitializeSdk { get; set; } + protected SentryHostOptions() { } public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } public void ConfigureScope(System.Action action) { } } + public class SentryLoggingOptions + { + public SentryLoggingOptions() { } + public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } + public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } + } public static class SentryLoggingOptionsExtensions { + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, System.Func filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, System.Func filter) { } } @@ -47,6 +53,6 @@ namespace Sentry.Extensions.Logging.Extensions.DependencyInjection public static class ServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSentry(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) - where TOptions : Sentry.Extensions.Logging.SentryLoggingOptions, new () { } + where TOptions : Sentry.Extensions.Logging.SentryHostOptions, new () { } } } \ No newline at end of file diff --git a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt index 8650a342f4..26b02c5b85 100644 --- a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt +++ b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt @@ -4,7 +4,6 @@ { public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { } public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action? optionsConfiguration) { } - public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, string dsn) { } } public static class SentryLoggerFactoryExtensions { @@ -28,16 +27,23 @@ namespace Sentry.Extensions.Logging public bool IsEnabled(Sentry.SentryLevel level) { } public void Log(Sentry.SentryLevel logLevel, string message, System.Exception? exception = null, params object?[] args) { } } - public class SentryLoggingOptions : Sentry.SentryOptions + public abstract class SentryHostOptions : Sentry.SentryOptions { - public SentryLoggingOptions() { } - public bool InitializeSdk { get; set; } + protected SentryHostOptions() { } public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } public void ConfigureScope(System.Action action) { } } + public class SentryLoggingOptions + { + public SentryLoggingOptions() { } + public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } + public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } + } public static class SentryLoggingOptionsExtensions { + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, System.Func filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, System.Func filter) { } } @@ -47,6 +53,6 @@ namespace Sentry.Extensions.Logging.Extensions.DependencyInjection public static class ServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSentry(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) - where TOptions : Sentry.Extensions.Logging.SentryLoggingOptions, new () { } + where TOptions : Sentry.Extensions.Logging.SentryHostOptions, new () { } } } \ No newline at end of file diff --git a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt index 8650a342f4..26b02c5b85 100644 --- a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt +++ b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt @@ -4,7 +4,6 @@ { public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { } public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action? optionsConfiguration) { } - public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, string dsn) { } } public static class SentryLoggerFactoryExtensions { @@ -28,16 +27,23 @@ namespace Sentry.Extensions.Logging public bool IsEnabled(Sentry.SentryLevel level) { } public void Log(Sentry.SentryLevel logLevel, string message, System.Exception? exception = null, params object?[] args) { } } - public class SentryLoggingOptions : Sentry.SentryOptions + public abstract class SentryHostOptions : Sentry.SentryOptions { - public SentryLoggingOptions() { } - public bool InitializeSdk { get; set; } + protected SentryHostOptions() { } public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } public void ConfigureScope(System.Action action) { } } + public class SentryLoggingOptions + { + public SentryLoggingOptions() { } + public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } + public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } + } public static class SentryLoggingOptionsExtensions { + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, System.Func filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, System.Func filter) { } } @@ -47,6 +53,6 @@ namespace Sentry.Extensions.Logging.Extensions.DependencyInjection public static class ServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSentry(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) - where TOptions : Sentry.Extensions.Logging.SentryLoggingOptions, new () { } + where TOptions : Sentry.Extensions.Logging.SentryHostOptions, new () { } } } \ No newline at end of file diff --git a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.Net4_8.verified.txt b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.Net4_8.verified.txt index 8650a342f4..26b02c5b85 100644 --- a/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.Net4_8.verified.txt +++ b/test/Sentry.Extensions.Logging.Tests/ApiApprovalTests.Run.Net4_8.verified.txt @@ -4,7 +4,6 @@ { public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { } public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action? optionsConfiguration) { } - public static Microsoft.Extensions.Logging.ILoggingBuilder AddSentry(this Microsoft.Extensions.Logging.ILoggingBuilder builder, string dsn) { } } public static class SentryLoggerFactoryExtensions { @@ -28,16 +27,23 @@ namespace Sentry.Extensions.Logging public bool IsEnabled(Sentry.SentryLevel level) { } public void Log(Sentry.SentryLevel logLevel, string message, System.Exception? exception = null, params object?[] args) { } } - public class SentryLoggingOptions : Sentry.SentryOptions + public abstract class SentryHostOptions : Sentry.SentryOptions { - public SentryLoggingOptions() { } - public bool InitializeSdk { get; set; } + protected SentryHostOptions() { } public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } public void ConfigureScope(System.Action action) { } } + public class SentryLoggingOptions + { + public SentryLoggingOptions() { } + public Microsoft.Extensions.Logging.LogLevel MinimumBreadcrumbLevel { get; set; } + public Microsoft.Extensions.Logging.LogLevel MinimumEventLevel { get; set; } + } public static class SentryLoggingOptionsExtensions { + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } + public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryHostOptions options, System.Func filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, Sentry.Extensions.Logging.ILogEntryFilter filter) { } public static void AddLogEntryFilter(this Sentry.Extensions.Logging.SentryLoggingOptions options, System.Func filter) { } } @@ -47,6 +53,6 @@ namespace Sentry.Extensions.Logging.Extensions.DependencyInjection public static class ServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSentry(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) - where TOptions : Sentry.Extensions.Logging.SentryLoggingOptions, new () { } + where TOptions : Sentry.Extensions.Logging.SentryHostOptions, new () { } } } \ No newline at end of file diff --git a/test/Sentry.Extensions.Logging.Tests/ConfigurationOptionsTests.cs b/test/Sentry.Extensions.Logging.Tests/ConfigurationOptionsTests.cs index 2c66765548..4a6fcc815e 100644 --- a/test/Sentry.Extensions.Logging.Tests/ConfigurationOptionsTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/ConfigurationOptionsTests.cs @@ -29,12 +29,7 @@ public IServiceProvider GetSut() { var configuration = Builder.Build(); var services = new ServiceCollection(); - _ = services.AddLogging(builder => builder.AddConfiguration(configuration).AddSentry(o => - { - o.BackgroundWorker = Substitute.For(); - o.InitNativeSdks = false; - o.AutoSessionTracking = false; - })); + _ = services.AddLogging(builder => builder.AddConfiguration(configuration).AddSentry()); return services.BuildServiceProvider(); } } @@ -49,49 +44,11 @@ public void SentryLoggingOptions_ValuesFromAppSettings() using (new AssertionScope()) { - sentryLoggingOptions.InitializeSdk.Should().BeFalse(); sentryLoggingOptions.MinimumBreadcrumbLevel.Should().Be(LogLevel.Warning); sentryLoggingOptions.MinimumEventLevel.Should().Be(LogLevel.Critical); } } - [Fact] - public void SentryOptions_InitializeTrue_ValuesAppliedFromLoggingOptions() - { - var dict = new Dictionary - { - {"Sentry:InitializeSdk", "true"}, - }; - - _ = _fixture.Builder.AddInMemoryCollection(dict); - - var provider = _fixture.GetSut(); - var sentryLoggingOptions = provider.GetRequiredService>().Value; - - Assert.Equal(150, sentryLoggingOptions.MaxBreadcrumbs); - Assert.Equal("e386dfd", sentryLoggingOptions.Release); - Assert.Equal(ValidDsn, sentryLoggingOptions.Dsn); - } - - [Fact] - public void SentryOptions_DefaultTags_ValuesApplied() - { - const string expectedKey = "expected_key"; - const string expectedValue = "expected value"; - var dict = new Dictionary - { - {"Sentry:DefaultTags:" + expectedKey, expectedValue}, - }; - - _ = _fixture.Builder.AddInMemoryCollection(dict); - - var provider = _fixture.GetSut(); - var sentryLoggingOptions = provider.GetRequiredService>().Value; - - sentryLoggingOptions.DefaultTags.Should().ContainKey(expectedKey); - sentryLoggingOptions.DefaultTags[expectedKey].Should().Be(expectedValue); - } - [Fact] public void SentryLoggerProvider_ResolvedFromILoggerProvider() { diff --git a/test/Sentry.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs b/test/Sentry.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs index 8f9546b8d8..25166aad29 100644 --- a/test/Sentry.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs @@ -11,10 +11,7 @@ public void AddSentry_LoggingBuilder_AddLoggerProviders() { // Arrange var serviceCollection = new ServiceCollection(); - serviceCollection.AddLogging((ILoggingBuilder builder) => builder.AddSentry(options => - { - options.InitializeSdk = false; - })); + serviceCollection.AddLogging((ILoggingBuilder builder) => builder.AddSentry()); using var serviceProvider = serviceCollection.BuildServiceProvider(); using var loggerFactory = serviceProvider.GetRequiredService(); @@ -32,10 +29,7 @@ public void AddSentry_LoggingBuilder_AddLoggerFilterRules() { // Arrange var serviceCollection = new ServiceCollection(); - serviceCollection.AddLogging((ILoggingBuilder builder) => builder.AddSentry(options => - { - options.InitializeSdk = false; - })); + serviceCollection.AddLogging((ILoggingBuilder builder) => builder.AddSentry()); using var serviceProvider = serviceCollection.BuildServiceProvider(); using var loggerFactory = serviceProvider.GetRequiredService(); diff --git a/test/Sentry.Extensions.Logging.Tests/LoggingTests.cs b/test/Sentry.Extensions.Logging.Tests/LoggingTests.cs index 4e4dd049da..7bf40d2d33 100644 --- a/test/Sentry.Extensions.Logging.Tests/LoggingTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/LoggingTests.cs @@ -24,14 +24,18 @@ public void Log_CapturesEvent(LogLevel logLevel) // Arrange var worker = Substitute.For(); + using var sentry = SentrySdk.Init(o => + { + o.Dsn = ValidDsn; + o.BackgroundWorker = worker; + o.InitNativeSdks = false; + }); + var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(builder => builder.AddSentry(o => { - o.Dsn = ValidDsn; o.MinimumBreadcrumbLevel = LogLevel.None; o.MinimumEventLevel = logLevel; - o.BackgroundWorker = worker; - o.InitNativeSdks = false; })); serviceCollection.Configure(options => options.AddFilter(CategoryName, LogLevel.None)); using var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -70,14 +74,18 @@ public void Log_AddsBreadcrumb(LogLevel logLevel) // Arrange var worker = Substitute.For(); + using var sentry = SentrySdk.Init(o => + { + o.Dsn = ValidDsn; + o.BackgroundWorker = worker; + o.InitNativeSdks = false; + }); + var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(builder => builder.AddSentry(o => { - o.Dsn = ValidDsn; o.MinimumBreadcrumbLevel = logLevel; o.MinimumEventLevel = LogLevel.None; - o.BackgroundWorker = worker; - o.InitNativeSdks = false; })); serviceCollection.Configure(options => options.AddFilter(CategoryName, LogLevel.None)); using var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -121,14 +129,18 @@ public void Log_CapturesStructuredLog(LogLevel logLevel) // Arrange var worker = Substitute.For(); + using var sentry = SentrySdk.Init(o => + { + o.Dsn = ValidDsn; + o.BackgroundWorker = worker; + o.InitNativeSdks = false; + }); + var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(builder => builder.AddSentry(o => { - o.Dsn = ValidDsn; o.MinimumBreadcrumbLevel = LogLevel.None; o.MinimumEventLevel = LogLevel.None; - o.BackgroundWorker = worker; - o.InitNativeSdks = false; })); serviceCollection.Configure(options => options.AddFilter(CategoryName, logLevel)); using var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -164,14 +176,18 @@ public void Log_EventsAndBreadcrumbsIgnoreConfiguration_StructuredLogsRespectCon var envelopes = new List(2); worker.EnqueueEnvelope(Arg.Do(envelope => envelopes.Add(envelope))); + using var sentry = SentrySdk.Init(o => + { + o.Dsn = ValidDsn; + o.BackgroundWorker = worker; + o.InitNativeSdks = false; + }); + var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(builder => builder.AddSentry(o => { - o.Dsn = ValidDsn; o.MinimumBreadcrumbLevel = LogLevel.Information; o.MinimumEventLevel = LogLevel.Warning; - o.BackgroundWorker = worker; - o.InitNativeSdks = false; })); serviceCollection.Configure(options => options.AddFilter(CategoryName, LogLevel.Error)); using var serviceProvider = serviceCollection.BuildServiceProvider(); diff --git a/test/Sentry.Extensions.Logging.Tests/SentryLoggerFactoryExtensionsTests.cs b/test/Sentry.Extensions.Logging.Tests/SentryLoggerFactoryExtensionsTests.cs index 8937cf76e3..09191fd0e3 100644 --- a/test/Sentry.Extensions.Logging.Tests/SentryLoggerFactoryExtensionsTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/SentryLoggerFactoryExtensionsTests.cs @@ -5,91 +5,16 @@ namespace Sentry.Extensions.Logging.Tests; public class SentryLoggerFactoryExtensionsTests { [Fact] - public void AddSentry_ConfigureScope_HubEnabledTrue_InvokesCallback() - { - const SentryLevel expected = SentryLevel.Debug; - var sut = Substitute.For(); - var hub = Substitute.For(); - _ = hub.IsEnabled.Returns(true); - var scope = new Scope(new SentryOptions()); - hub.When(w => w.ConfigureScope(Arg.Any>())) - .Do(info => info.Arg>()(scope)); - _ = SentrySdk.UseHub(hub); - - _ = sut.AddSentry(o => - { - o.InitializeSdk = false; // use the mock above - o.ConfigureScope(s => s.Level = expected); - }); - - Assert.Equal(expected, scope.Level); - } - - [Fact] - public void AddSentry_ConfigureScope_HubEnabledFalse_DoesNotInvokesCallback() - { - const SentryLevel expected = SentryLevel.Debug; - var sut = Substitute.For(); - var hub = Substitute.For(); - _ = hub.IsEnabled.Returns(false); - var scope = new Scope(new SentryOptions()); - hub.When(w => w.ConfigureScope(Arg.Any>())) - .Do(info => info.Arg>()(scope)); - _ = SentrySdk.UseHub(hub); - - _ = sut.AddSentry(o => - { - o.InitializeSdk = false; // use the mock above - o.ConfigureScope(s => s.Level = expected); - }); - - Assert.NotEqual(expected, scope.Level); - } - - [Fact] - public void AddSentry_InitializeSdkFalse_HubAdapter() + public void AddSentry_ProviderUsesHubAdapter() { var sut = Substitute.For(); - _ = sut.AddSentry(o => o.InitializeSdk = false); + _ = sut.AddSentry(); sut.Received(1) .AddProvider(Arg.Is(p => p.Hub == HubAdapter.Instance)); } - [Fact] - public void AddSentry_NoDiagnosticSet_MelSet() - { - SentryLoggingOptions options = null; - var sut = Substitute.For(); - _ = sut.AddSentry(o => - { - o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; - o.Debug = true; - options = o; - }); - - _ = Assert.IsType(options.DiagnosticLogger); - } - - [Fact] - public void AddSentry_DiagnosticSet_NoOverriden() - { - SentryLoggingOptions options = null; - var sut = Substitute.For(); - var diagnosticLogger = Substitute.For(); - _ = sut.AddSentry(o => - { - o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; - o.Debug = true; - Assert.Null(o.DiagnosticLogger); - o.DiagnosticLogger = diagnosticLogger; - options = o; - }); - - Assert.Same(diagnosticLogger, options.DiagnosticLogger); - } - [Fact] public void AddSentry_WithOptionsCallback_CallbackInvoked() { @@ -97,7 +22,7 @@ public void AddSentry_WithOptionsCallback_CallbackInvoked() var expected = Substitute.For(); _ = expected.AddSentry(o => { - o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; + o.MinimumEventLevel = LogLevel.Critical; callbackInvoked = true; }); @@ -118,7 +43,7 @@ public void AddSentry_NoOptionsDelegate_ProviderAdded() public void AddSentry_ReturnsSameFactory() { var expected = Substitute.For(); - var actual = expected.AddSentry(o => o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue); + var actual = expected.AddSentry(o => o.MinimumEventLevel = LogLevel.Critical); Assert.Same(expected, actual); } @@ -127,7 +52,7 @@ public void AddSentry_ReturnsSameFactory() public void AddSentry_ConfigureOptionsOverload_ReturnsSameFactory() { var expected = Substitute.For(); - var actual = expected.AddSentry(o => o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue); + var actual = expected.AddSentry(o => o.MinimumEventLevel = LogLevel.Critical); Assert.Same(expected, actual); } @@ -140,7 +65,7 @@ public void AddSentry_ConfigureOptionsOverload_InvokesCallback() var invoked = false; _ = expected.AddSentry(o => { - o.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; + o.MinimumEventLevel = LogLevel.Critical; Assert.NotNull(o); invoked = true; }); diff --git a/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsExtensionsTests.cs b/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsExtensionsTests.cs index 9671860170..d4cb540b6b 100644 --- a/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsExtensionsTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsExtensionsTests.cs @@ -1,33 +1,53 @@ +using Microsoft.Extensions.Logging; + namespace Sentry.Extensions.Logging.Tests; public class SentryLoggingOptionsExtensionsTests { - private readonly SentryLoggingOptions _sut = new(); + private class TestHostOptions : SentryHostOptions; + + [Fact] + public void AddLogEntryFilter_LoggingOptions_AddsFilter() + { + var sut = new SentryLoggingOptions(); + var filter = Substitute.For(); + + sut.AddLogEntryFilter(filter); + + sut.Filters.Should().ContainSingle().Which.Should().BeSameAs(filter); + } [Fact] - public void ApplyDefaultTags_TagInEvent_DoesNotOverrideTag() + public void AddLogEntryFilter_HostOptions_AddsFilterToLoggingOptions() { - const string key = "key"; - const string expected = "event tag value"; - var target = new SentryEvent(); - target.SetTag(key, expected); - _sut.DefaultTags[key] = "default value"; + var sut = new TestHostOptions(); + var filter = Substitute.For(); - _sut.ApplyDefaultTags(target); + sut.AddLogEntryFilter(filter); - Assert.Equal(expected, target.Tags[key]); + sut.Logging.Filters.Should().ContainSingle().Which.Should().BeSameAs(filter); } [Fact] - public void ApplyDefaultTags_TagNotInEvent_AppliesTag() + public void AddLogEntryFilter_HostOptionsDelegate_AddsFilterToLoggingOptions() { - const string key = "key"; - const string expected = "default tag value"; - var target = new SentryEvent(); - _sut.DefaultTags[key] = expected; + var sut = new TestHostOptions(); + + sut.AddLogEntryFilter((_, _, _, _) => true); + + sut.Logging.Filters.Should().ContainSingle().Which.Should().BeOfType(); + } - _sut.ApplyDefaultTags(target); + [Fact] + public void MinimumLevels_HostOptions_PassThroughToLoggingOptions() + { + var sut = new TestHostOptions + { + MinimumBreadcrumbLevel = LogLevel.Debug, + MinimumEventLevel = LogLevel.Critical, + }; - Assert.Equal(expected, target.Tags[key]); + sut.Logging.MinimumBreadcrumbLevel.Should().Be(LogLevel.Debug); + sut.Logging.MinimumEventLevel.Should().Be(LogLevel.Critical); } } diff --git a/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs b/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs index 778215de16..1c7df8cf07 100644 --- a/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/SentryLoggingOptionsSetupTests.cs @@ -10,102 +10,11 @@ public class SentryLoggingOptionsSetupTests public void Configure_BindsConfigurationToOptions() { // Arrange - var expected = new SentryLoggingOptions - { - IsGlobalModeEnabled = true, - EnableScopeSync = true, - TagFilters = new List { "tag1", "tag2" }, - SendDefaultPii = true, - IsEnvironmentUser = true, - ServerName = "FakeServerName", - AttachStacktrace = true, - MaxBreadcrumbs = 7, - SampleRate = 0.7f, - Release = "FakeRelease", - Distribution = "FakeDistribution", - Environment = "Test", - Dsn = "https://d4d82fc1c2c4032a83f3a29aa3a3aff@fake-sentry.io:65535/2147483647", - MaxQueueItems = 8, - MaxCacheItems = 9, - ShutdownTimeout = TimeSpan.FromSeconds(13), - FlushTimeout = TimeSpan.FromSeconds(17), - DecompressionMethods = DecompressionMethods.GZip | DecompressionMethods.Deflate, - RequestBodyCompressionLevel = CompressionLevel.Fastest, - RequestBodyCompressionBuffered = true, - SendClientReports = true, - Debug = true, - DiagnosticLevel = SentryLevel.Warning, - ReportAssembliesMode = ReportAssembliesMode.InformationalVersion, - DeduplicateMode = DeduplicateMode.AggregateException, - CacheDirectoryPath = "~/test", - CaptureFailedRequests = true, - // FailedRequestStatusCodes = IList, - FailedRequestTargets = ["target1", "target2"], - InitCacheFlushTimeout = TimeSpan.FromSeconds(27), - // DefaultTags = Dictionary, - TracesSampleRate = 0.8f, - TracePropagationTargets = new List { "target3", "target4" }, - StackTraceMode = StackTraceMode.Enhanced, - MaxAttachmentSize = 21478, - DetectStartupTime = StartupTimeDetectionMode.Fast, - AutoSessionTrackingInterval = TimeSpan.FromHours(3), - AutoSessionTracking = true, - UseAsyncFileIO = true, - JsonPreserveReferences = true, - - MinimumBreadcrumbLevel = LogLevel.Debug, - MinimumEventLevel = LogLevel.Error, - InitializeSdk = true - }; var config = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { - ["IsGlobalModeEnabled"] = expected.IsGlobalModeEnabled.ToString(), - ["EnableScopeSync"] = expected.EnableScopeSync.ToString(), - ["TagFilters:0"] = expected.TagFilters.First().ToString(), - ["TagFilters:1"] = expected.TagFilters.Last().ToString(), - ["SendDefaultPii"] = expected.SendDefaultPii.ToString(), - ["IsEnvironmentUser"] = expected.IsEnvironmentUser.ToString(), - ["ServerName"] = expected.ServerName, - ["AttachStacktrace"] = expected.AttachStacktrace.ToString(), - ["MaxBreadcrumbs"] = expected.MaxBreadcrumbs.ToString(), - ["SampleRate"] = expected.SampleRate.Value.ToString(CultureInfo.InvariantCulture), - ["Release"] = expected.Release, - ["Distribution"] = expected.Distribution, - ["Environment"] = expected.Environment, - ["Dsn"] = expected.Dsn, - ["MaxQueueItems"] = expected.MaxQueueItems.ToString(), - ["MaxCacheItems"] = expected.MaxCacheItems.ToString(), - ["ShutdownTimeout"] = expected.ShutdownTimeout.ToString(), - ["FlushTimeout"] = expected.FlushTimeout.ToString(), - ["DecompressionMethods"] = expected.DecompressionMethods.ToString(), - ["RequestBodyCompressionLevel"] = expected.RequestBodyCompressionLevel.ToString(), - ["RequestBodyCompressionBuffered"] = expected.RequestBodyCompressionBuffered.ToString(), - ["SendClientReports"] = expected.SendClientReports.ToString(), - ["Debug"] = expected.Debug.ToString(), - ["DiagnosticLevel"] = expected.DiagnosticLevel.ToString(), - ["ReportAssembliesMode"] = expected.ReportAssembliesMode.ToString(), - ["DeduplicateMode"] = expected.DeduplicateMode.ToString(), - ["CacheDirectoryPath"] = expected.CacheDirectoryPath.ToString(), - ["CaptureFailedRequests"] = expected.CaptureFailedRequests.ToString(), - ["FailedRequestStatusCodes"] = expected.FailedRequestStatusCodes.ToString(), - ["FailedRequestTargets:0"] = expected.FailedRequestTargets.First().ToString(), - ["FailedRequestTargets:1"] = expected.FailedRequestTargets.Last().ToString(), - ["InitCacheFlushTimeout"] = expected.InitCacheFlushTimeout.ToString(), - ["DefaultTags"] = expected.DefaultTags.ToString(), - ["TracesSampleRate"] = expected.TracesSampleRate.Value.ToString(CultureInfo.InvariantCulture), - ["TracePropagationTargets:0"] = expected.TracePropagationTargets.First().ToString(), - ["TracePropagationTargets:1"] = expected.TracePropagationTargets.Last().ToString(), - ["StackTraceMode"] = expected.StackTraceMode.ToString(), - ["MaxAttachmentSize"] = expected.MaxAttachmentSize.ToString(), - ["DetectStartupTime"] = expected.DetectStartupTime.ToString(), - ["AutoSessionTrackingInterval"] = expected.AutoSessionTrackingInterval.ToString(), - ["AutoSessionTracking"] = expected.AutoSessionTracking.ToString(), - ["UseAsyncFileIO"] = expected.UseAsyncFileIO.ToString(), - ["JsonPreserveReferences"] = expected.JsonPreserveReferences.ToString(), - ["MinimumBreadcrumbLevel"] = expected.MinimumBreadcrumbLevel.ToString(), - ["MinimumEventLevel"] = expected.MinimumEventLevel.ToString(), - ["InitializeSdk"] = expected.InitializeSdk.ToString(), + ["MinimumBreadcrumbLevel"] = nameof(LogLevel.Debug), + ["MinimumEventLevel"] = nameof(LogLevel.Critical), }) .Build(); @@ -121,48 +30,8 @@ public void Configure_BindsConfigurationToOptions() // Assert using (new AssertionScope()) { - actual.IsGlobalModeEnabled.Should().Be(expected.IsGlobalModeEnabled); - actual.EnableScopeSync.Should().Be(expected.EnableScopeSync); - actual.TagFilters.Should().BeEquivalentTo(expected.TagFilters); - actual.SendDefaultPii.Should().Be(expected.SendDefaultPii); - actual.IsEnvironmentUser.Should().Be(expected.IsEnvironmentUser); - actual.ServerName.Should().Be(expected.ServerName); - actual.AttachStacktrace.Should().Be(expected.AttachStacktrace); - actual.MaxBreadcrumbs.Should().Be(expected.MaxBreadcrumbs); - actual.SampleRate.Should().Be(expected.SampleRate); - actual.Release.Should().Be(expected.Release); - actual.Distribution.Should().Be(expected.Distribution); - actual.Environment.Should().Be(expected.Environment); - actual.Dsn.Should().Be(expected.Dsn); - actual.MaxQueueItems.Should().Be(expected.MaxQueueItems); - actual.MaxCacheItems.Should().Be(expected.MaxCacheItems); - actual.ShutdownTimeout.Should().Be(expected.ShutdownTimeout); - actual.FlushTimeout.Should().Be(expected.FlushTimeout); - actual.DecompressionMethods.Should().Be(expected.DecompressionMethods); - actual.RequestBodyCompressionLevel.Should().Be(expected.RequestBodyCompressionLevel); - actual.RequestBodyCompressionBuffered.Should().Be(expected.RequestBodyCompressionBuffered); - actual.SendClientReports.Should().Be(expected.SendClientReports); - actual.Debug.Should().Be(expected.Debug); - actual.DiagnosticLevel.Should().Be(expected.DiagnosticLevel); - actual.ReportAssembliesMode.Should().Be(expected.ReportAssembliesMode); - actual.DeduplicateMode.Should().Be(expected.DeduplicateMode); - actual.CacheDirectoryPath.Should().Be(expected.CacheDirectoryPath); - actual.CaptureFailedRequests.Should().Be(expected.CaptureFailedRequests); - actual.FailedRequestTargets.Should().BeEquivalentTo(expected.FailedRequestTargets); - actual.InitCacheFlushTimeout.Should().Be(expected.InitCacheFlushTimeout); - actual.TracesSampleRate.Should().Be(expected.TracesSampleRate); - actual.TracePropagationTargets.Should().BeEquivalentTo(expected.TracePropagationTargets); - actual.StackTraceMode.Should().Be(expected.StackTraceMode); - actual.MaxAttachmentSize.Should().Be(expected.MaxAttachmentSize); - actual.DetectStartupTime.Should().Be(expected.DetectStartupTime); - actual.AutoSessionTrackingInterval.Should().Be(expected.AutoSessionTrackingInterval); - actual.AutoSessionTracking.Should().Be(expected.AutoSessionTracking); - actual.UseAsyncFileIO.Should().Be(expected.UseAsyncFileIO); - actual.JsonPreserveReferences.Should().Be(expected.JsonPreserveReferences); - - actual.MinimumBreadcrumbLevel.Should().Be(expected.MinimumBreadcrumbLevel); - actual.MinimumEventLevel.Should().Be(expected.MinimumEventLevel); - actual.InitializeSdk.Should().Be(expected.InitializeSdk); + actual.MinimumBreadcrumbLevel.Should().Be(LogLevel.Debug); + actual.MinimumEventLevel.Should().Be(LogLevel.Critical); } } } diff --git a/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerProviderTests.cs b/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerProviderTests.cs index c8d797244e..fd9b7c88d1 100644 --- a/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerProviderTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerProviderTests.cs @@ -6,22 +6,19 @@ namespace Sentry.Extensions.Logging.Tests; -public class SentryStructuredLoggerProviderTests +public class SentryStructuredLoggerProviderTests : IDisposable { private class Fixture { - public IOptions Options { get; } public IHub Hub { get; } public MockClock Clock { get; } public SdkVersion Sdk { get; } public Fixture() { - var loggingOptions = new SentryLoggingOptions(); - - Options = Microsoft.Extensions.Options.Options.Create(loggingOptions); Hub = Substitute.For(); - Hub.SubstituteConfigureScope(new Scope(loggingOptions)); + SentryClientExtensions.SentryOptionsForTestingOnly = new SentryOptions(); + Hub.SubstituteConfigureScope(new Scope(new SentryOptions())); Clock = new MockClock(); Sdk = new SdkVersion { @@ -34,12 +31,14 @@ public Fixture() public SentryStructuredLoggerProvider GetSut() { - return new SentryStructuredLoggerProvider(Options.Value, Hub, Clock, Sdk); + return new SentryStructuredLoggerProvider(Hub, Clock, Sdk); } } private readonly Fixture _fixture = new(); + public void Dispose() => SentryClientExtensions.SentryOptionsForTestingOnly = null; + [Fact] public void Type_CustomAttributes_HasProviderAliasAttribute() { @@ -56,7 +55,6 @@ public void Ctor_DependencyInjection_CanCreate() using var services = new ServiceCollection() .AddLogging() .AddSingleton() - .AddSingleton(_fixture.Options) .AddSingleton(_fixture.Hub) .BuildServiceProvider(); @@ -85,7 +83,6 @@ public void CreateLogger_DependencyInjection_CanLog() using var services = new ServiceCollection() .AddLogging() .AddSingleton() - .AddSingleton(_fixture.Options) .AddSingleton(_fixture.Hub) .BuildServiceProvider(); diff --git a/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerTests.cs b/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerTests.cs index 0b11148cb8..c6a84e8ad6 100644 --- a/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/SentryStructuredLoggerTests.cs @@ -10,7 +10,7 @@ public class SentryStructuredLoggerTests : IDisposable private class Fixture { public string CategoryName { get; internal set; } - public IOptions Options { get; } + public SentryOptions Options { get; } public IHub Hub { get; } public MockClock Clock { get; } public SdkVersion Sdk { get; } @@ -20,18 +20,18 @@ private class Fixture public Fixture() { - var loggingOptions = new SentryLoggingOptions + Options = new SentryOptions { Debug = true, DiagnosticLogger = DiagnosticLogger, Environment = "my-environment", Release = "my-release", }; + SentryClientExtensions.SentryOptionsForTestingOnly = Options; CategoryName = nameof(CategoryName); - Options = Microsoft.Extensions.Options.Options.Create(loggingOptions); Hub = Substitute.For(); - Hub.SubstituteConfigureScope(new Scope(loggingOptions)); + Hub.SubstituteConfigureScope(new Scope(Options)); Clock = new MockClock(new DateTimeOffset(2025, 04, 22, 14, 51, 00, 789, TimeSpan.FromHours(2))); Sdk = new SdkVersion { @@ -58,7 +58,7 @@ public void WithActiveSpan(SentryId traceId, SpanId spanId) public SentryStructuredLogger GetSut() { - return new SentryStructuredLogger(CategoryName, Options.Value, Hub, Clock, Sdk); + return new SentryStructuredLogger(CategoryName, Hub, Clock, Sdk); } } @@ -66,6 +66,7 @@ public SentryStructuredLogger GetSut() public void Dispose() { + SentryClientExtensions.SentryOptionsForTestingOnly = null; _fixture.CapturedLogs.Should().BeEmpty(); _fixture.DiagnosticLogger.Entries.Should().BeEmpty(); } @@ -129,7 +130,7 @@ public void Log_LogLevelNone_DoesNotCaptureLog() [Fact] public void Log_WithoutActiveSpan_CaptureLog() { - var scope = new Scope(_fixture.Options.Value); + var scope = new Scope(_fixture.Options); _fixture.Hub.GetSpan().Returns((ISpan?)null); _fixture.Hub.SubstituteConfigureScope(scope); var logger = _fixture.GetSut(); diff --git a/test/Sentry.Extensions.Logging.Tests/ServiceCollectionExtensionsTests.cs b/test/Sentry.Extensions.Logging.Tests/ServiceCollectionExtensionsTests.cs new file mode 100644 index 0000000000..5b80c1d115 --- /dev/null +++ b/test/Sentry.Extensions.Logging.Tests/ServiceCollectionExtensionsTests.cs @@ -0,0 +1,51 @@ +using Microsoft.Extensions.DependencyInjection; +using Sentry.Extensions.Logging.Extensions.DependencyInjection; + +namespace Sentry.Extensions.Logging.Tests; + +public class ServiceCollectionExtensionsTests : IDisposable +{ + private class TestHostOptions : SentryHostOptions; + + public void Dispose() => SentrySdk.Close(); + + private static ServiceProvider GetSut(bool initializeSdk, Action configureScope) + { + var services = new ServiceCollection(); + services.Configure(o => + { + o.Dsn = ValidDsn; + o.BackgroundWorker = Substitute.For(); + o.AutoSessionTracking = false; + o.InitNativeSdks = false; + o.ConfigureScope(configureScope); + }); + services.AddSentry(initializeSdk); + return services.BuildServiceProvider(); + } + + [Fact] + public void AddSentry_HubResolved_InitializesSdkAndAppliesConfigureScope() + { + var configured = false; + using var provider = GetSut(initializeSdk: true, _ => configured = true); + + _ = provider.GetRequiredService(); + + SentrySdk.IsEnabled.Should().BeTrue(); + configured.Should().BeTrue(); + } + + [Fact] + public void AddSentry_WithoutInitializeSdk_HubResolved_LeavesSdkAlone() + { + SentrySdk.UseHub(DisabledHub.Instance); + var configured = false; + using var provider = GetSut(initializeSdk: false, _ => configured = true); + + _ = provider.GetRequiredService(); + + SentrySdk.IsEnabled.Should().BeFalse(); + configured.Should().BeFalse(); + } +} diff --git a/test/Sentry.Extensions.Logging.Tests/appsettings.json b/test/Sentry.Extensions.Logging.Tests/appsettings.json index dc995ef4f2..42dd09734e 100644 --- a/test/Sentry.Extensions.Logging.Tests/appsettings.json +++ b/test/Sentry.Extensions.Logging.Tests/appsettings.json @@ -1,10 +1,6 @@ { "Sentry": { - "Dsn": "https://d4d82fc1c2c4032a83f3a29aa3a3aff@fake-sentry.io:65535/2147483647", - "MaxBreadcrumbs": 150, - "Release": "e386dfd", "MinimumBreadcrumbLevel": "Warning", - "MinimumEventLevel": "Critical", - "InitializeSdk": false + "MinimumEventLevel": "Critical" } } diff --git a/test/Sentry.Google.Cloud.Functions.Tests/SentryStartupTests.cs b/test/Sentry.Google.Cloud.Functions.Tests/SentryStartupTests.cs index 39c14fa641..0ddd1bc042 100644 --- a/test/Sentry.Google.Cloud.Functions.Tests/SentryStartupTests.cs +++ b/test/Sentry.Google.Cloud.Functions.Tests/SentryStartupTests.cs @@ -127,7 +127,7 @@ public void ConfigureLogging_Logging_AddLoggerProviders() { LoggingBuilder.Services.Configure(options => { - options.InitializeSdk = false; + options.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; }); var sut = new SentryStartup(); @@ -146,7 +146,7 @@ public void ConfigureLogging_Logging_AddLoggerFilterRules() { LoggingBuilder.Services.Configure(options => { - options.InitializeSdk = false; + options.Dsn = Sentry.SentryConstants.DisableSdkDsnValue; }); var sut = new SentryStartup(); diff --git a/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt b/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt index db0645d89c..bac8f36955 100644 --- a/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt +++ b/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt @@ -34,7 +34,7 @@ namespace Sentry.Maui void Bind(Microsoft.Maui.Controls.VisualElement element, System.Action addBreadcrumb); void UnBind(Microsoft.Maui.Controls.VisualElement element); } - public class SentryMauiOptions : Sentry.Extensions.Logging.SentryLoggingOptions + public class SentryMauiOptions : Sentry.Extensions.Logging.SentryHostOptions { public SentryMauiOptions() { } public bool AttachScreenshot { get; set; } diff --git a/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt b/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt index db0645d89c..bac8f36955 100644 --- a/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt +++ b/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt @@ -34,7 +34,7 @@ namespace Sentry.Maui void Bind(Microsoft.Maui.Controls.VisualElement element, System.Action addBreadcrumb); void UnBind(Microsoft.Maui.Controls.VisualElement element); } - public class SentryMauiOptions : Sentry.Extensions.Logging.SentryLoggingOptions + public class SentryMauiOptions : Sentry.Extensions.Logging.SentryHostOptions { public SentryMauiOptions() { } public bool AttachScreenshot { get; set; } diff --git a/test/Sentry.Maui.Tests/Internal/SentryMauiStructuredLoggerProviderTests.cs b/test/Sentry.Maui.Tests/Internal/SentryMauiStructuredLoggerProviderTests.cs index a4ee5bb016..7d54cf85e8 100644 --- a/test/Sentry.Maui.Tests/Internal/SentryMauiStructuredLoggerProviderTests.cs +++ b/test/Sentry.Maui.Tests/Internal/SentryMauiStructuredLoggerProviderTests.cs @@ -6,21 +6,18 @@ namespace Sentry.Maui.Tests.Internal; -public class SentryMauiStructuredLoggerProviderTests +public class SentryMauiStructuredLoggerProviderTests : IDisposable { private class Fixture { - public IOptions Options { get; } public IHub Hub { get; } public MockClock Clock { get; } public SdkVersion Sdk { get; } public Fixture() { - var loggingOptions = new SentryMauiOptions(); - - Options = Microsoft.Extensions.Options.Options.Create(loggingOptions); Hub = Substitute.For(); + SentryClientExtensions.SentryOptionsForTestingOnly = new SentryOptions(); Clock = new MockClock(); Sdk = new SdkVersion { @@ -33,12 +30,14 @@ public Fixture() public SentryMauiStructuredLoggerProvider GetSut() { - return new SentryMauiStructuredLoggerProvider(Options.Value, Hub, Clock, Sdk); + return new SentryMauiStructuredLoggerProvider(Hub, Clock, Sdk); } } private readonly Fixture _fixture = new(); + public void Dispose() => SentryClientExtensions.SentryOptionsForTestingOnly = null; + [Fact] public void Type_CustomAttributes_HasProviderAliasAttribute() { @@ -55,7 +54,6 @@ public void Ctor_DependencyInjection_CanCreate() using var services = new ServiceCollection() .AddLogging() .AddSingleton() - .AddSingleton(_fixture.Options) .AddSingleton(_fixture.Hub) .BuildServiceProvider(); @@ -84,7 +82,6 @@ public void CreateLogger_DependencyInjection_CanLog() using var services = new ServiceCollection() .AddLogging() .AddSingleton() - .AddSingleton(_fixture.Options) .AddSingleton(_fixture.Hub) .BuildServiceProvider(); diff --git a/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs b/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs index e512cbd5ea..afbe518260 100644 --- a/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs +++ b/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs @@ -190,6 +190,32 @@ public void UseSentry_SetsMauiSdkNameAndVersion() Assert.Equal(MauiConstants.SdkVersion, @event.Sdk.Version); } + [Fact] + public void UseSentry_ConfigureScope_AppliedWhenSdkInitialized() + { + // Arrange + SentryEvent @event = null; + var builder = _fixture.Builder + .UseSentry(options => + { + options.ConfigureScope(scope => scope.SetTag("configured", "at-init")); + options.SetBeforeSend((e, _) => + { + @event = e; + return null; + }); + }); + + // Act + using var app = builder.Build(); + var client = app.Services.GetRequiredService(); + client.CaptureMessage("test"); + + // Assert + Assert.NotNull(@event); + Assert.Equal("at-init", @event.Tags["configured"]); + } + [Fact] public void UseSentry_EnablesHub() { @@ -338,10 +364,7 @@ public void UseSentry_Logging_AddLoggerProviders() var builder = _fixture.Builder; // Act - builder.UseSentry((SentryMauiOptions options) => - { - options.InitializeSdk = false; - }); + builder.UseSentry(); using var serviceProvider = builder.Services.BuildServiceProvider(); var providers = serviceProvider.GetRequiredService>().ToArray(); @@ -359,10 +382,7 @@ public void UseSentry_Logging_AddLoggerFilterRules() var builder = _fixture.Builder; // Act - builder.UseSentry((SentryMauiOptions options) => - { - options.InitializeSdk = false; - }); + builder.UseSentry(); using var serviceProvider = builder.Services.BuildServiceProvider(); var loggerFilterOptions = serviceProvider.GetRequiredService>().Value; diff --git a/test/Sentry.Tests/SentryOptionsTests.cs b/test/Sentry.Tests/SentryOptionsTests.cs index b5e91926c6..2c126ad63f 100644 --- a/test/Sentry.Tests/SentryOptionsTests.cs +++ b/test/Sentry.Tests/SentryOptionsTests.cs @@ -703,4 +703,33 @@ public void CachesInstallationId() installationId2.Should().Be(installationId1); logger.Received(0).Log(SentryLevel.Debug, "Resolved installation ID '{0}'.", null, Arg.Any()); } + + [Fact] + public void ApplyDefaultTags_TagInEvent_DoesNotOverrideTag() + { + const string key = "key"; + const string expected = "event tag value"; + var sut = new SentryOptions(); + var target = new SentryEvent(); + target.SetTag(key, expected); + sut.DefaultTags[key] = "default value"; + + sut.ApplyDefaultTags(target); + + Assert.Equal(expected, target.Tags[key]); + } + + [Fact] + public void ApplyDefaultTags_TagNotInEvent_AppliesTag() + { + const string key = "key"; + const string expected = "default tag value"; + var sut = new SentryOptions(); + var target = new SentryEvent(); + sut.DefaultTags[key] = expected; + + sut.ApplyDefaultTags(target); + + Assert.Equal(expected, target.Tags[key]); + } }