.NET 6 日志记录中间件
.NET 6 Logging middleware
我们正在尝试创建一个中间件,允许您登录到 HTTP 响应正文的外部服务。
我们尝试用 MemoryStream 替换它,但是当我们尝试读取它时,它却被关闭了。
有人可以帮助我们吗?
提前致谢
代码如下:
public class LogMiddleware
{
private readonly RequestDelegate _next;
public LogMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var originBody = context.Response.Body;
try
{
var memStream = new MemoryStream();
context.Response.Body = memStream;
await _next(context).ConfigureAwait(false);
memStream.Position = 0;
var responseBody = new StreamReader(memStream).ReadToEnd();
var memoryStreamModified = new MemoryStream();
var sw = new StreamWriter(memoryStreamModified);
sw.Write(responseBody);
sw.Flush();
memoryStreamModified.Position = 0;
await memoryStreamModified.CopyToAsync(originBody).ConfigureAwait(false);
}
finally
{
context.Response.Body = originBody;
}
}
}
在以下 Whosebug 问题中对此有很多很好的讨论:
因为这个当前问题调用 out.NET 6,所以我会特别关注这个答案,它切断了很多以前的解决方法:
综上所述,由于该问题中概述的各种原因(缓冲区、转换、泄漏、数据大小),管理请求和响应流是一个 non-trivial 挑战。根据您需要对日志记录参数施加的控制级别,您可能会发现仅使用 built-in HttpLoggingMiddleware.
是有益的
可以注册:
builder.Services.AddHttpLogging(opts =>
{
opts .LoggingFields = HttpLoggingFields.ResponseBody;
});
然后使用 app.UseHttpLogging()
添加到管道中,此时您可以连接到 ASP NET Core ILogger
以获取响应正文作为日志记录实现的一部分:
https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingExtensions.cs,27
感谢开源,如果您需要构建更强大或更深入的钩子,您可以在此处深入了解 Microsoft 如何实现该中间件:https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingMiddleware.cs,35c5841599b94285
关键要素是 IHttpResponseBodyFeature
实现的使用,它是 not heavily documented 但它是连接到 request/response 管道那部分的抽象点,因为 3.x. Rick Strahl 在他的博客中有一个 post,其中显示了那里所需的一些实施深度:
我们正在尝试创建一个中间件,允许您登录到 HTTP 响应正文的外部服务。
我们尝试用 MemoryStream 替换它,但是当我们尝试读取它时,它却被关闭了。
有人可以帮助我们吗?
提前致谢
代码如下:
public class LogMiddleware
{
private readonly RequestDelegate _next;
public LogMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var originBody = context.Response.Body;
try
{
var memStream = new MemoryStream();
context.Response.Body = memStream;
await _next(context).ConfigureAwait(false);
memStream.Position = 0;
var responseBody = new StreamReader(memStream).ReadToEnd();
var memoryStreamModified = new MemoryStream();
var sw = new StreamWriter(memoryStreamModified);
sw.Write(responseBody);
sw.Flush();
memoryStreamModified.Position = 0;
await memoryStreamModified.CopyToAsync(originBody).ConfigureAwait(false);
}
finally
{
context.Response.Body = originBody;
}
}
}
在以下 Whosebug 问题中对此有很多很好的讨论:
因为这个当前问题调用 out.NET 6,所以我会特别关注这个答案,它切断了很多以前的解决方法:
综上所述,由于该问题中概述的各种原因(缓冲区、转换、泄漏、数据大小),管理请求和响应流是一个 non-trivial 挑战。根据您需要对日志记录参数施加的控制级别,您可能会发现仅使用 built-in HttpLoggingMiddleware.
是有益的可以注册:
builder.Services.AddHttpLogging(opts =>
{
opts .LoggingFields = HttpLoggingFields.ResponseBody;
});
然后使用 app.UseHttpLogging()
添加到管道中,此时您可以连接到 ASP NET Core ILogger
以获取响应正文作为日志记录实现的一部分:
https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingExtensions.cs,27
感谢开源,如果您需要构建更强大或更深入的钩子,您可以在此处深入了解 Microsoft 如何实现该中间件:https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingMiddleware.cs,35c5841599b94285
关键要素是 IHttpResponseBodyFeature
实现的使用,它是 not heavily documented 但它是连接到 request/response 管道那部分的抽象点,因为 3.x. Rick Strahl 在他的博客中有一个 post,其中显示了那里所需的一些实施深度: