Home > OS >  How to disable Serilog to log one exception?
How to disable Serilog to log one exception?

Time:07-07

(Asp.Net core 3.1/.Net 6) I need to disable the ERR logging of exception TaskCanceledException in an Asp.Net application (built by others). I've used the following middleware to suppress the TaskCanceledException

app.UseMiddleware<TaskCanceledMiddleware>();

public class TaskCanceledMiddleware
{
    private readonly RequestDelegate _next;

    public TaskCanceledMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (TaskCanceledException)
        {
            // Set StatusCode 499 Client Closed Request
            logger.WARN("...")
            context.Response.StatusCode = 499;
        }
    }
}

I can see the WARN log in the logs. However, I can still find the following EROR messages by Serilog.AspNetCore.RequestLoggingMiddleware? (Note the error level is EROR)

2022-07-06 07:30:40.6636|116344477|EROR|Serilog.AspNetCore.RequestLoggingMiddleware|HTTP "GET" "/api/v1/myurl" responded 500 in 23213.3233 ms
System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at ....

Why there is still errors of TaskCanceledException after using app.UseMiddleware<TaskCanceledMiddleware>()? (BTW, what's the level of EROR? Shouldn't it be ERR?)

CodePudding user response:

do you know where the exception is thrown? Maybe it throws not inside asp.net core action execution pipeline (where Middleware works). You can register a filter to intercept application wide exceptions inside .AddControllers() registration like this:

 _ = services
        .AddControllers(options =>
        {
            //Global filters
            _ = options.Filters.Add<ApiGlobalExceptionFilterAttribute>();
            ///...omissis...
        })

Here a simple exception filter attribute implementation:

public sealed class ApiGlobalExceptionFilterAttribute : ExceptionFilterAttribute
{
    private readonly ILogger<ApiGlobalExceptionFilterAttribute> _logger;

    public ApiGlobalExceptionFilterAttribute(ILogger<ApiGlobalExceptionFilterAttribute> logger)
    {
        _logger = logger;
    }

    public override void OnException(ExceptionContext context)
    {
        var request = context.HttpContext?.Request;

        if (context.Exception is TaskCanceledException tcExc)
        {
            // Set StatusCode 499 Client Closed Request
            _logger.WARN("...");
            context.Result = new ErrorActionResult(499);
        }
        else
        {
            //TODO: manage errors
        }

        context.ExceptionHandled = true;

        base.OnException(context);
    }
}

internal class ErrorActionResult : IActionResult
{
    [JsonIgnore]
    public int StatusCode { get; private set; }

    public ErrorActionResult(int statusCode)
    {
        StatusCode = statusCode;
    }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        var error = new
        {
            Code = StatusCode,
            Message = "Internal server error"
        };

        var objectResult = new ObjectResult(error)
        {
            StatusCode = StatusCode
        };

        await objectResult.ExecuteResultAsync(context);
    }
}

The context.ExceptionHandled = true; stops exception to be propagated inside pipeline.

Hope it helps!

CodePudding user response:

you can try excluding logging for certain exception like this.

new LoggerConfiguration()
       ....
       .Filter.ByExcluding(logEvent => logEvent.Exception != null && logEvent.Exception.GetType() == typeof(TaskCanceledException))
       ...CreateLogger();
  • Related