在ASP.Net Core 3.1 API中记录响应正文

问题描述

最近,我开始为我工作的公司开发API。 经过一些研究,我们最终将NLog用作日志记录库,并且它具有Layout Renderer来记录发布的请求正文,所以很好。但是,还需要记录响应,处理请求和返回请求所花费的时间(因为第三方供应商也会消耗响应,并且通常它们中的一些供应商会这样做:-我单击了东西-嗯,不,你没有。

现在,这些天我已经阅读了很多有关中间件日志记录的内容,但是有些文章过时了,有些解决方案部分起作用(查看开发人员页面时有问题),我在github上的某个地方读到,记录日志是一种不好的做法响应,因为它可能包含敏感数据。也许我缺少遥测之类的东西?

感谢您的时间和帮助,并为您的咆哮感到抱歉,无休止的阅读测试后,我仍然非常生气。

我已经尝试过什么以及当前问题是什么。 context.Response.Body的问题在于它是不可读但可写的流。为了读取它,必须将其分配给另一个流,然后将一个新的可读流分配给.Body,然后允许其继续到控制器,读取返回的流并将其复制回.Body。

示例中间件类。 (来源:jarz.net | logging-middleware

    public class LoggingMiddleware
        {
            private readonly RequestDelegate _next;
            private readonly ILogger<LoggingMiddleware> _logger;
    
            public LoggingMiddleware(RequestDelegate next,ILogger<LoggingMiddleware> logger)
            {
                _logger = logger;
                _next = next;
            }
    
            public async Task Invoke(HttpContext context)
            {
                if (_logger.IsEnabled(LogLevel.Trace))
                {
                    string responseBodyString = string.Empty;
    
                    try
                    {
                        // Swap the original Response.Body stream with one we can read / seek
                        Stream originalResponseBody = context.Response.Body;
                        using MemoryStream replacementResponseBody = new MemoryStream();
                        context.Response.Body = replacementResponseBody;
    
                        await _next(context); // Continue processing (additional middleware,controller,etc.)
    
                        // Outbound (after the controller)
                        replacementResponseBody.Position = 0;
    
                        // copy the response body to the original stream
                        await replacementResponseBody.copyToAsync(originalResponseBody).ConfigureAwait(false);
                        context.Response.Body = originalResponseBody;
    
                        if (replacementResponseBody.CanRead)
                        {
                            replacementResponseBody.Position = 0;
                            responseBodyString = new StreamReader(replacementResponseBody,leaveOpen: true).ReadToEndAsync().ConfigureAwait(false).GetAwaiter().GetResult();
                            replacementResponseBody.Position = 0;
                        }
                    }
                    finally
                    {
                        if (responseBodyString.Length > 0)
                        {
                            _logger.LogTrace($"{responseBodyString}");
                        }
                    }
                }
                else
                    await _next(context);
            }
        }

解决方法

这是将日志记录中间件添加到ASP.NET Core服务的最小端到端示例,而不会干扰开发人员异常页面的生成。

https://github.com/Treit/LoggingMiddlewareExample