[英]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.