Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2fb7d37
ref(logs): make API stable (remove Experimental from Options)
Flash0ver Nov 6, 2025
cd79096
fix: MAUI sample
Flash0ver Nov 6, 2025
33aaeac
ref(logs): remove experimental MinimumLogLevel
Flash0ver Nov 6, 2025
f8a7369
Merge branch 'main' into logs/fix-configuration
Flash0ver Nov 20, 2025
1a119b5
merge: cleanup after merge
Flash0ver Nov 20, 2025
9ac70b7
fix(logs): minimum Log-Level for Structured Logs
Flash0ver Nov 25, 2025
8bc1b02
ref!: make all SentryLoggerProviders non-public
Flash0ver Nov 25, 2025
bc86bb7
example: enable Logs for Generic-Host sample
Flash0ver Nov 25, 2025
c65dcb1
feat: enable Logs for Google-Cloud-Functions
Flash0ver Nov 25, 2025
fb91a5b
ref: seal internal Configure-Options
Flash0ver Nov 25, 2025
14010ba
Merge branch 'main' into logs/fix-configuration
Flash0ver Nov 25, 2025
26d56fa
docs: add CHANGELOG entry
Flash0ver Nov 25, 2025
0b56dac
docs: add CHANGELOG entry
Flash0ver Nov 25, 2025
e8a5f86
Merge branch 'main' into logs/fix-configuration
Flash0ver Nov 26, 2025
467898f
Update CHANGELOG.md
Flash0ver Nov 26, 2025
c5012cd
test: add Configure-Logging test
Flash0ver Nov 26, 2025
fab6da5
ref: suppress null
Flash0ver Nov 26, 2025
ce4b5e1
Merge branch 'main' into logs/fix-configuration
jamescrosswell Nov 27, 2025
35b4a8f
Update samples/Sentry.Samples.Google.Cloud.Functions/Function.cs
Flash0ver Nov 28, 2025
8a05445
ref: more samples
Flash0ver Nov 28, 2025
fd9dc83
Update CHANGELOG.md
Flash0ver Nov 28, 2025
b26b3b0
docs: add comment to MAUI sample
Flash0ver Dec 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,27 @@

## Unreleased

### BREAKING CHANGES

- Remove `SentryLoggingOptions.ExperimentalLogging.MinimumLogLevel`. _Structured Logs_ can now be configured via the `"Sentry"` logging provider (e.g. in `appsettings.json` and `appsettings.{HostEnvironment}.json`) ([#4700](https://github.com/getsentry/sentry-dotnet/pull/4700))
- All logging provider types are _internal_ now in order to ensure configuration as intended ([#4700](https://github.com/getsentry/sentry-dotnet/pull/4700))

### Features

- Added a new SDK `Sentry.Extensions.AI` which allows LLM usage instrumentation via `Microsoft.Extensions.AI` ([#4657](https://github.com/getsentry/sentry-dotnet/pull/4657))
- Add support for _Structured Logs_ in `Sentry.Google.Cloud.Functions` ([#4700](https://github.com/getsentry/sentry-dotnet/pull/4700))

### Fixes

- Captured [Http Client Errors](https://docs.sentry.io/platforms/dotnet/guides/aspnet/configuration/http-client-errors/) on .NET 5+ now include a full stack trace in order to improve Issue grouping ([#4724](https://github.com/getsentry/sentry-dotnet/pull/4724))
- Sentry Tracing middleware crashed ASP.NET Core in .NET 10 in 6.0.0-rc.1 and earlier ([#4747](https://github.com/getsentry/sentry-dotnet/pull/4747))
- Avoid appending `/NODEFAULTLIB:MSVCRT` to NativeAOT linker arguments on Windows when targetting non-Windows platforms (Android, Browser) ([#4760](https://github.com/getsentry/sentry-dotnet/pull/4760))
- Minimum Log-Level for _Structured Logs_, _Breadcrumbs_ and _Events_ in all Logging-Integrations ([#4700](https://github.com/getsentry/sentry-dotnet/pull/4700))
- for `Sentry.Extensions.Logging`, `Sentry.AspNetCore`, `Sentry.Maui` and `Sentry.Google.Cloud.Functions`
- the Logger-Provider for _Breadcrumbs_ and _Events_ ignores Logging-Configuration (e.g. via `appsettings.json`)
- use the intended `SentryLoggingOptions.MinimumBreadcrumbLevel`, `SentryLoggingOptions.MinimumEventLevel`, or add filter functions via `SentryLoggingOptionsExtensions.AddLogEntryFilter`
- the Logger-Provider for _Structured Logs_ respects Logging-Configuration (e.g. via `appsettings.json`)
- when enabled by `SentryOptions.EnableLogs`

### Dependencies

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ public void Setup()
{
Dsn = DsnSamples.ValidDsn,
EnableLogs = true,
ExperimentalLogging =
{
MinimumLogLevel = LogLevel.Information,
}
};
options.SetBeforeSendLog((SentryLog log) =>
{
Expand Down
7 changes: 6 additions & 1 deletion samples/Sentry.Samples.AspNetCore.Basic/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
options.Debug = true;
#endif

// This option enables Logs sent to Sentry.
// Configure the minimum Log Level of Breadcrumbs and Events
options.MinimumBreadcrumbLevel = LogLevel.Information;
options.MinimumEventLevel = LogLevel.Error;

// This option enables Logs sent to Sentry
// Configure the minimum Log Level of Structured-Logs via e.g. "appsettings.json" and "appsettings.{HostEnvironment}.json"
options.EnableLogs = true;
});

Expand Down
14 changes: 14 additions & 0 deletions samples/Sentry.Samples.AspNetCore.Basic/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
},
"Sentry": {
"LogLevel": {
"Default": "Trace"
}
}
},
"AllowedHosts": "*"
}
2 changes: 2 additions & 0 deletions samples/Sentry.Samples.GenericHost/SampleHostedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ internal class SampleHostedService(IHub hub, ILogger<SampleHostedService> logger
{
public Task StartAsync(CancellationToken cancellationToken)
{
// Configure structured logging via appsettings.json (Logging:Sentry:LogLevel:)
logger.LogTrace("LogLevel.Trace is not configured to be sent as structured log");
// Logging integration by default keeps informational logs as Breadcrumb
logger.LogInformation("Starting sample hosted service. This goes as a breadcrumb");
// You can also add breadcrumb directly through Sentry.Hub:
Expand Down
8 changes: 7 additions & 1 deletion samples/Sentry.Samples.GenericHost/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
"Logging": {
"LogLevel": {
"Default": "Trace"
},
"Sentry": {
"LogLevel": {
"Default": "Information" // Configure structured logs
}
}
},
"Sentry": {
//"Dsn": "TODO: Configure your DSN here and uncomment this line",
"MinimumBreadcrumbLevel": "Debug",
"MinimumEventLevel": "Warning",
"SendDefaultPii": true // Send user name and machine name
"SendDefaultPii": true, // Send user name and machine name
"EnableLogs": true // Send structured logs
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class Function : IHttpFunction

public Task HandleAsync(HttpContext context)
{
_logger.LogTrace("LogLevel.Trace is not configured to be sent as structured log");
_logger.LogInformation("Useful info that is added to the breadcrumb list.");
throw new Exception("Bad function");
}
Expand Down
13 changes: 12 additions & 1 deletion samples/Sentry.Samples.Google.Cloud.Functions/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug"
},
"Sentry": {
"LogLevel": {
"Default": "Information"
}
}
},
"Sentry": {
//"Dsn": "TODO: Configure your DSN here and uncomment this line",
"MaxRequestBodySize": "Always",
"SendDefaultPii": true,
"EnableTracing": true
"EnableTracing": true,
"EnableLogs" : true
}
}
1 change: 0 additions & 1 deletion samples/Sentry.Samples.ME.Logging/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
// 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.ExperimentalLogging.MinimumLogLevel = LogLevel.Trace; // This level or above will result in log sent to Sentry

// This option enables Logs sent to Sentry.
options.EnableLogs = true;
Expand Down
10 changes: 8 additions & 2 deletions src/Sentry.AspNetCore/SentryAspNetCoreLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Sentry.Extensions.Logging;
using Sentry.Infrastructure;

namespace Sentry.AspNetCore;

/// <summary>
/// Logger provider for Sentry.
/// Sentry Logger Provider for <see cref="Breadcrumb"/> and <see cref="SentryEvent"/>.
/// </summary>
[ProviderAlias("Sentry")]
public class SentryAspNetCoreLoggerProvider : SentryLoggerProvider
internal sealed class SentryAspNetCoreLoggerProvider : SentryLoggerProvider
{
/// <summary>
/// Creates a new instance of <see cref="SentryAspNetCoreLoggerProvider"/>
Expand All @@ -17,4 +18,9 @@ public SentryAspNetCoreLoggerProvider(IOptions<SentryAspNetCoreOptions> options,
: base(options, hub)
{
}

internal SentryAspNetCoreLoggerProvider(SentryAspNetCoreOptions options, IHub hub, ISystemClock clock)
: base(hub, clock, options)
{
}
}
4 changes: 2 additions & 2 deletions src/Sentry.AspNetCore/SentryAspNetCoreOptionsSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Sentry.AspNetCore;
/// Sets up ASP.NET Core option for Sentry.
/// </summary>
#if NETSTANDARD2_0
public class SentryAspNetCoreOptionsSetup : ConfigureFromConfigurationOptions<SentryAspNetCoreOptions>
internal sealed class SentryAspNetCoreOptionsSetup : ConfigureFromConfigurationOptions<SentryAspNetCoreOptions>
{
/// <summary>
/// Creates a new instance of <see cref="SentryAspNetCoreOptionsSetup"/>.
Expand All @@ -32,7 +32,7 @@ public override void Configure(SentryAspNetCoreOptions options)
}

#else
public class SentryAspNetCoreOptionsSetup : IConfigureOptions<SentryAspNetCoreOptions>
internal sealed class SentryAspNetCoreOptionsSetup : IConfigureOptions<SentryAspNetCoreOptions>
{
private readonly IConfiguration _config;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
namespace Sentry.AspNetCore;

/// <summary>
/// Structured Logger Provider for Sentry.
/// Sentry Logger Provider for <see cref="SentryLog"/>.
/// </summary>
[ProviderAlias("SentryLogs")]
[ProviderAlias("Sentry")]
internal sealed class SentryAspNetCoreStructuredLoggerProvider : SentryStructuredLoggerProvider
{
public SentryAspNetCoreStructuredLoggerProvider(IOptions<SentryAspNetCoreOptions> options, IHub hub)
Expand Down
11 changes: 6 additions & 5 deletions src/Sentry.AspNetCore/SentryWebHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,15 @@ public static IWebHostBuilder UseSentry(
_ = logging.Services.AddSingleton<ILoggerProvider, SentryAspNetCoreLoggerProvider>();
_ = logging.Services.AddSingleton<ILoggerProvider, SentryAspNetCoreStructuredLoggerProvider>();

_ = logging.AddFilter<SentryAspNetCoreLoggerProvider>(
"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware",
LogLevel.None);
_ = logging.AddFilter<SentryAspNetCoreStructuredLoggerProvider>(static (string? categoryName, LogLevel logLevel) =>
// Add a delegate rule in order to ignore Configuration like "appsettings.json" and "appsettings.{HostEnvironment}.json"
_ = logging.AddFilter<SentryAspNetCoreLoggerProvider>(static (string? categoryName, LogLevel logLevel) =>
{
return categoryName is null
|| (categoryName != "Sentry.ISentryClient" && categoryName != "Sentry.AspNetCore.SentryMiddleware");
|| categoryName != "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware";
});
// Add non-delegate rules in order to respect Configuration like "appsettings.json" and "appsettings.{HostEnvironment}.json"
_ = logging.AddFilter<SentryAspNetCoreStructuredLoggerProvider>("Sentry.ISentryClient", LogLevel.None);
_ = logging.AddFilter<SentryAspNetCoreStructuredLoggerProvider>("Sentry.AspNetCore.SentryMiddleware", LogLevel.None);

var sentryBuilder = logging.Services.AddSentry();
configureSentry?.Invoke(context, sentryBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,11 @@ internal class BindableSentryLoggingOptions : BindableSentryOptions
public LogLevel? MinimumEventLevel { get; set; }
public bool? InitializeSdk { get; set; }

public BindableSentryLoggingExperimentalOptions ExperimentalLogging { get; set; } = new();

internal sealed class BindableSentryLoggingExperimentalOptions
{
public LogLevel? MinimumLogLevel { 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;

options.ExperimentalLogging.MinimumLogLevel = ExperimentalLogging.MinimumLogLevel ?? options.ExperimentalLogging.MinimumLogLevel;
}
}
8 changes: 2 additions & 6 deletions src/Sentry.Extensions.Logging/LoggingBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,8 @@ internal static ILoggingBuilder AddSentry<TOptions>(
builder.AddFilter<SentryLoggerProvider>(_ => true);

// Logs from the SentryLogger should not flow to the SentryStructuredLogger as this may cause recursive invocations.
// Filtering of logs is handled in SentryStructuredLogger, using SentryOptions.MinimumLogLevel
builder.AddFilter<SentryStructuredLoggerProvider>(static (string? categoryName, LogLevel logLevel) =>
{
return categoryName is null
|| categoryName != "Sentry.ISentryClient";
});
// Filtering of structured logs is handled by Microsoft.Extensions.Configuration and Microsoft.Extensions.Options.
builder.AddFilter<SentryStructuredLoggerProvider>("Sentry.ISentryClient", LogLevel.None);

return builder;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Sentry.Extensions.Logging/SentryLoggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
namespace Sentry.Extensions.Logging;

/// <summary>
/// Sentry Logger Provider.
/// Sentry Logger Provider for <see cref="Breadcrumb"/> and <see cref="SentryEvent"/>.
/// </summary>
[ProviderAlias("Sentry")]
public class SentryLoggerProvider : ILoggerProvider
internal class SentryLoggerProvider : ILoggerProvider
{
private readonly ISystemClock _clock;
private readonly SentryLoggingOptions _options;
Expand Down
35 changes: 0 additions & 35 deletions src/Sentry.Extensions.Logging/SentryLoggingOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,39 +50,4 @@ public class SentryLoggingOptions : SentryOptions
/// List of callbacks to be invoked when initializing the SDK
/// </summary>
internal Action<Scope>[] ConfigureScopeCallbacks { get; set; } = Array.Empty<Action<Scope>>();

/// <summary>
/// Experimental Sentry Logging features.
/// </summary>
/// <remarks>
/// This and related experimental APIs may change in the future.
/// </remarks>
[Experimental(Infrastructure.DiagnosticId.ExperimentalFeature)]
public SentryLoggingExperimentalOptions ExperimentalLogging { get; set; } = new();

/// <summary>
/// Experimental Sentry Logging options.
/// </summary>
/// <remarks>
/// This and related experimental APIs may change in the future.
/// </remarks>
[Experimental(Infrastructure.DiagnosticId.ExperimentalFeature)]
public sealed class SentryLoggingExperimentalOptions
{
internal SentryLoggingExperimentalOptions()
{
}

/// <summary>
/// Gets or sets the minimum log level.
/// <para>This API is experimental and it may change in the future.</para>
/// </summary>
/// <remarks>
/// Logs with this level or higher will be stored as <see cref="SentryLog"/>.
/// </remarks>
/// <value>
/// The minimum log level.
/// </value>
public LogLevel MinimumLogLevel { get; set; } = LogLevel.Trace;
}
}
4 changes: 2 additions & 2 deletions src/Sentry.Extensions.Logging/SentryLoggingOptionsSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Sentry.Extensions.Logging;

internal class SentryLoggingOptionsSetup : IConfigureOptions<SentryLoggingOptions>
internal sealed class SentryLoggingOptionsSetup : IConfigureOptions<SentryLoggingOptions>
{
private readonly IConfiguration _config;

Expand All @@ -30,7 +30,7 @@ public void Configure(SentryLoggingOptions options)

namespace Sentry.Extensions.Logging;

internal class SentryLoggingOptionsSetup : ConfigureFromConfigurationOptions<SentryLoggingOptions>
internal sealed class SentryLoggingOptionsSetup : ConfigureFromConfigurationOptions<SentryLoggingOptions>
{
public SentryLoggingOptionsSetup(
ILoggerProviderConfiguration<SentryLoggerProvider> providerConfiguration)
Expand Down
3 changes: 1 addition & 2 deletions src/Sentry.Extensions.Logging/SentryStructuredLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ public bool IsEnabled(LogLevel logLevel)
{
return _hub.IsEnabled
&& _options.EnableLogs
&& logLevel != LogLevel.None
&& logLevel >= _options.ExperimentalLogging.MinimumLogLevel;
&& logLevel != LogLevel.None;
}

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace Sentry.Extensions.Logging;

/// <summary>
/// Sentry Structured Logger Provider.
/// Sentry Logger Provider for <see cref="SentryLog"/>.
/// </summary>
[ProviderAlias("SentryLogs")]
[ProviderAlias("Sentry")]
internal class SentryStructuredLoggerProvider : ILoggerProvider
{
private readonly SentryLoggingOptions _options;
Expand All @@ -20,6 +20,11 @@ public SentryStructuredLoggerProvider(IOptions<SentryLoggingOptions> options, IH
{
}

internal SentryStructuredLoggerProvider(IHub hub, ISystemClock clock, SentryLoggingOptions options)
: this(options, hub, clock, CreateSdkVersion())
{
}

internal SentryStructuredLoggerProvider(SentryLoggingOptions options, IHub hub, ISystemClock clock, SdkVersion sdk)
{
_options = options;
Expand Down
13 changes: 10 additions & 3 deletions src/Sentry.Google.Cloud.Functions/SentryStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,17 @@ public override void ConfigureLogging(WebHostBuilderContext context, ILoggingBui

logging.Services.AddSingleton<IConfigureOptions<SentryAspNetCoreOptions>, SentryAspNetCoreOptionsSetup>();
logging.Services.AddSingleton<ILoggerProvider, SentryAspNetCoreLoggerProvider>();
logging.Services.AddSingleton<ILoggerProvider, SentryAspNetCoreStructuredLoggerProvider>();

logging.AddFilter<SentryAspNetCoreLoggerProvider>(
"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware",
LogLevel.None);
// Add a delegate rule in order to ignore Configuration like "appsettings.json" and "appsettings.{HostEnvironment}.json"
logging.AddFilter<SentryAspNetCoreLoggerProvider>(static (string? categoryName, LogLevel logLevel) =>
{
return categoryName is null
|| categoryName != "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware";
});
// Add non-delegate rules in order to respect Configuration like "appsettings.json" and "appsettings.{HostEnvironment}.json"
logging.AddFilter<SentryAspNetCoreStructuredLoggerProvider>("Sentry.ISentryClient", LogLevel.None);
logging.AddFilter<SentryAspNetCoreStructuredLoggerProvider>("Sentry.AspNetCore.SentryMiddleware", LogLevel.None);

logging.Services.AddSentry();
}
Expand Down
11 changes: 10 additions & 1 deletion src/Sentry.Maui/Internal/SentryMauiLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Sentry.Extensions.Logging;
using Sentry.Infrastructure;

namespace Sentry.Maui.Internal;

/// <summary>
/// Sentry Logger Provider for <see cref="Breadcrumb"/> and <see cref="SentryEvent"/>.
/// </summary>
[ProviderAlias("Sentry")]
internal class SentryMauiLoggerProvider : SentryLoggerProvider
internal sealed class SentryMauiLoggerProvider : SentryLoggerProvider
{
public SentryMauiLoggerProvider(IOptions<SentryMauiOptions> options, IHub hub)
: base(options, hub)
{
}

internal SentryMauiLoggerProvider(SentryMauiOptions options, IHub hub, ISystemClock clock)
: base(hub, clock, options)
{
}
}
Loading
Loading