2017-04-26 3 views
2

Hinweis: Diese Frage bezieht sich auf elmah.io (https://elmah.io/), den cloudbasierten Ausnahmeprotokollierungsdienst und nicht auf die traditionelle Elmah .Net-Bibliothek.Wie Elmah.io gut mit ASP.NET Core und Fehlerbehandlung Middleware machen?

Ich benutze ASP.NET Core und habe eine einfache Ausnahme behandeln Middleware.

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

Diese Middleware die folgenden JSON Antworten in Abhängigkeit von den Ausnahmen wird zurückkehren, dass sie sieht:

Für Argument:

HTTP/1.1 400 Bad Request 

{"message":""} 

Für alle anderen Ausnahmen:

HTTP/1.1 500 Internal Server Error 

{"message":""} 

I 'd wie elmah.io Log 500 Antworten und ignorieren 400 Antworten (das ist die Standardkonfiguration von elmah.io). Wenn jedoch die Exception-Handler und elmah.io in dieser Reihenfolge in Startup des Configure Hook registriert, nichts in elmah.io angemeldet wird:

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

Wenn ich jedoch die Registrierung, um auf die folgenden ändern, wird alles protokolliert (einschließlich 400 Antworten). Dies macht Sinn, da elmah.io die Ausnahmen behandelt, bevor HandleExceptionMiddleware bekommt eine Chance, um die Antwort zu ändern:

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

Was ist der beste Weg, um diese Dienste zu konfigurieren, so dass elmah.io Protokolle 500 Antworten und 400 Antworten ignoriert?

Die einzige Problemumgehung, die ich gefunden habe, ist das Erstellen und Registrieren von 2 Ausnahmeübergabe-Middlewares statt nur 1. Einer, der sich vorher anmeldet, und einer, der sich nach elmah.io registriert. Es funktioniert, aber scheint ein wenig hässlich:

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) 

ich hier ein Beispielprojekt erstellt, dieses Verhalten zu zeigen: https://github.com/johnnyoshika/elmah-io-experiment

Antwort

2

Der richtige Weg elmah.io zu konfigurieren, wird unter Verwendung von Verhalten 2. Sie wollen Rufen Sie die UseElmahIo Methode auf, nachdem Sie andere Methoden aufgerufen haben, die Ausnahmen behandeln. Dies liegt daran, eine Menge Fehlerbehandlung Middleware (einschließlich Ihrer HandleExceptionMiddleware) alle Ausnahmen schlucken und das Ergebnis in etwas anderes konvertieren. In Ihrem Fall fängt HandleExceptionMiddleware alle Ausnahmen ab und legt eine neue Antwort fest. In diesem Fall wird unsere Middleware nie über die Ausnahme benachrichtigt (wie Sie auch erwähnen).

Wir haben ein paar verschiedene Möglichkeiten, dies zu lösen:

Lösung 1

Anruf UseElmahIo nach UseMiddleware Aufruf und einen benutzerdefinierten ignorieren Filter hinzufügen, um die Fehler schließlich becomming schlecht Anfragen zu ignorieren:

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

Der Nachteil dieses Ansatzes ist, dass Sie eine Reihe ähnlicher Regeln sowohl in HandleExceptionMiddleware als auch in yo pflegen müssen Ihre elmah.io Konfiguration.

Lösung 2

Anruf UseElmahIo vor UseMiddleware aufrufen und gibt Codes, welchen Status, auch wenn eine Ausnahme zu protokollieren (durch HandleExceptionMiddleware in diesem Fall geschluckt) nicht geworfen:

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

Die Nachteil dieser Methode ist, dass Sie alle Statuscodes manuell angeben müssen und dass die Informationen der aktuellen Ausnahme nicht auf elmah.io verfügbar sind. Der Grund dafür ist wieder, dass HandleExceptionMiddleware es für elmah.io unmöglich machen zu sehen, dass eine Ausnahme ausgelöst wurde.

Ich persönlich bevorzuge Lösung 1, da dies sicherstellt, dass alle Ausnahmen eingefangen werden, einschließlich Informationen wie StackTrace und der Ausnahmetyp.

+0

Große Antwort! Ich habe einiges gelernt. Ich hatte das gedacht, weil elmah.io 500 Antworten standardmäßig protokolliert, dass ich 500 zur 'HandledStatusCodesToLog' Liste nicht hinzufügen musste. Ich habe jetzt gelernt, dass das Verhalten anders ist, wenn 500 in dieser Liste ist. Wie du schon sagtest, Lösung 2 ist definitiv nicht großartig b/c die Stack-Trace wird nicht protokolliert. Lösung 1 ist besser und wird mein Problem lösen, aber ich denke, ich werde bei der 2-Middleware bleiben, weil ich auf diese Weise nicht die gleichen Regeln an 2 Stellen einhalten muss. –

Verwandte Themen