Ich überarbeite derzeit ein großes Subsystem mit einer mehrschichtigen Architektur und habe Mühe, eine wirksame Strategie für die Fehlerprotokollierung und -behandlung zu entwickeln.
Angenommen, meine Architektur besteht aus den folgenden drei Ebenen:
- Öffentliche Schnittstelle (IE und MVC-Controller)
- Domänenschicht
- Datenzugriffsschicht
Meine Verwirrung ist, wo ich die Fehlerprotokollierung implementieren soll:
Die einfachste Lösung wäre, die Protokollierung auf der obersten Ebene zu implementieren (IE, Public Interface \ MVC Controller). Dies fühlt sich jedoch falsch an, da es bedeutet, die Ausnahme durch die verschiedenen Ebenen zu sprudeln und sie dann aufzuzeichnen. anstatt die Ausnahme an der Quelle zu protokollieren.
Es ist offensichtlich die beste Lösung, die Ausnahme an der Quelle zu protokollieren, da ich die meisten Informationen habe. Mein Problem dabei ist, dass ich nicht jede Ausnahme an der Quelle abfangen kann, ohne ALLE Ausnahmen abzufangen. Auf der Ebene der Domäne / öffentlichen Schnittstelle führt dies dazu, dass Ausnahmen abgefangen werden, die von der darunter liegenden Ebene bereits abgefangen, protokolliert und erneut ausgelöst wurden .
Eine andere mögliche Strategie ist eine Mischung aus # 1 und # 2; Dabei fange ich bestimmte Ausnahmen auf der Ebene ab, auf der sie höchstwahrscheinlich ausgelöst werden (IE-Catching, Protokollierung und erneutes Auslösen
SqlExceptions
auf der Datenzugriffsebene), und protokolliere dann alle weiteren nicht erfassten Ausnahmen auf der obersten Ebene. Dies würde jedoch auch erfordern, dass ich jede Ausnahme auf oberster Ebene abfange und erneut protokolliere, da ich nicht zwischen Fehlern, die bereits protokolliert wurden, und Fehlern, die noch nicht behandelt wurden, unterscheiden kann.
Dies ist offensichtlich ein Problem in den meisten Softwareanwendungen. Daher muss es eine Standardlösung für dieses Problem geben, die dazu führt, dass Ausnahmen an der Quelle abgefangen und einmal protokolliert werden. Ich kann jedoch nicht sehen, wie ich das selbst machen soll.
Beachten Sie, dass der Titel dieser Frage " Ausnahmen in einer mehrschichtigen Anwendung protokollieren" sehr ähnlich ist , die Antworten in diesem Beitrag jedoch nicht detailliert genug sind, um meine Frage zu beantworten.
quelle
The easiest solution would be to implement the logging at the top level
- mach das. Das Protokollieren von Ausnahmen an ihrer Quelle ist keine gute Idee, und jede Anwendung, auf die ich gestoßen bin, die dies tut, war ein PITA zum Debuggen. Es sollte in der Verantwortung des Anrufers liegen, Ausnahmen zu behandeln.try{ ... } catch(Exception ex) { Log(ex); }
würde dazu führen, dass auf jeder Ebene dieselbe Ausnahme protokolliert wird. (Es scheint auch eine ziemlich schlechte Praxis zu sein, jede Ausnahme auf jeder Ebene der CodebasisAntworten:
Zu Ihren Fragen:
Es ist absolut richtig und plausibel, die Ausnahmeblase bis zur obersten Ebene zu haben. Keine der Methoden der höheren Ebene versucht, einen Prozess nach dem Fehler fortzusetzen, was normalerweise nicht gelingen kann. Und eine gut ausgestattete Ausnahme enthält alle Informationen, die für die Protokollierung erforderlich sind. Wenn Sie nichts gegen Ausnahmen unternehmen, können Sie Ihren Code sauber halten und sich auf die Hauptaufgabe konzentrieren, anstatt auf die Fehler.
Das ist zur Hälfte richtig. Ja, die nützlichsten Informationen sind dort verfügbar. Aber ich würde empfehlen, all dies in das Exception-Objekt zu schreiben (falls es noch nicht vorhanden ist), anstatt es sofort zu protokollieren. Wenn Sie sich auf einer niedrigen Ebene anmelden, müssen Sie dennoch eine Ausnahme auslösen, um Ihren Anrufern mitzuteilen, dass Sie Ihren Job nicht abgeschlossen haben. Dies führt zu mehreren Protokollen desselben Ereignisses.
Ausnahmen
Meine wichtigste Richtlinie ist, Ausnahmen nur auf oberster Ebene zu erfassen und zu protokollieren. Und alle Ebenen darunter sollten sicherstellen, dass alle erforderlichen Fehlerinformationen auf die oberste Ebene übertragen werden. In einer Einzelprozessanwendung, z. B. in Java, bedeutet dies meistens, überhaupt nicht außerhalb der obersten Ebene zu versuchen / zu fangen oder zu protokollieren.
Manchmal möchten Sie einige Kontextinformationen in das Ausnahmeprotokoll aufnehmen, die in der ursprünglichen Ausnahme nicht verfügbar sind, z. B. die SQL-Anweisung und die Parameter, die ausgeführt wurden, als die Ausnahme ausgelöst wurde. Dann können Sie die ursprüngliche Ausnahme abfangen und eine neue auslösen, die die ursprüngliche Ausnahme plus den Kontext enthält.
Natürlich stört das wirkliche Leben manchmal:
In Java müssen Sie manchmal eine Ausnahme abfangen und in einen anderen Ausnahmetyp umbrechen, um einige feste Methodensignaturen zu beachten. Wenn Sie jedoch eine Ausnahme erneut auslösen, stellen Sie sicher, dass die erneut ausgelöste alle Informationen enthält, die für die spätere Protokollierung erforderlich sind.
Wenn Sie eine Grenze zwischen Prozessen überschreiten, können Sie technisch häufig nicht das gesamte Ausnahmeobjekt einschließlich des Stack-Trace übertragen. Und natürlich kann die Verbindung verloren gehen. Hier ist also ein Punkt, an dem ein Dienst Ausnahmen protokollieren und dann versuchen sollte, so viele Fehlerinformationen wie möglich über die Leitung an den Client zu übertragen. Der Dienst muss sicherstellen, dass der Client eine Fehlermeldung erhält, indem er entweder eine Fehlerantwort erhält oder bei einer unterbrochenen Verbindung eine Zeitüberschreitung feststellt. Dies führt normalerweise dazu, dass derselbe Fehler zweimal protokolliert wird, einmal innerhalb des Dienstes (mit mehr Details) und einmal auf der obersten Ebene des Clients.
Protokollierung
Ich füge einige Sätze zum Protokollieren im Allgemeinen hinzu, nicht nur zum Protokollieren von Ausnahmen.
Neben Ausnahmesituationen möchten Sie, dass wichtige Aktivitäten Ihrer Anwendung auch im Protokoll aufgezeichnet werden. Verwenden Sie daher ein Protokollierungsframework.
Seien Sie vorsichtig mit den Protokollebenen (das Lesen von Protokollen, in denen Debug-Informationen und schwerwiegende Fehler nicht mit unterschiedlichen gekennzeichnet sind, ist schmerzhaft!). Typische Protokollebenen sind:
Setzen Sie in der Produktion die Protokollebene auf INFO. Die Ergebnisse sollten für einen Systemadministrator nützlich sein, damit er weiß, was los ist. Erwarten Sie von ihm, dass er Sie für jeden FEHLER im Protokoll und in der Hälfte der WARNUNGEN um Hilfe oder Fehlerbehebung bittet.
Aktivieren Sie die DEBUG-Stufe nur während echter Debugsitzungen.
Gruppieren Sie die Protokolleinträge in entsprechende Kategorien (z. B. nach dem vollqualifizierten Klassennamen des Codes, der den Eintrag generiert), sodass Sie Debug-Protokolle für bestimmte Teile Ihres Programms aktivieren können.
quelle
Ich bereite mich auf die Abstimmungen vor, aber ich werde mich auf die Beine stellen und sagen, ich bin nicht sicher, ob ich dem zustimmen kann.
Das Aufblähen von Ausnahmen und noch weniger das erneute Aufzeichnen von Ausnahmen ist ein zusätzlicher Aufwand mit geringem Nutzen. Fangen Sie die Ausnahme an der Quelle ab (ja, am einfachsten), protokollieren Sie sie, aber lösen Sie die Ausnahme dann nicht erneut aus, sondern melden Sie dem Aufrufer nur "Fehler". "-1", null, leere Zeichenfolge, eine Aufzählung, was auch immer. Der Anrufer muss nur wissen, dass der Anruf fehlgeschlagen ist, fast nie die grauenhaften Details. Und die werden in deinem Logbuch sein, oder? In dem seltenen Fall, dass der Anrufer die Details benötigt, gehen Sie voran und sprudeln Sie, aber nicht als automatischer undenkbarer Standard.
quelle
null
oder die leere Zeichenfolge? Ist es -1 oder eine negative Zahl? 2. Wenn es den Anrufer nicht interessiert (dh nicht prüft), führt dies zu Fehlern, die nicht mit der ursprünglichen Ursache zusammenhängen, zNullPointerException
. B. a . Oder schlimmer: Die Berechnung wird mit falschen Werten fortgesetzt. 3. Wenn es den Aufrufer interessieren würde, aber der Programmierer denkt, dass diese Methode fehlschlägt, erinnert ihn der Compiler nicht daran. Ausnahmen haben diese Probleme nicht, entweder Sie fangen oder Sie werfen um.