【发布时间】:2020-08-19 21:56:11
【问题描述】:
最近我开始为我工作的公司开发 API。 经过一些研究,我们最终使用 NLog 作为日志库,它有一个 Layout Renderer 用于记录发布的请求正文,这很好。但是,还需要记录响应,请求处理和返回所花费的时间(因为它也将被 3rd 方供应商消耗,通常与其中一些供应商一起使用的方式是:-我点击事情。-嗯,不,你没有)。
现在,这些天我读了很多关于中间件日志的文章,但是有些帖子已经过时了,有些解决方案部分工作(查看开发人员页面时遇到问题),我在 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);
}
}
【问题讨论】:
-
您面临的问题是什么?
-
我正在寻求有关如何执行此操作的指导和最佳实践。
标签: c# asp.net-core middleware