繁体   English   中英

如何在asp.net core(Kestrel)中记录http请求消息(非正文)和响应消息(非正文)

[英]how to log http request message(not body) and response message(not body) in asp.net core(Kestrel)

我的要求样本

GET http://localhost:5000/api/values HTTP/1.1
cache-control: no-cache
User-Agent: PostmanRuntime/6.4.1
Accept: */*
Host: localhost:5000
accept-encoding: gzip, deflate
Connection: keep-alive

和回应

HTTP/1.1 200 OK
Date: Wed, 28 Mar 2018 07:18:08 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 19

["value1","value2"]

我想获取所有HTTP消息进行日志

我应该如何获取请求消息和响应消息

因为我可以找到任何错误的日志(例如错误请求消息(自定义TCP))

一种选择是创建自定义中间件,然后您可以在其中检查请求/响应以建立所需的日志。

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?tabs=aspnetcore2x#writing-middleware

中间件使您可以在传入和传出中获取请求。

在上下文(HttpContext)上,您应该能够获取所需的数据-https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.http.httpcontext?view=aspnetcore- 2.0

我写了一个中间件,以nginx风格记录访问日志。 您可以执行大致相同的操作,并在LogData类中添加并填充自己的字段,然后更改DefaultFormatter函数。

public class RequestLogMiddleware
{

    public class LogData {
        public IPAddress RemoteAddr {get;set;}
        public string User {get; set;}
        public int ResponseStatus {get; set;}

        public string RequestMethod {get;set;}
        public string RequestTimestamp {get;set;}
        public string RequestPath {get;set;}

        public string RequestProtocol {get;set;}
        public string UserAgent {get;set;}

        public long DurationMs {get;set;}
    }

    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public RequestLogMiddleware(RequestDelegate next, ILoggerFactory factory)
    {
        _next = next;
        _logger = factory.CreateLogger("RequestLog");

    }

    private Func<LogData, string> _logLineFormatter;
    private Func<LogData,string> logLineFormatter{
        get  {

            if (this._logLineFormatter != null) {
                return this._logLineFormatter;
            } 
            return this.DefaultFormatter();
        }
        set {
            this._logLineFormatter = value;
        }
    }

    /// <summary>
    /// Override this to set the default formatter if none was supplied
    /// </summary>
    /// <returns></returns>
    protected Func<LogData, string> DefaultFormatter() {
            return (logData => $"{logData.RemoteAddr} - {logData.User} {logData.RequestTimestamp} \"{logData.RequestMethod} {logData.RequestPath} {logData.RequestProtocol}\" {logData.ResponseStatus} \"{logData.UserAgent}\" {logData.DurationMs}ms");
    }

    /// <summary>
    /// Used to set a custom formatter for this instance
    /// </summary>
    /// <param name="formatter"></param>
    public void SetLogLineFormat(Func<LogData, string> formatter) {
        this._logLineFormatter = formatter;
    }

    public async Task Invoke(HttpContext context)
    {

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

        var nowString = now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo);
        var user = context.User.Identity.Name ?? "-";
        var request = context.Request.Path +  (string.IsNullOrEmpty(context.Request.QueryString.ToString()) ? "" : context.Request.QueryString.ToString());
        var responseStatus = context.Response.StatusCode;
        var userAgent = context.Request.Headers.ContainsKey("User-Agent") ? context.Request.Headers["User-Agent"].ToString() : "-";
        var protocol = context.Request.Protocol;
        var duration = watch.ElapsedMilliseconds;
        var remoteAddr = context.Connection.RemoteIpAddress;    
        var method = context.Request.Method;

        var logData = new LogData {
            RemoteAddr = remoteAddr,
            RequestMethod = method,
            RequestPath = request,
            RequestProtocol = protocol,
            RequestTimestamp = nowString,
            ResponseStatus = responseStatus,
            User = user,
            UserAgent = userAgent,
            DurationMs = duration,
        };

        _logger.LogInformation(this.logLineFormatter(logData));

    }
}

只需在Startup.csConfigure方法中进行连接即可:

app.UseMiddleware(typeof(RequestLogMiddleware));

确保它是您添加的第一个中间件。

输出示例:

info: RequestLog[0]
      ::1 - - 2018-08-10T14:23:04.183+02:00 "GET /api/ping HTTP/1.1" 200 "-" 266ms
info: RequestLog[0]
      ::1 - - 2018-08-10T14:23:04.569+02:00 "POST /api/search HTTP/1.1" 401 "-" 31ms
info: RequestLog[0]
      ::1 - - 2018-08-10T14:23:04.375+02:00 "POST /api/search HTTP/1.1" 200 "-" 3453ms
info: RequestLog[0]
      ::1 - - 2018-08-10T14:23:04.375+02:00 "POST /api/search HTTP/1.1" 200 "-" 4341ms
info: RequestLog[0]
      ::1 - - 2018-08-10T14:23:08.932+02:00 "POST /api/search HTTP/1.1" 400 "-" 16ms

记录器可以在配置中打开/关闭:

"Logging": {
    "LogLevel": {
      "Default": "Warning",
      "RequestLog": "Information"
    }
},

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM