在 Application Insights 中记录失败请求的请求正文的最佳做法是什么?
What is the best practice to log request body on failed requests in Application Insights?
请求失败时记录 HTTP 请求正文的最佳方式是什么?
我正在通过覆盖异常记录器来记录未处理的异常:
public class AiExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
if (context != null && context.Exception != null)
{
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
// the requestBody is always empty because the stream is non-rewinadable?
string requestBody = context.Request.Content.ReadAsStringAsync().Result;
telemetry.Properties.Add("Request Body", requestBody);
Logger.LogException(telemetry);
}
base.Log(context);
}
}
通过上面的代码,请求内容始终为空。我也尝试了 this,但由于调用 GetBufferlessInputStream 而引发了不受支持的方法异常。所以这也不管用。
我可以使用 DelegatingHandler 记录所有请求内容,但我只想记录由未处理的异常导致的失败请求的请求正文。
有什么想法吗?
你是对的。您不能像使用 Streams 那样重置位置 属性。相反,复制内容并阅读副本。
if (context != null && context.Exception != null)
{
HttpContent requestContent = new HttpContent();
request.Content.CopyToAsync(requestContent);
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
// the requestBody is always empty because the stream is non-rewinadable?
string requestBody = requestContent.ReadAsStringAsync().Result;
telemetry.Properties.Add("Request Body", requestBody);
Logger.LogException(context.Exception);
}
With the above code, the request content is always empty.
您可以使用 ReadAsStreamAsync 方法获取请求流并重置此流的位置。之后,您可以使用 StreamReader 从这个 steam 中读取内容。以下代码供您参考。我对其进行了测试,它在我这边运行良好。
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
//Get request stream and reset the position of this stream
Stream requestBodyStream = context.Request.Content.ReadAsStreamAsync().Result;
requestBodyStream.Position = 0;
string requestBody = string.Empty;
using (StreamReader sr = new StreamReader(requestBodyStream))
{
requestBody = sr.ReadToEnd();
}
telemetry.Properties.Add("Request Body", requestBody);
这是 Amor 的替代方案 - MSFT 使用 CopyTo
的答案
public class AiExceptionLogger : ExceptionLogger
{
public override async void Log(ExceptionLoggerContext context)
{
if (context != null && context.Exception != null)
{
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
using (var ms = new MemoryStream())
{
await context.Request.Content.CopyToAsync(ms);
var requestBody = Encoding.UTF8.GetString(ms.ToArray());
telemetry.Properties.Add("Request Body", requestBody);
}
Logger.LogException(telemetry);
}
base.Log(context);
}
}
请求失败时记录 HTTP 请求正文的最佳方式是什么?
我正在通过覆盖异常记录器来记录未处理的异常:
public class AiExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
if (context != null && context.Exception != null)
{
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
// the requestBody is always empty because the stream is non-rewinadable?
string requestBody = context.Request.Content.ReadAsStringAsync().Result;
telemetry.Properties.Add("Request Body", requestBody);
Logger.LogException(telemetry);
}
base.Log(context);
}
}
通过上面的代码,请求内容始终为空。我也尝试了 this,但由于调用 GetBufferlessInputStream 而引发了不受支持的方法异常。所以这也不管用。
我可以使用 DelegatingHandler 记录所有请求内容,但我只想记录由未处理的异常导致的失败请求的请求正文。
有什么想法吗?
你是对的。您不能像使用 Streams 那样重置位置 属性。相反,复制内容并阅读副本。
if (context != null && context.Exception != null)
{
HttpContent requestContent = new HttpContent();
request.Content.CopyToAsync(requestContent);
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
// the requestBody is always empty because the stream is non-rewinadable?
string requestBody = requestContent.ReadAsStringAsync().Result;
telemetry.Properties.Add("Request Body", requestBody);
Logger.LogException(context.Exception);
}
With the above code, the request content is always empty.
您可以使用 ReadAsStreamAsync 方法获取请求流并重置此流的位置。之后,您可以使用 StreamReader 从这个 steam 中读取内容。以下代码供您参考。我对其进行了测试,它在我这边运行良好。
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
//Get request stream and reset the position of this stream
Stream requestBodyStream = context.Request.Content.ReadAsStreamAsync().Result;
requestBodyStream.Position = 0;
string requestBody = string.Empty;
using (StreamReader sr = new StreamReader(requestBodyStream))
{
requestBody = sr.ReadToEnd();
}
telemetry.Properties.Add("Request Body", requestBody);
这是 Amor 的替代方案 - MSFT 使用 CopyTo
public class AiExceptionLogger : ExceptionLogger
{
public override async void Log(ExceptionLoggerContext context)
{
if (context != null && context.Exception != null)
{
ExceptionTelemetry telemetry = new ExceptionTelemetry(context.Exception);
using (var ms = new MemoryStream())
{
await context.Request.Content.CopyToAsync(ms);
var requestBody = Encoding.UTF8.GetString(ms.ToArray());
telemetry.Properties.Add("Request Body", requestBody);
}
Logger.LogException(telemetry);
}
base.Log(context);
}
}