Allow to pass an exception to the "logging module" through other means than HttpContext.AddError
tsimbalar opened this issue · comments
The current means for the module to log the errors is to take a look at Server.GetLastError()
(this is actually how the SerilogWeb.Classic.WebAPI pushes unhandled exceptions to the logging module).
While it covers most scenarios, it is kind of problematic when using IIS Custom Error Pages and ASP.NET MVC together.
In MVC, the standard one way to handle errors is by using HandleErrorAttribute
(or a subclass) that states which view should be shown depending on the thrown exception.
While this sets the proper HttpCode for the response (the generated log event has the proper status code), the Exception is actually lost and does not appear in the log. (see #29 where this exception is logged only when CustomErrors="Off"
).
When I write a custom IExceptionFilter
/ FilterAttribute
, I can add the exception through a call to filterContext.HttpContext.AddError(myException)
. When I do that, the Exception properly appears in the logs, but the presence of this Exception in the list of errors seems to trigger the IIS Custom Errors mechanism, and no matter what, instead of showing a custom view (passed to the attribute), the IIS-custom error page that is configured for Status Code 500 is shown ...
It seems I can either choose between either using AuthorizeAttribute
or having exceptions in my logs ... which is not ideal ...
Maybe we should need a way to report an exception to the Logging Module without going through HttpContext.AddError()
...
I am thinking that it could be something like :
- adding an extension method on top of
HttpContext
(and friends) :AddSerilogWebError(Exception ex)
that would store that Exception somewhere in the current context - modify the current LoggingModule to look for Exceptions in :
Server.GetLastError()
(current behavior)Context.AllErrors.LastOrDefault()
(current behavior)- in the part of context where
AddSerilogWebError
stored it (new behavior)
This would allow to add write a custom AuthorizeAttribute
that would store exceptions specifically for the logging module.
Optionnally SerilogWeb.Classic.WebApi could also use that channel to report to the logging module instead of using Context.AddError()
.
Does that make sense ?
I think this would also be helpful to report errors in "stacks" on top of ASP.NET like :
- WCF (when hosted in IIS)
- MVC
- Web API
without interfering too much into the hard-coupling IIS / ASP.NET
I implemented something locally that seems ok which basically just follows what was already done for the stopwatch in WebRequestLoggingHandler
.
I think it just needs a nicer public api/wrapping with some update to the readme documentation to support the approach.
In my custom ExceptionFilterAttribute
for OnException
and OnExceptionAsync
I added:
HttpContext.Current?.Items.Add(SerilogWebClassic.ErrorKey, context.Exception);
1 line modification to SerilogWeb.Classic.WebRequestLoggingHandler
var error = _application.Server.GetLastError() ?? _application.Context.Items[SerilogWebClassic.ErrorKey] as Exception;
I guess you could switch the order on the above if you want custom exception tracking to have a higher priority.
For the public library version, an extension method could be provided to avoid needing to know about the key details
public static void AddSerilogException(this HttpContext context, Exception ex)
{
context.Items.Add(SerilogWebClassic.ErrorKey, ex);
}
Hi @laurencee ,
so sorry for taking so long to react ...
Yes that looks exactly like what I had in mind !
In terms of priority, I think the custom exception should indeed have higher priority (later on, this could be customizable, but that's probably not necessary from the start)
Do you think you could find the time to create a Pull Request for this one ?
@tsimbalar Hey sorry about taking a while to get back to you, we had actually moved over to net core so I forgot about looking at this.
I'll see if I can get a PR up for this next week or week after, quite a busy time leading up to holidays :)