Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions sentry-dotnet/5265/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o /out

FROM mcr.microsoft.com/dotnet/aspnet:10.0
WORKDIR /app
COPY --from=build /out .
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
ENTRYPOINT ["dotnet", "Sentry.Repro.dll"]
107 changes: 107 additions & 0 deletions sentry-dotnet/5265/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Sentry;
using Sentry.AspNetCore;
using Sentry.Extensibility;
using Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSerilog((_, c) =>
c.Enrich.FromLogContext()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.Sentry());

builder.Services.AddTransient<ISentryEventProcessor, ExampleEventProcessor>();

((IWebHostBuilder)builder.WebHost).UseSentry(o =>
{
o.Dsn = Environment.GetEnvironmentVariable("SENTRY_DSN")
?? "https://examplePublicKey@o0.ingest.sentry.io/0";
o.Debug = true;
});

var app = builder.Build();

app.Use(async (context, next) =>
{
var log = context.RequestServices.GetRequiredService<ILoggerFactory>()
.CreateLogger("ReproTest");

if (context.Request.Path == "/test")
{
ExampleEventProcessor.CallCount = 0;

Console.WriteLine();
Console.WriteLine("========================================");
Console.WriteLine("=== Test 1: Static Serilog Logger ===");
Console.WriteLine("========================================");
// Goes through: Serilog -> WriteTo.Sentry() -> SentrySink -> SentrySdk.CaptureEvent
Log.Logger.Error("Error via static Serilog logger");

await Task.Delay(500);
var countAfterTest1 = ExampleEventProcessor.CallCount;

Console.WriteLine();
Console.WriteLine("========================================");
Console.WriteLine("=== Test 2: ILogger (log.LogError) ===");
Console.WriteLine("========================================");
// Goes through: ILogger -> Serilog (via UseSerilog) -> WriteTo.Sentry() -> SentrySink
// BUG: ISentryEventProcessor should be called but reportedly is not
log.LogError(new InvalidOperationException("test exception"), "Error via ILogger");

await Task.Delay(500);
var countAfterTest2 = ExampleEventProcessor.CallCount;

Console.WriteLine();
Console.WriteLine("========================================");
Console.WriteLine("=== Summary ===");
Console.WriteLine("========================================");
Console.WriteLine($"ExampleEventProcessor called after Test 1: {countAfterTest1} time(s)");
Console.WriteLine($"ExampleEventProcessor called after Test 2: {countAfterTest2 - countAfterTest1} time(s)");

if (countAfterTest2 - countAfterTest1 == 0)
{
Console.WriteLine("BUG CONFIRMED: ISentryEventProcessor was NOT called for ILogger path!");
}
else
{
Console.WriteLine("Bug NOT reproduced: ISentryEventProcessor was called for both paths.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete reproduction pass criteria

Low Severity

The /test summary treats a zero increase after Test 2 as proof the ILogger path skipped ISentryEventProcessor, without requiring Test 1 to increment CallCount. If neither path invokes the processor, or only static Serilog fails, the console text can still claim an ILogger-only bug or that the issue was not reproduced.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8620203. Configure here.

}

context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(
$"Test 1 (static Serilog): ExampleEventProcessor called {countAfterTest1} time(s)\n" +
$"Test 2 (ILogger): ExampleEventProcessor called {countAfterTest2 - countAfterTest1} time(s)\n" +
"Check the server console for full details.\n");
}
else
{
await next();
}
});

app.MapGet("/", () => "Navigate to /test to trigger the reproduction");

app.Run();

sealed class ExampleEventProcessor : ISentryEventProcessor
{
public static int CallCount;

public SentryEvent Process(SentryEvent @event)
{
Interlocked.Increment(ref CallCount);
Console.WriteLine($">>> ExampleEventProcessor.Process CALLED! (call #{CallCount})");
Console.WriteLine($" Message: {@event.Message?.Formatted ?? "(no message)"}");
Console.WriteLine($" Exception: {@event.Exception?.Message ?? "(no exception)"}");
return @event;
}
}
55 changes: 55 additions & 0 deletions sentry-dotnet/5265/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Reproduction for sentry-dotnet#5265

**Issue:** https://github.com/getsentry/sentry-dotnet/issues/5265

## Description

The issue reports that `ISentryEventProcessor` implementations registered via DI
(`builder.Services.AddTransient<ISentryEventProcessor, ExampleEventProcessor>()`) are **not** called
when logging through `Microsoft.Extensions.Logging.ILogger` (e.g., `log.LogError(...)`), but **are**
called when logging through the static Serilog logger (`Log.Logger.Error(...)`).

## Steps to Reproduce

1. Build and run with Docker:
```bash
docker build -t sentry-repro-5265 .
docker run --rm -p 8085:8080 sentry-repro-5265
```

Optionally set a real Sentry DSN:
```bash
export SENTRY_DSN=https://your-dsn@sentry.io/0
docker run --rm -p 8085:8080 -e SENTRY_DSN sentry-repro-5265
```

2. Trigger the test:
```bash
curl http://localhost:8085/test
```

3. Check the server console output for `ExampleEventProcessor.Process CALLED!` messages.

## Expected Behavior

`ExampleEventProcessor.Process` should be called for **both**:
- Test 1: `Log.Logger.Error(...)` (static Serilog logger)
- Test 2: `log.LogError(...)` (ILogger from Microsoft.Extensions.Logging)

## Actual Behavior

According to the issue, `ExampleEventProcessor.Process` is only called for Test 1 (static Serilog),
**not** for Test 2 (ILogger).

**Note:** In this reproduction (Sentry 6.5.0, .NET 10), the event processor IS called for both paths.
The issue author reports the bug when running from Visual Studio with a debugger attached. The bug may
be related to how the debugger interacts with the event processing pipeline, or to a specific
environment configuration.

## Environment

- .NET: 10.0
- Sentry.AspNetCore: 6.5.0
- Sentry.Serilog: 6.5.0
- Serilog: 4.3.1
- Serilog.AspNetCore: 10.0.0
15 changes: 15 additions & 0 deletions sentry-dotnet/5265/Sentry.Repro.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Sentry.AspNetCore" Version="6.5.0" />
<PackageReference Include="Sentry.Serilog" Version="6.5.0" />
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
</ItemGroup>

</Project>
Loading