如何在serilog的输出.net核心中添加“请求正文"? [英] How to add 'request body' in serilog's output .net core?

查看:97
本文介绍了如何在serilog的输出.net核心中添加“请求正文"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于.net core 3.1的Web API.

I have a web API based on .net core 3.1.

我正在使用SeriLog库作为记录器.

I'm using the SeriLog library as a logger.

这是我的SeriLog配置.Serilog已从"appsettings.json"配置.

Here is my SeriLog Configuration. Serilog has been configured from 'appsettings.json'.

我需要在日志输出中添加请求正文"参数(如果存在).有什么方法可以配置它.另外,我分享我的日志输出.

I need to add 'request body' parameters to log's output if it exists. Is there any way to configure this. Also, I share my log output.

推荐答案

我编写了一个自定义中间件来捕获HTTP请求和响应.它与ASP.NET Core 3.X兼容,并且也应与2.X和.NET 5.0兼容,尽管我尚未在那些框架版本中对其进行过测试.

I wrote a custom middleware to capture both HTTP requests and responses. It is compatible with ASP.NET Core 3.X and should also work with 2.X and .NET 5.0, although I haven't tested it with those framework versions.

这是我的git仓库的链接: https://github.com/matthew-daddario/AspNetCoreRequestResponseLogger

Here's the link to my git repo: https://github.com/matthew-daddario/AspNetCoreRequestResponseLogger

相关代码是这样:

    public class RequestResponseLoggerMiddleware
{
    private readonly RequestDelegate _next;
    private readonly bool _isRequestResponseLoggingEnabled;

    public RequestResponseLoggerMiddleware(RequestDelegate next, IConfiguration config)
    {
        _next = next;
        _isRequestResponseLoggingEnabled = config.GetValue<bool>("EnableRequestResponseLogging", false);
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        // Middleware is enabled only when the EnableRequestResponseLogging config value is set.
        if (_isRequestResponseLoggingEnabled)
        {
            Console.WriteLine($"HTTP request information:\n" +
                $"\tMethod: {httpContext.Request.Method}\n" +
                $"\tPath: {httpContext.Request.Path}\n" +
                $"\tQueryString: {httpContext.Request.QueryString}\n" +
                $"\tHeaders: {FormatHeaders(httpContext.Request.Headers)}\n" +
                $"\tSchema: {httpContext.Request.Scheme}\n" +
                $"\tHost: {httpContext.Request.Host}\n" +
                $"\tBody: {await ReadBodyFromRequest(httpContext.Request)}");

            // Temporarily replace the HttpResponseStream, which is a write-only stream, with a MemoryStream to capture it's value in-flight.
            var originalResponseBody = httpContext.Response.Body;
            using var newResponseBody = new MemoryStream();
            httpContext.Response.Body = newResponseBody;

            // Call the next middleware in the pipeline
            await _next(httpContext);

            newResponseBody.Seek(0, SeekOrigin.Begin);
            var responseBodyText = await new StreamReader(httpContext.Response.Body).ReadToEndAsync();

            Console.WriteLine($"HTTP request information:\n" +
                $"\tStatusCode: {httpContext.Response.StatusCode}\n" +
                $"\tContentType: {httpContext.Response.ContentType}\n" +
                $"\tHeaders: {FormatHeaders(httpContext.Response.Headers)}\n" +
                $"\tBody: {responseBodyText}");

            newResponseBody.Seek(0, SeekOrigin.Begin);
            await newResponseBody.CopyToAsync(originalResponseBody);
        }
        else
        {
            await _next(httpContext);
        }
    }

    private static string FormatHeaders(IHeaderDictionary headers) => string.Join(", ", headers.Select(kvp => $"{{{kvp.Key}: {string.Join(", ", kvp.Value)}}}"));

    private static async Task<string> ReadBodyFromRequest(HttpRequest request)
    {
        // Ensure the request's body can be read multiple times (for the next middlewares in the pipeline).
        request.EnableBuffering();

        using var streamReader = new StreamReader(request.Body, leaveOpen: true);
        var requestBody = await streamReader.ReadToEndAsync();

        // Reset the request's body stream position for next middleware in the pipeline.
        request.Body.Position = 0;
        return requestBody;
    }
}

这篇关于如何在serilog的输出.net核心中添加“请求正文"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆