繁体   English   中英

在 ASP.Net Core 3.1 中记录响应主体 API

[英]Logging response body in ASP.Net Core 3.1 API

最近我开始为我工作的公司开发一个 API。 经过一些研究,我们决定使用 NLog 作为日志库,它有一个用于记录发布的请求主体的布局渲染器,所以这很好。 但是,还需要记录响应,请求处理和返回所花费的时间(因为它也会被 3rd 方供应商消耗,通常它与其中一些供应商的方式是:-我点击了东西。-嗯,不,你没有)。

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

感谢您的宝贵时间和帮助,对于我的咆哮,我深表歉意,在无休止的阅读测试之后,我仍然很焦躁。

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

示例中间件 class。(来源: 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 核心服务添加日志记录中间件,而不会中断诸如生成开发人员异常页面之类的事情。

https://github.com/Treit/LoggingMiddlewareExample

暂无
暂无

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

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