.NET Core中获取外部API请求体并记录至Application Insights的方法
最优实现方案:记录自身API及外部API的请求体到Application Insights
一、核心思路
要同时记录自身API的入站请求和调用外部API的出站请求,需分两部分处理:
- 入站请求:沿用现有代码逻辑,通过
HttpContext读取请求体 - 出站请求:拦截HTTP客户端的请求流程,在发送前捕获请求体和URL信息
二、具体实现步骤
1. 自定义HTTP客户端消息处理器(拦截外部API请求)
创建继承自DelegatingHandler的处理器,在发送请求前捕获外部API的URL和请求体,再记录到Application Insights:
public class LoggingHandler : DelegatingHandler { private readonly ILogger<LoggingHandler> _logger; private readonly RecyclableMemoryStreamManager _streamManager; public LoggingHandler(ILogger<LoggingHandler> logger, RecyclableMemoryStreamManager streamManager) { _logger = logger; _streamManager = streamManager; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { string requestBody = string.Empty; if (request.Content != null) { // 复制请求流以便读取,同时保留原始流供后续发送使用 var originalStream = await request.Content.ReadAsStreamAsync(cancellationToken); originalStream.Position = 0; using (var memoryStream = _streamManager.GetStream()) { await originalStream.CopyToAsync(memoryStream, cancellationToken); memoryStream.Position = 0; requestBody = new StreamReader(memoryStream).ReadToEnd(); // 重置原始流位置,确保请求能正常发送 originalStream.Position = 0; request.Content = new StreamContent(originalStream); } } // 记录外部API请求信息到Application Insights _logger.LogInformation("External API Request - URL: {Url}, Body: {RequestBody}", request.RequestUri, requestBody); return await base.SendAsync(request, cancellationToken); } }
2. 注册自定义处理器到HTTP客户端
在Program.cs(或Startup.cs)中注册处理器,确保所有调用外部API的HTTP客户端都使用该拦截逻辑:
builder.Services.AddSingleton<RecyclableMemoryStreamManager>(); builder.Services.AddTransient<LoggingHandler>(); // 注册带日志处理器的HTTP客户端 builder.Services.AddHttpClient("ExternalApiClient") .AddHttpMessageHandler<LoggingHandler>();
3. 优化现有入站请求日志逻辑
调整现有代码,确保读取请求体后不影响后续中间件处理,同时完善日志内容:
private async Task LogRequest(HttpContext context, string correlationID) { context.Request.EnableBuffering(); aiLogger.LogPageView(context.Request.Path.Value); string requestBody = string.Empty; using (var requestStream = _recyclableMemoryStreamManager.GetStream()) { await context.Request.Body.CopyToAsync(requestStream); requestStream.Position = 0; requestBody = new StreamReader(requestStream).ReadToEnd(); // 重置请求流位置,确保后续流程能正常读取 context.Request.Body.Position = 0; } // 记录自身API请求信息 aiLogger.LogInformation("Inbound API Request - Path: {Path}, Body: {RequestBody}, CorrelationID: {CorrelationID}", context.Request.Path, requestBody, correlationID); }
4. 关联追踪ID(Correlation ID)
为方便在Application Insights中排查问题,确保入站和出站请求使用同一个CorrelationID:
- 在入站请求日志中生成或获取
CorrelationID,存入HttpContext.Items - 在
LoggingHandler中从HttpContext获取该ID,一并记录到日志
三、关键注意事项
- 流重置:读取入站/出站请求流后,必须重置流的位置,否则后续流程无法读取内容
- 内存管理:使用
RecyclableMemoryStreamManager避免频繁创建内存流带来的性能损耗 - 敏感信息过滤:若请求体包含密码、Token等敏感数据,需先脱敏再记录,防止数据泄露
内容的提问来源于stack exchange,提问作者pavan
相关产品推荐
相关产品推荐

