In my ASP.NET Core project I have some places where I’m handling a potential exception with a try-catch block. In those cases I don’t want the exception to be reported to sentry, since I’ve caught it and dealt with it already in code.
How can I prevent those exceptions from being sent to Sentry? I am a little bit surprised that Sentry would log those kinds of exceptions, since my assumption was that by default it would only log uncaught exceptions.
Sentry will log anything that goes unhandled, but also what you capture explicitly with SentrySdk.CaptureException. Additionally, it has logging integrations. With ASP.NET Core it automatically captures any LogError and LogCritical as events. And any LogWarning and LogInformation are included as breadcrumbs, to any events captured for a particular web request.
It sounds to me that you’re handling an exception and calling LogError in the catch blog. You can stop the SDK from capturing those in a few different ways: Add a BeforeSend callback to filter events based on some of its properties:
For example a property to use is the SDK name, that has the value sentry.dotnet.extensions.logging.
Another, simpler alternative is to raise the minimum level required for the integration to capture an event. By default it’s Error but you could raise to Critical. So only if you’re calling LogCritical it’ll send an event to Sentry.
Thank you for your reply, @bruno-garcia . To provide a little bit more context: Inside an ASP.NET Core route, I’m doing some EF Core logic:
try
{
// Save some changes that we expect to fail sometimes
await _context.SaveChangesAsync();
}
catch (DbUpdateException)
{
// In this example, since the DB update failed, we simply return NoContent().
return NoContent();
}
So it looks like you’re right and Sentry might be getting its event from a LogError message from EF Core. In fact, it’s two separate log messages: one from "Microsoft.EntityFrameworkCore.Database.Command" and one from "Microsoft.EntityFrameworkCore.Update".
So you’re suggesting to filter in BeforeSend based on the logger-source, right? (just so I understand correctly).
I’m wondering if there is a way to keep handling EF Core`s LogError events in Sentry except for those cases like above, where I catch the exception. Basically, seeing LogError events in general show up in Sentry sounds great… except for those cases where I already caught the exception and handled it. What would be a nice way to achieve that?
I have investigated this some more and either something is wrong in the SDK or I must be missing something:
I have created two identical controller actions with the only difference being that one action catches the DbUpdateException thrown by EF Core and handles it, whereas the other controller action doesn’t catch the exception at all (in which case we’d expect Sentry to catch it at the end).
Now, when I define a BeforeSend callback and I inspect the sentryEvent, it looks identical in both cases (caught / uncaught). So there is no way for me to tell Sentry:
ignore this one exception (since it was caught)
continue with the capture of that exception (since it was not caught)
… since I cannot distinguish between caught and uncaught.
I must be missing something. There must be a way for Sentry to distinguish between caught EF Core exceptions and uncaught EF Core exceptions. Otherwise it would defeat the whole purpose of using Sentry in the first place.
More info:
In both exception cases (caught, uncaught) the logger shows as Microsoft.EntityFrameworkCore.Update with level error
It’s identical because in both cases EF is calling LogError which Sentry captures. If the same exception instance is logged twice, Sentry’s deduplication logic drops the second capture:
The BeforeSend suggestion was one of them. You can also use the specific ASPNET logging filter for example how it’s done here:
The problem here is that EF is logging it internal as Error. It can’t possible know if you’re about to handle that once they throw, or not. At the point it gets to your catch block (or not) Sentry already received an error and it’s doing its job of sending it to the backend.