Skip to content

Commit 12f24bb

Browse files
committed
Add option to exception handler middleware to not log error
1 parent 091e35e commit 12f24bb

File tree

5 files changed

+29
-9
lines changed

5 files changed

+29
-9
lines changed

src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddlewareImpl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ public async Task Invoke(HttpContext context)
115115
}
116116
catch (Exception ex)
117117
{
118+
DiagnosticsTelemetry.AddMetricsTags(context, ex);
119+
118120
var exceptionName = ex.GetType().FullName!;
119121

120122
if ((ex is OperationCanceledException || ex is IOException) && context.RequestAborted.IsCancellationRequested)
@@ -135,8 +137,6 @@ public async Task Invoke(HttpContext context)
135137
return;
136138
}
137139

138-
DiagnosticsTelemetry.ReportUnhandledException(_logger, context, ex);
139-
140140
if (context.Response.HasStarted)
141141
{
142142
_logger.ResponseStartedErrorPageMiddleware();

src/Middleware/Diagnostics/src/DiagnosticsTelemetry.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@
33

44
using Microsoft.AspNetCore.Http.Features;
55
using Microsoft.AspNetCore.Http;
6-
using Microsoft.Extensions.Logging;
76

87
namespace Microsoft.AspNetCore.Diagnostics;
98

109
internal static class DiagnosticsTelemetry
1110
{
12-
public static void ReportUnhandledException(ILogger logger, HttpContext context, Exception ex)
11+
public static void AddMetricsTags(HttpContext context, Exception ex)
1312
{
14-
logger.UnhandledException(ex);
15-
1613
if (context.Features.Get<IHttpMetricsTagsFeature>() is { } tagsFeature)
1714
{
1815
// Multiple exception middleware could be registered that have already added the tag.

src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerMiddlewareImpl.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,13 @@ static async Task Awaited(ExceptionHandlerMiddlewareImpl middleware, HttpContext
112112

113113
private async Task HandleException(HttpContext context, ExceptionDispatchInfo edi)
114114
{
115+
DiagnosticsTelemetry.AddMetricsTags(context, edi.SourceException);
116+
115117
var exceptionName = edi.SourceException.GetType().FullName!;
116118

117119
if ((edi.SourceException is OperationCanceledException || edi.SourceException is IOException) && context.RequestAborted.IsCancellationRequested)
118120
{
121+
// Don't log unhandled exception for aborted request.
119122
_logger.RequestAbortedException();
120123

121124
if (!context.Response.HasStarted)
@@ -127,11 +130,10 @@ private async Task HandleException(HttpContext context, ExceptionDispatchInfo ed
127130
return;
128131
}
129132

130-
DiagnosticsTelemetry.ReportUnhandledException(_logger, context, edi.SourceException);
131-
132133
// We can't do anything if the response has already started, just abort.
133134
if (context.Response.HasStarted)
134135
{
136+
_logger.UnhandledException(edi.SourceException);
135137
_logger.ResponseStartedErrorHandler();
136138

137139
_metrics.RequestException(exceptionName, ExceptionResult.Skipped, handler: null);
@@ -201,6 +203,7 @@ private async Task HandleException(HttpContext context, ExceptionDispatchInfo ed
201203
}
202204
}
203205
}
206+
204207
// If the response has already started, assume exception handler was successful.
205208
if (context.Response.HasStarted || handled || _options.StatusCodeSelector != null || context.Response.StatusCode != StatusCodes.Status404NotFound || _options.AllowStatusCode404Response)
206209
{
@@ -210,10 +213,18 @@ private async Task HandleException(HttpContext context, ExceptionDispatchInfo ed
210213
WriteDiagnosticEvent(_diagnosticListener, eventName, new { httpContext = context, exception = edi.SourceException });
211214
}
212215

216+
if (!_options.SuppressLoggingOnHandledException)
217+
{
218+
_logger.UnhandledException(edi.SourceException);
219+
}
220+
213221
_metrics.RequestException(exceptionName, ExceptionResult.Handled, handler);
214222
return;
215223
}
216224

225+
// Log original unhandled exception before it is wrapped.
226+
_logger.UnhandledException(edi.SourceException);
227+
217228
edi = ExceptionDispatchInfo.Capture(new InvalidOperationException($"The exception handler configured on {nameof(ExceptionHandlerOptions)} produced a 404 status response. " +
218229
$"This {nameof(InvalidOperationException)} containing the original exception was thrown since this is often due to a misconfigured {nameof(ExceptionHandlerOptions.ExceptionHandlingPath)}. " +
219230
$"If the exception handler is expected to return 404 status responses then set {nameof(ExceptionHandlerOptions.AllowStatusCode404Response)} to true.", edi.SourceException));
@@ -222,6 +233,9 @@ private async Task HandleException(HttpContext context, ExceptionDispatchInfo ed
222233
{
223234
// Suppress secondary exceptions, re-throw the original.
224235
_logger.ErrorHandlerException(ex2);
236+
237+
// There was an error handling the exception. Log original unhandled exception.
238+
_logger.UnhandledException(edi.SourceException);
225239
}
226240
finally
227241
{

src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerOptions.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,17 @@ public class ExceptionHandlerOptions
4040
public bool AllowStatusCode404Response { get; set; }
4141

4242
/// <summary>
43-
/// Gets or sets a delegate used to map an exception to a http status code.
43+
/// Gets or sets a delegate used to map an exception to an HTTP status code.
4444
/// </summary>
4545
/// <remarks>
4646
/// If <see cref="StatusCodeSelector"/> is <c>null</c>, the default exception status code 500 is used.
4747
/// </remarks>
4848
public Func<Exception, int>? StatusCodeSelector { get; set; }
49+
50+
/// <summary>
51+
/// Gets or sets a value that determines if the exception handler middleware should suppress logging
52+
/// if the exception was handled by either <see cref="ExceptionHandler"/>, <see cref="IProblemDetailsService"/> or
53+
/// <see cref="IExceptionHandler"/> registered in the DI container.
54+
/// </summary>
55+
public bool SuppressLoggingOnHandledException { get; set; }
4956
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
#nullable enable
2+
Microsoft.AspNetCore.Builder.ExceptionHandlerOptions.SuppressLoggingOnHandledException.get -> bool
3+
Microsoft.AspNetCore.Builder.ExceptionHandlerOptions.SuppressLoggingOnHandledException.set -> void

0 commit comments

Comments
 (0)