简体   繁体   English

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

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

Recently I started developing an API for the company I work for.最近我开始为我工作的公司开发一个 API。 After some research we resulted to using NLog as a logging library and it has a Layout Renderer for logging the posted request body, so that's good.经过一些研究,我们决定使用 NLog 作为日志库,它有一个用于记录发布的请求主体的布局渲染器,所以这很好。 But, there is also a need for logging the response, the time it took for the request to process and return (since it will be also consumed by 3rd party vendors and usually the way it goes with some of them is: -I clicked the thing. -hmm no you didn't).但是,还需要记录响应,请求处理和返回所花费的时间(因为它也会被 3rd 方供应商消耗,通常它与其中一些供应商的方式是:-我点击了东西。-嗯,不,你没有)。

Now, I have read so much these days about Middleware logging and but some posts are dated, some solutions work partially (having an issue with viewing the developer page), somewhere in github I've read that it's bad practice to log the response since it can contain sensitive data.现在,这些天我已经阅读了很多关于中间件日志记录的文章,但是有些帖子已经过时,有些解决方案部分起作用(在查看开发人员页面时遇到问题),在 github 的某个地方我读到记录响应是不好的做法,因为它可以包含敏感数据。 Maybe there is something like telemetry I'm missing?也许我缺少遥测之类的东西?

Thanks for your time and help and sorry for the rant, I'm still pretty burned after the endless reading-testing.感谢您的宝贵时间和帮助,对于我的咆哮,我深表歉意,在无休止的阅读测试之后,我仍然很焦躁。

What I have already tried and what the current issue is.我已经尝试过什么以及当前的问题是什么。 The issue with the context.Response.Body is that it is a non-readable, but writeable stream. In order to read it, it must be assigned to another stream, then assign a new readable stream to the.Body, then allow it to continue to the controller, read the returned stream and copy it back to the.Body. context.Response.Body 的问题在于它是一个不可读,但可写的 stream。为了读取它,必须将它分配给另一个 stream,然后将一个新的可读 stream 分配给.Body,然后允许它继续 controller,读取返回的 stream 并将其复制回.Body。

The example middleware class. (Credits to: jarz.net | logging-middleware )示例中间件 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);
            }
        }

Here is a minimal, end-to-end example of adding logging middleware to an ASP.NET Core service, without disrupting things like the generation of the developer exception page.这是一个最小的、端到端的示例,它向 ASP.NET 核心服务添加日志记录中间件,而不会中断诸如生成开发人员异常页面之类的事情。

https://github.com/Treit/LoggingMiddlewareExample https://github.com/Treit/LoggingMiddlewareExample

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

相关问题 在 ASP.Net Core 中压缩之前记录响应正文 - Logging response body BEFORE compression in ASP.Net Core 带有自定义响应包装器的 ASP.NET Core 3.1 Web API 中的 JSON 响应中断 - JSON response breaks in ASP.NET Core 3.1 Web API with custom response wrapper ASP.NET Core 3.1 Web API JSON 响应骆驼化超过第一个字符 - ASP.NET Core 3.1 web API JSON response camelizes more than first character ASP.NET Core API Controller:Response.Body.WriteAsync base64字符串无法正常工作 - ASP.NET Core API Controller: Response.Body.WriteAsync base64 string not working Why Fetch Post request with JSON parameter in the body to ASP.NET Core 3.1 WEB API or MVC Controller does not get anything? - Why Fetch Post request with JSON parameter in the body to ASP.NET Core 3.1 WEB API or MVC Controller does not get anything? 如何使 ASP.NET Core (v3.1) Web API 接受来自主体的子类参数 - How to make ASP.NET Core (v3.1) Web API accepts child class parameter from body ASP.NET 核心 api 项目 3.1 发布在 IIS - ASP.NET Core api project 3.1 publish on IIS ASP.NET Core 3.1:Web API 身份登录 - ASP.NET Core 3.1: Web API identity sign in Asp.net 核心 3.1 保护 API 和 web 应用程序 - Asp.net core 3.1 securing API and web app ASP.NET 内核中的全局异常处理程序 Web API 3.1 - Global Exception Handler in ASP.NET Core Web API 3.1
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM