Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net Core Web API Capturing HTTP Requests for Logging

I'm having difficulty capturing HTTP requests for logging purposes in ASP.NET Core Web API. I was able to find an example here

http://dotnetliberty.com/index.php/2016/01/07/logging-asp-net-5-requests-using-middleware/

which has helped. It's basically a logging class that gets added to the HTTP request pipeline using the middleware functionality. The problem is that the class method only gets invoked on application start up. I can't get it to be invoked on any of my get or post http requests. The get or post http requests are working because I can debug and the responses are ok which I tried using Fiddler and http client within a console application.

Here is my logging class

using Microsoft.AspNetCore.Http; 
using Microsoft.Extensions.Logging; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Threading.Tasks; 


namespace CoreWebAPI.Models 
{ 
public class RequestLoggingMiddleware 
{ 
    private readonly RequestDelegate _next; 
    private readonly ILogger<RequestLoggingMiddleware> _logger; 


    public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger) 
    { 
        _next = next; 
        _logger = logger; 
    } 


    public async Task Invoke(HttpContext context) 
    { 
        var startTime = DateTime.UtcNow; 


        var watch = Stopwatch.StartNew(); 
        await _next.Invoke(context); 
        watch.Stop(); 


        var logTemplate = @" 
Client IP: {clientIP} 
Request path: {requestPath} 
Request content type: {requestContentType} 
Request content length: {requestContentLength} 
Start time: {startTime} 
Duration: {duration}"; 


        _logger.LogInformation(logTemplate, 
            context.Connection.RemoteIpAddress.ToString(), 
            context.Request.Path, 
            context.Request.ContentType, 
            context.Request.ContentLength, 
            startTime, 
            watch.ElapsedMilliseconds); 
    } 
} 
} 

And here is my Startup.Configure method in my Startup.cs class

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
        loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
        loggerFactory.AddDebug(); 




        app.UseApplicationInsightsRequestTelemetry(); 


        app.UseApplicationInsightsExceptionTelemetry(); 


        app.UseMvc(); 
        app.UseCors(builder => builder.AllowAnyOrigin()); 


        app.UseMiddleware<RequestLoggingMiddleware>(); 

    }

The last line is where I piggy back onto the HTTP requests using app.UseMiddleware. I think this should work but if anyone has a clue why it doesn't or an alternative that'd be great. Please let me know if you I should provide additional information.

like image 980
Don Avatar asked Feb 06 '23 22:02

Don


2 Answers

The middleware are invoked in sort of a pipeline, in the order they are registered, and they all decide whether they should invoke the next one or not (see your own logging middleware: await _next.Invoke(context);).

When a requests comes in that is handled by the Mvc framework, it will not be passed down to the next middleware.

To get logging on all requests you need to put the registration of the logging before any middleware that terminates the pipeline, such as Mvc.

like image 196
rmac Avatar answered Feb 09 '23 12:02

rmac


This will work just fine.

public async Task Invoke(HttpContext context)
{
    var timer = new Stopwatch();
    timer.Start();
    await _next(context);

    //Need to stop the timer after the pipeline finish
    timer.Stop();
    _logger.LogDebug("The request took '{0}' ms", timerer.ElapsedMilliseconds);
}

in the Startup you need to add the Middleware at the begining of the pipeline

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{ 
    loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
    loggerFactory.AddDebug(); 

    app.UseMiddleware<RequestLoggingMiddleware>();

    // rest of the middlewares 
      ..................

    app.UseMvc(); 
}
like image 30
Mihai Dumitrascu Avatar answered Feb 09 '23 11:02

Mihai Dumitrascu