2017-05-03 49 views
4

请求失败时记录HTTP请求主体的最佳方式是什么?在Application Insights中对失败的请求记录请求正文的最佳做法是什么?

我通过重写异常记录仪记录未处理的异常:

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记录所有请求内容,但我只想记录由未处理的异常导致失败请求的请求正文。

任何想法?

回答

2

与上面的代码中,请求内容总是空的。

您可以使用ReadAsStreamAsync方法获取请求流并重置此流的位置。之后,您可以使用StreamReader从此蒸汽中读取内容。以下代码供您参考。我测试了它,它在我身边运行得很好。

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); 
+0

即使我使用了Mitch Stewart的CopyTo方法,我也接受了您的答案。但由于他的代码不完整,需要修改才能工作,所以我无法将其标记为正确答案:) –

+0

@ErtayShashko我不确定为什么这是可接受的答案,因为它不起作用。您无法重置该位置。 – Phill

+0

@Phill,如果您无法在您的环境中重置requestBodyStream的位置,则可以将其复制到MemoryStream并重置MemoryStream的位置。然后我们可以从MemoryStream读取数据。 MemoryStream ms = new MemoryStream(); requestBodyStream.CopyTo(ms); ms.Position = 0; – Amor

0

你说得对。您无法像使用Streams一样重置Position属性。相反,请复制内容并阅读副本。

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); 
} 
+0

HttpContent是一个抽象类,也需要CopyTo从流中的:)你需要编辑你的答案。我会试着看看它是否会起作用。 –

0

下面是奥马尔的选择 - 使用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); 
    } 
}