次のようなメッセージ ハンドラーで、すべての要求/応答パケットのログ記録を実装しました。
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var correlationId = Guid.NewGuid();
RequestApiLogger.LogHttpRequest(request, correlationId);
return await base.SendAsync(request, cancellationToken).ContinueWith(
task =>
{
var response = task.Result;
response.Headers.Add("http-tracking-id", correlationId.ToString("D"));
ResponseApiLogger.LogHttpResponse(response, correlationId);
return response;
}, cancellationToken);
}
毎日 (数千のうち) 約 10 ~ 20 の API 応答がログに記録されていないようです。これらの API を呼び出しているモバイル デバイスがあり、リクエストを行った可能性があると考え、その後ネットワーク接続を失います。この場合、レスポンスは送信されず、ログにも記録されません。
ただし、postman でテストすると、ログ実行リクエストを実行し、途中でキャンセル ボタンを押すと、実際に応答が最終的にログに書き込まれることがわかります。次のリクエストがあったときに書かれているようです。
Web API 2.0 が要求を受け取った場合、常に応答を発行しますか? クライアントが中止されたかどうかは重要ですか? クライアントがネットワークへの接続を失った場合は問題になりますか?
エラーをトラップするために、log4net とグローバルな例外ロガーを使用しています。ただし、応答を「失った」前後のすべてのログを見ると、ログに記録された例外はありません。グローバルロガーは次のとおりです。
internal class GlobalExceptionLogger : ExceptionLogger
{
private static readonly ILog Log4Net = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public override void Log(ExceptionLoggerContext context)
{
Log4Net.Error(
string.Format("Unhandled exception thrown in {0} for request {1}", context.Request.Method,
context.Request.RequestUri), context.Exception);
}
}
起動時にハンドラーとロガーを登録する方法を次に示します。
GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new GlobalExceptionLogger());
GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandler());
私もこれをテストするのに苦労しています。どんな提案も大歓迎です。