Asp.Net Core 3.1 每次请求记录接口访问日志

我们总是有记录操作日志的需求,很早以前可以使用ActionFilter来实现,现在可已使用自定义中间键的方法

  1. 首先定义RequestResponseLoggingMiddleware中间件。说明这里日志记录通过Repository记录在数据库中,有其他需求的同学可以自定义这块,比如想通过nlog或log4net记录日志
public class RequestResponseLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private RequestResponseLog _logInfo;

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

    public async Task Invoke(HttpContext context)
    {
        _logInfo = new RequestResponseLog();
        var serviceProvider = context.RequestServices;
        var logRepo = (IAsyncRepository<Log>)serviceProvider.GetService(typeof(IAsyncRepository<Log>));

        HttpRequest request = context.Request;
        _logInfo.Url = request.Path.ToString();
        _logInfo.Headers = request.Headers.ToDictionary(k => k.Key, v => string.Join(";", v.Value.ToList()));
        _logInfo.Method = request.Method;
        _logInfo.ExcuteStartTime = DateTime.Now;

        //获取request.Body内容
        if (request.Method.ToLower().Equals("post"))
        {

            HttpRequestRewindExtensions.EnableBuffering(request); //启用倒带功能,就可以让 Request.Body 可以再次读取

            Stream stream = request.Body;
            request.Body.Position = 0;

            StreamReader sr = new StreamReader(request.Body);
            string bodyContent = await sr.ReadToEndAsync();
            _logInfo.RequestBody = bodyContent;

            request.Body.Position = 0;
        }
        else if (request.Method.ToLower().Equals("get"))
        {
            _logInfo.RequestBody = request.QueryString.Value;
        }

        //获取Response.Body内容
        var originalBodyStream = context.Response.Body;

        using (var responseBody = new MemoryStream())
        {
            context.Response.Body = responseBody;

            await _next(context);

            _logInfo.ResponseBody = await FormatResponse(context.Response);
            _logInfo.ExcuteEndTime = DateTime.Now;
            await logRepo.AddAsync(new Log
            {
                User = "admin",
                Content = _logInfo.ToString(),
                CreateTime = DateTime.Now
            });
            await logRepo.SaveChangesAsync();

            await responseBody.CopyToAsync(originalBodyStream);
        }
    }

    private async Task<string> FormatResponse(HttpResponse response)
    {
        response.Body.Seek(0, SeekOrigin.Begin);
        var text = await new StreamReader(response.Body).ReadToEndAsync();
        response.Body.Seek(0, SeekOrigin.Begin);

        return text;
    }
}

public static class RequestResponseLoggingMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestResponseLogging(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestResponseLoggingMiddleware>();
    }
}

2.在Startup的Configure中add中间件

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRequestResponseLogging();
}
posted @ 2023-04-21 10:17  小辫子啦啦啦  阅读(311)  评论(0编辑  收藏  举报