C# 请求和响应日志的自然链接.NET核心应用程序
我正在尝试按GUID链接请求和响应日志。我要么为每个请求和响应获得相同的GUID,要么为每个请求和响应获得完全不同的GUID。我需要的是链接的请求和响应具有相同的GUID,但与所有其他请求和响应不同。在我目前的结构中,有可能做到这一点吗C# 请求和响应日志的自然链接.NET核心应用程序,c#,.net-core,C#,.net Core,我正在尝试按GUID链接请求和响应日志。我要么为每个请求和响应获得相同的GUID,要么为每个请求和响应获得完全不同的GUID。我需要的是链接的请求和响应具有相同的GUID,但与所有其他请求和响应不同。在我目前的结构中,有可能做到这一点吗 public class RequestResponseLoggingMiddleware { private readonly RequestDelegate _next; private readon
public class RequestResponseLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private readonly RecyclableMemoryStreamManager _recyclableMemoryStreamManager;
public RequestResponseLoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<RequestResponseLoggingMiddleware>();
_recyclableMemoryStreamManager = new RecyclableMemoryStreamManager();
}
public async Task Invoke(HttpContext context)
{
await LogRequest(context);
await LogResponse(context);
}
private async Task LogRequest(HttpContext context)
{
context.Request.EnableBuffering();
await using var requestStream = _recyclableMemoryStreamManager.GetStream();
await context.Request.Body.CopyToAsync(requestStream);
var Request = new Dictionary<string, string>(){
{"Http Request Information", $"{DateTime.UtcNow}"},
{"ID", Guid.NewGuid().ToString()},
{"IP", $"{context.Request.HttpContext.Connection.RemoteIpAddress}" },
{"Schema", context.Request.Scheme},
{"Path", context.Request.Path},
{"QueryString", $"{context.Request.QueryString}"},
{"Request Body", ReadStreamInChunks(requestStream)}
};
var requestJson = JsonConvert.SerializeObject(Request, Formatting.None);
_logger.LogInformation(requestJson);
context.Request.Body.Position = 0;
}
private async Task LogResponse(HttpContext context)
{
var originalBodyStream = context.Response.Body;
await using var responseBody = _recyclableMemoryStreamManager.GetStream();
context.Response.Body = responseBody;
await _next(context);
context.Response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(context.Response.Body).ReadToEndAsync();
context.Response.Body.Seek(0, SeekOrigin.Begin);
var Response = new Dictionary<string, string>(){
{"Http Response Information", $"{DateTime.UtcNow}"},
{"ID", Guid.NewGuid().ToString()},
{"IP", $"{context.Request.HttpContext.Connection.RemoteIpAddress}" },
{"Schema", context.Request.Scheme},
{"Path", context.Request.Path },
{"QueryString", $"{context.Request.QueryString}"},
{"Response Body", text}
};
var responseJson = JsonConvert.SerializeObject(Response, Formatting.None);
_logger.LogInformation(responseJson);
await responseBody.CopyToAsync(originalBodyStream);
}
private static string ReadStreamInChunks(Stream stream)
{
const int readChunkBufferLength = 4096;
stream.Seek(0, SeekOrigin.Begin);
using var textWriter = new StringWriter();
using var reader = new StreamReader(stream);
var readChunk = new char[readChunkBufferLength];
int readChunkLength;
do
{
readChunkLength = reader.ReadBlock(readChunk, 0, readChunkBufferLength);
textWriter.Write(readChunk, 0, readChunkLength);
} while (readChunkLength > 0);
return textWriter.ToString();
}
公共类RequestResponseLoggingMiddleware
{
private readonly RequestDelegate\u next;
专用只读ILogger\u记录器;
私有只读可回收内存流管理器\u可回收内存流管理器;
公共RequestResponseLoggingMiddleware(RequestDelegate下一步,iLogger工厂loggerFactory)
{
_下一个=下一个;
_logger=loggerFactory.CreateLogger();
_recyclableMemoryStreamManager=新的recyclableMemoryStreamManager();
}
公共异步任务调用(HttpContext上下文)
{
等待日志请求(上下文);
等待日志响应(上下文);
}
专用异步任务日志请求(HttpContext上下文)
{
context.Request.enableBuffer();
使用var requestStream=_recyclableMemoryStreamManager.GetStream()等待;
wait context.Request.Body.CopyToAsync(requestStream);
var请求=新字典(){
{“Http请求信息”,$“{DateTime.UtcNow}”,
{“ID”,Guid.NewGuid().ToString()},
{“IP”,$“{context.Request.HttpContext.Connection.RemoteIpAddress}”,
{“Schema”,context.Request.Scheme},
{“Path”,context.Request.Path},
{“QueryString”,$“{context.Request.QueryString}”,
{“请求正文”,ReadStreamInChunks(requestStream)}
};
var requestJson=JsonConvert.SerializeObject(请求,格式化.None);
_logger.LogInformation(requestJson);
context.Request.Body.Position=0;
}
专用异步任务日志响应(HttpContext上下文)
{
var originalBodyStream=context.Response.Body;
使用var responseBody=_recyclableMemoryStreamManager.GetStream()等待;
context.Response.Body=responseBody;
等待下一步(上下文);
context.Response.Body.Seek(0,SeekOrigin.Begin);
var text=wait new StreamReader(context.Response.Body).ReadToEndAsync();
context.Response.Body.Seek(0,SeekOrigin.Begin);
var Response=newdictionary(){
{“Http响应信息”,$“{DateTime.UtcNow}”,
{“ID”,Guid.NewGuid().ToString()},
{“IP”,$“{context.Request.HttpContext.Connection.RemoteIpAddress}”,
{“Schema”,context.Request.Scheme},
{“Path”,context.Request.Path},
{“QueryString”,$“{context.Request.QueryString}”,
{“答复正文”,正文}
};
var responseJson=JsonConvert.SerializeObject(Response,Formatting.None);
_日志信息(responseJson);
wait responseBody.CopyToAsync(originalBodyStream);
}
私有静态字符串ReadStreamInChunks(流)
{
const int readChunkBufferLength=4096;
stream.Seek(0,SeekOrigin.Begin);
使用var textWriter=new StringWriter();
使用var reader=newstreamreader(流);
var readChunk=新字符[readChunkBufferLength];
int-readChunkLength;
做
{
readChunkLength=reader.ReadBlock(readChunk,0,readChunkBufferLength);
Write(readChunk,0,readChunkLength);
}而(readChunkLength>0);
返回textWriter.ToString();
}
我将扩展请求和响应json对象,并在其中添加一些ID字段,并使用相同的Guid填充:
public class RequestResponseLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private readonly RecyclableMemoryStreamManager _recyclableMemoryStreamManager;
public RequestResponseLoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<RequestResponseLoggingMiddleware>();
_recyclableMemoryStreamManager = new RecyclableMemoryStreamManager();
}
public async Task Invoke(HttpContext context)
{
var guid = Guid.NewGuid();
await LogRequest(context, guid);
await LogResponse(context, guid);
}
private async Task LogRequest(HttpContext context, Guid guid)
{
context.Request.EnableBuffering();
await using var requestStream = _recyclableMemoryStreamManager.GetStream();
await context.Request.Body.CopyToAsync(requestStream);
var Request = new Dictionary<string, string>(){
{"Request ID", guid.ToString()}
{"Http Request Information", $"{DateTime.UtcNow}"},
{"ID", Guid.NewGuid().ToString()},
{"IP", $"{context.Request.HttpContext.Connection.RemoteIpAddress}" },
{"Schema", context.Request.Scheme},
{"Path", context.Request.Path},
{"QueryString", $"{context.Request.QueryString}"},
{"Request Body", ReadStreamInChunks(requestStream)}
};
var requestJson = JsonConvert.SerializeObject(Request, Formatting.None);
_logger.LogInformation(requestJson);
context.Request.Body.Position = 0;
}
private async Task LogResponse(HttpContext context, Guid guid)
{
var originalBodyStream = context.Response.Body;
await using var responseBody = _recyclableMemoryStreamManager.GetStream();
context.Response.Body = responseBody;
await _next(context);
context.Response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(context.Response.Body).ReadToEndAsync();
context.Response.Body.Seek(0, SeekOrigin.Begin);
var Response = new Dictionary<string, string>(){
{"Request ID", guid.ToString()}
{"Http Response Information", $"{DateTime.UtcNow}"},
{"ID", Guid.NewGuid().ToString()},
{"IP", $"{context.Request.HttpContext.Connection.RemoteIpAddress}" },
{"Schema", context.Request.Scheme},
{"Path", context.Request.Path },
{"QueryString", $"{context.Request.QueryString}"},
{"Response Body", text}
};
var responseJson = JsonConvert.SerializeObject(Response, Formatting.None);
_logger.LogInformation(responseJson);
await responseBody.CopyToAsync(originalBodyStream);
}
private static string ReadStreamInChunks(Stream stream)
{
const int readChunkBufferLength = 4096;
stream.Seek(0, SeekOrigin.Begin);
using var textWriter = new StringWriter();
using var reader = new StreamReader(stream);
var readChunk = new char[readChunkBufferLength];
int readChunkLength;
do
{
readChunkLength = reader.ReadBlock(readChunk, 0, readChunkBufferLength);
textWriter.Write(readChunk, 0, readChunkLength);
} while (readChunkLength > 0);
return textWriter.ToString();
}
公共类RequestResponseLoggingMiddleware
{
private readonly RequestDelegate\u next;
专用只读ILogger\u记录器;
私有只读可回收内存流管理器\u可回收内存流管理器;
公共RequestResponseLoggingMiddleware(RequestDelegate下一步,iLogger工厂loggerFactory)
{
_下一个=下一个;
_logger=loggerFactory.CreateLogger();
_recyclableMemoryStreamManager=新的recyclableMemoryStreamManager();
}
公共异步任务调用(HttpContext上下文)
{
var guid=guid.NewGuid();
等待日志请求(上下文、guid);
等待日志响应(上下文、guid);
}
专用异步任务日志请求(HttpContext上下文,Guid)
{
context.Request.enableBuffer();
使用var requestStream=_recyclableMemoryStreamManager.GetStream()等待;
wait context.Request.Body.CopyToAsync(requestStream);
var请求=新字典(){
{“请求ID”,guid.ToString()}
{“Http请求信息”,$“{DateTime.UtcNow}”,
{“ID”,Guid.NewGuid().ToString()},
{“IP”,$“{context.Request.HttpContext.Connection.RemoteIpAddress}”,
{“Schema”,context.Request.Scheme},
{“Path”,context.Request.Path},
{“QueryString”,$“{context.Request.QueryString}”,
{“请求正文”,ReadStreamInChunks(requestStream)}
};
var requestJson=JsonConvert.SerializeObject(请求,格式化.None);
_logger.LogInformation(requestJson);
context.Request.Body.Position=0;
}
专用异步任务日志响应(HttpContext上下文,Guid)
{
var originalBodyStream=context.Response.Body;
等待使用var responseBody=\u recyclableMemorySt
class GuidProvider {
public string CorrelationId {get; private set;}
public GuidProvider() {
CorrelationId = Guid.NewGuid().ToString()
}
}
services.AddScoped(typeof(GuidProvider));
public RequestResponseLoggingMiddleware(..., GuidProvider guidProvider)
{
guidProvider.CorrelationId; // should stay the same within request
...
}```