2017-04-26 2 views
2

注:この質問は、従来のElmah .Netライブラリではなく、elmah.io(https://elmah.io/)、クラウドベースの例外ログサービスに関するものです。elmah.ioをASP.NET Coreとミドルウェアを渡す際にうまく動作させるには?

私はASP.NET Coreを使用しており、ミドルウェアを処理する単純な例外があります。

public class HandleExceptionMiddleware 
{ 
    public HandleExceptionMiddleware(RequestDelegate next) 
    { 
     Next = next; 
    } 

    RequestDelegate Next { get; } 

    public async Task Invoke(HttpContext httpContext) 
    { 
     try 
     { 
      await Next(httpContext); 
     } 
     catch (Exception ex) 
     { 
      await HandleExceptionAsync(httpContext, ex); 
     } 
    } 

    Task HandleExceptionAsync(HttpContext context, Exception ex) 
    { 
     var code = HttpStatusCode.InternalServerError; 

     if (ex is ArgumentException) 
      code = HttpStatusCode.BadRequest; 

     var result = JsonConvert.SerializeObject(new { message = ex.Message }); 
     context.Response.ContentType = "application/json"; 
     context.Response.StatusCode = (int)code; 
     return context.Response.WriteAsync(result); 
    } 
} 

本ミドルウェアは、それが見ている例外に応じて、以下のJSONレスポンスを返します。

ArgumentExceptionがために:

HTTP/1.1 400 Bad Request 

{"message":""} 

他のすべての例外の場合:

HTTP/1.1 500 Internal Server Error 

{"message":""} 

私はelmah.ioが500の応答をログに記録し、を無視するようにしますの応答(これはデフォルトのelmah.io構成です)。しかし、ときに例外ハンドラとelmah.ioがスタートアップの設定フックにこの順に登録されている、何もelmah.ioにログインしていない取得します、しかし、私は次のように登録順序を変更

app.UseElmahIo("API_KEY", new Guid("LOG_ID")); 
    app.UseMiddleware<HandleExceptionMiddleware>() 

場合は、すべてが取得しますログ記録(400回の応答を含む)。 HandleExceptionMiddlewareが応答を変更する機会を得る前にelmah.ioは、例外を処理するので、これは理にかなって:

app.UseMiddleware<HandleExceptionMiddleware>() 
    app.UseElmahIo("API_KEY", new Guid("LOG_ID")); 

elmah.ioログ500の応答ように、これらのサービスを設定するための最良の方法ですと400の応答を無視しますか?

私が思いついた唯一の回避策は、1つではなく2つの例外ハンドリングミドルウェアを作成して登録することです。以前に登録したものとelmah.ioの後に登録するものです。それは動作しますが、少し醜いようだ:

app.UseMiddleware<HandleInternalExceptionMiddleware>() // set 500 responses (these will have already been logged in elmah.io) 
    app.UseElmahIo("API_KEY", new Guid("LOG_ID")); 
    app.UseMiddleware<HandleExternalExceptionMiddleware>() // set 400 responses but ignore exceptions that should return 500 (these won't be logged in elmah.io) 

私はこの動作を示すために、ここではサンプルプロジェクトを作成: https://github.com/johnnyoshika/elmah-io-experiment

答えて

2

にelmah.ioを設定するための正しい方法を、動作2を使用しているあなたがしたいです例外を処理する他のメソッドを呼び出した後にUseElmahIoメソッドを呼び出します。これは、多くのエラー処理ミドルウェア(HandleExceptionMiddlewareを含む)がすべての例外を取り込み、その結果を別のものに変換するためです。あなたの場合、HandleExceptionMiddlewareはすべての例外をキャッチし、新しい応答を設定します。この場合、私たちのミドルウェアは例外について通知されることはありません(あなたも同様です)。

私たちは、この解決するためにいくつかの異なる方法があります:UseMiddlewareを呼び出した後

ソリューション1

コールUseElmahIoを、カスタムを追加し、最終的に悪い要求をbecommingエラーを無視するフィルタを無視:

app.UseMiddleware<HandleExceptionMiddleware>(); 
app.UseElmahIo("API_KEY", new Guid("LOG_ID"), new ElmahIoSettings 
{ 
    OnFilter = msg => msg.Type == typeof(ArgumentException).Name 
}); 

このアプローチの欠点は、HandleExceptionMiddlewareとyoの両方で一連の同様のルールを維持する必要があることですur elmah.io config。UseMiddlewareを呼び出す前に

ソリューション2

コールUseElmahIoにして(この場合はHandleExceptionMiddlewareに飲み込ま)例外がスローされていない場合でも、ログに記録するステータスコードを指定します。

app.UseElmahIo("API_KEY", new Guid("LOG_ID"), new ElmahIoSettings 
{ 
    HandledStatusCodesToLog = new List<int> { 404, 500, ... } 
}); 
app.UseMiddleware<HandleExceptionMiddleware>(); 

このアプローチでは、すべてのステータスコードを手動で指定する必要があり、投げられた実際の例外からの情報はelmah.ioで利用できないという欠点があります。この理由はまた、HandleExceptionMiddlewareは、例外がスローされたことをelmah.ioが確認できないようにしています。

私は個人的には、stacktraceや例外タイプなどの情報を含むすべての例外がキャッチされているので、解決策1を優先します。

+0

偉大な答え!私はかなりのことを学びました。 elmah.ioはデフォルトで500個のレスポンスを記録するので、 'HandledStatusCodesToLog'リストに500個を追加する必要はなかったと私は考えていました。私は今、500がそのリストに入っているときの動作が異なることを学びました。あなたが言ったように、解決策2は間違いなくb/cスタックトレースは記録されません。ソリューション1は優れており、私の問題は解決しますが、私は2つのミドルウェアのアプローチを採用するつもりだと思います。この方法では、2つの場所で同じルールを維持する必要はありません。 –

関連する問題