2016-08-04 16 views
4

This article erläutert im Detail, wie eine ASP.NET-Ausnahme in Windows EventLog protokolliert wird und dem Endbenutzer eine benutzerdefinierte Fehlerseite angezeigt wird.Schreiben Sie eine gefangene ASP.NET-Ausnahme in EventLog, ohne Details zu verlieren

Der standardmäßige Ereignisprotokollierungsmechanismus für eine ASP.NET-Webanwendung enthält jedoch automatisch viele nützliche Informationen, die in diesem Artikel nicht gezeigt werden. Das Implementieren des Codes in dem Artikel führt zu einem Verlust von Detail/Granularität in meinem Fehlerereignis.

Zum Beispiel können bei der automatischen Erkennung von nicht erfassten Exceptions viele Attribute unter den Überschriften angezeigt werden: Ereignisinformationen, Anwendungsinformationen, Prozessinformationen, Anforderungsinformationen, Threadinformationen, benutzerdefinierte Ereignisdetails.

Wie kann ich die Protokollierung aller Informationen implementieren, die in einer nicht abgefangenen Ausnahme protokolliert werden, und meine benutzerdefinierten Informationen in den Abschnitt Benutzerdefinierte Ereignisdetails? Die beste Antwort sollte vorzugsweise ein oder mehrere eingebaute Verfahren von System.Diagnostics oder System.Exception oder ähnlichem verwenden, d. H. Schreiben von so wenig Code wie möglich, um den Protokolleintrag mit allen oben erwähnten Abschnitten zu schreiben und einfach irgendwelche benutzerdefinierten Details an die Zeichenfolge anzufügen.

Wenn es möglich ist, möchte ich auch die einzigartige gehashten Ereignis-ID zurück (Beispiel b68b3934cbb0427e9497de40663c5225 von unten) zurück an die Anwendung für die Anzeige auf meinem ErrorPage.aspx

Beispiel Log-Format benötigt:

Event code: 3005 
Event message: An unhandled exception has occurred. 
Event time: 15/07/2016 15:44:01 
Event time (UTC): 15/07/2016 14:44:01 
Event ID: b68b3934cbb0427e9497de40663c5225 
Event sequence: 131 
Event occurrence: 2 
Event detail code: 0 

Application information: 
    Application domain: /LM/W3SVC/3/ROOT-1-131130657267252632 
    Trust level: Full 
    Application Virtual Path:/
    Application Path: C:\WWW\nobulus\nobulusPMM\Application\PMM\ 
    Machine name: L-ADAM 

Process information: 
    Process ID: 47216 
    Process name: iisexpress.exe 
    Account name: L-ADAM\Adam 

Exception information: 
    Exception type: ApplicationException 
    Exception message: Error running stored procedure saveValidation: Procedure or function 'saveValidation' expects parameter '@ValidatedBy', which was not supplied. 
    at PMM.Models.PMM_DB.runStoredProcedure(String StoredProcedureName, List`1 SQLParameters) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 104 
    at PMM.Models.PMM_DB.saveValidation(String PTLUniqueID, String ValidatedBy, DateTime ValidationDateTime, Nullable`1 ValidationCategoryID, String ValidationCategory,  String Comment, Nullable`1 ClockStartDate, Nullable`1 ClockStopDate, String StartRTTStatus, String StopRTTStatus, String LastRTTStatus, Boolean MergedPathway, String  MergedPathwayID, String ExtinctPathwayID, DataTable ChecklistResponses) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 265 
    at PMM.Validate.lnkSaveButton_Click(Object sender, EventArgs e) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Validate.aspx.cs:line 323 
    at System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e) 
    at System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) 
    at System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) 
    at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) 
    at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) 
    at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 



Request information: 
    Request URL: http://localhost:6901/Validate?PTLUniqueID=RTT10487 
    Request path: /Validate 
    User host address: ::1 
    User: L-ADAM\Adam 
    Is authenticated: True 
    Authentication Type: Negotiate 
    Thread account name: L-ADAM\Adam 

Thread information: 
    Thread ID: 19 
    Thread account name: L-ADAM\Adam 
    Is impersonating: False 
    Stack trace: at PMM.Models.PMM_DB.runStoredProcedure(String StoredProcedureName, List`1 SQLParameters) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB. cs:line 104 
    at PMM.Models.PMM_DB.saveValidation(String PTLUniqueID, String ValidatedBy, DateTime ValidationDateTime, Nullable`1 ValidationCategoryID, String ValidationCategory,  String Comment, Nullable`1 ClockStartDate, Nullable`1 ClockStopDate, String StartRTTStatus, String StopRTTStatus, String LastRTTStatus, Boolean MergedPathway, String  MergedPathwayID, String ExtinctPathwayID, DataTable ChecklistResponses) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 265 
    at PMM.Validate.lnkSaveButton_Click(Object sender, EventArgs e) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Validate.aspx.cs:line 323 
    at System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e) 
    at System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) 
    at System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) 
    at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) 
    at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) 
    at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 


Custom event details: 

Antwort

4

UPDATE

ich fand ILSpy mit und in verschiedenen Framework-Klassen-Roaming, die ASP.NET intern verwendet WebErrorEvent, die geschützte Methoden besitzen, um das gleiche Verhalten zu erreichen.

Lösung 1:

Dazu nur eine Klasse erstellen, die WebErrorEvent erbt, und dann außer Kraft setzen ihre constructor:

public class CustomWebErrorEvent : WebErrorEvent 
{ 
    public CustomWebErrorEvent(string message, EventSource source, int eventCode, Exception ex) : base(message, source, eventCode, ex) 
    { 
    } 
} 

Dann ist es innerhalb der Fehlermanagementmethode von Global.asax verwenden:

protected void Application_Error(Object sender, EventArgs e) 
{ 
    // Log error to the Event Log 
    Exception myError = null; 
    if (HttpContext.Current.Server.GetLastError() != null) 
    { 
     var r = new CustomWebErrorEvent("error", null, 120, HttpContext.Current.Server.GetLastError()); 
    } 
} 

Ich bin mir ziemlich sicher, dass es auch möglich ist, ASPNET zu überlasten nur gerade eine benutzerdefinierte WebErrorEvent zu erhöhen, aber ich habe es noch nicht gefunden.

Ich versuche immer noch herauszufinden, wie benutzerdefinierte Informationen zum Ereignis hinzugefügt werden, da das Überschreiben der Methode FormatCustomEventDetails nicht für Web-verwaltete Fehlerereignisse aufgerufen wird.

Lösung 2:

Wenn nicht möglich, da fehlt das Hinzufügen von benutzerdefinierten Feldern für jetzt können Sie eine ähnliche Methode verwenden, die ich geschrieben habe, die die gleiche Leistung hat:

// Log error to the Event Log 
Exception myError = null; 
if (HttpContext.Current.Server.GetLastError() != null) 
{ 
    var request = HttpContext.Current.Request; 
    myError = HttpContext.Current.Server.GetLastError(); 

    var dateAsBytes = System.Text.Encoding.UTF8.GetBytes(DateTime.Now.ToString("G")); 
    var id = Convert.ToBase64String(System.Security.Cryptography.MD5.Create().ComputeHash(dateAsBytes)); 

    // Event info: 
    var eventMessage = myError.Message; 
    var currentTime = DateTime.Now.ToString("G"); 
    var currentTimeUTC = DateTime.UtcNow.ToString("G"); 

    // Application info: 
    var appDomainName = AppDomain.CurrentDomain.FriendlyName; 
    var appDomainTrustLevel = (AppDomain.CurrentDomain.IsFullyTrusted) ? "Full" : "Partial"; 
    var appVirtualPath = VirtualPathUtility.GetDirectory(request.Path); 
    var appPath = request.PhysicalApplicationPath; 
    var machineName = Environment.MachineName; 

    // Process info: 
    var process = Process.GetCurrentProcess(); 
    var processId = process.Id; 
    var processName = process.ProcessName; 
    var user = System.Security.Principal.WindowsIdentity.GetCurrent().User; 
    var accountName = user.Translate(typeof(System.Security.Principal.NTAccount)); 

    // Exception info: 
    var exceptionType = myError.GetType().FullName; 
    var exceptionMessage = myError.Message; 
    var exceptionStack = myError.StackTrace; 

    // Request info: 
    var url = request.Url.AbsoluteUri; 
    var urlPath = request.Url.PathAndQuery; 
    var remoteAddress = request.UserHostAddress; 
    var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; 
    var isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated; 
    var authenticationType = System.Security.Principal.WindowsIdentity.GetCurrent().AuthenticationType; 

    // Thread info: 
    var impersonationLevel = System.Security.Principal.WindowsIdentity.GetCurrent().ImpersonationLevel; 
    var exceptionStack2 = myError.StackTrace; 

    // TODO: aggregate all info as string before writting to EventLog. 
} 

ich mit Ergebnis bestehenden .NET API benötigt fast alle benötigten Felder aus Ihrer Ausgabe, die nur benötigt werden, um als String aggregiert zu werden, bevor sie in EventLog ausgegeben werden.sehen

Sie, dass einige der Objekt verwende ich (wie AppDomain.CurrentDomain, HttpContext.Current.Request oder Process.GetCurrentProcess() viele andere Informationen gibt, die auch an den Ausgang ne hinzugefügt könnte, wenn nötig.

Das alles kann gewickelt werden natürlich unter einer Methode für Code Kürze

+0

Danke für das. Ich möchte nur ein wenig warten, um zu sehen, ob wir weitere Antworten in den nächsten Tagen bekommen. Wenn nicht, dann werde ich korrigieren und die Prämie - Ich hatte gehofft, die Methode zu finden, die .NET verwendet, um dieses Protokoll für nicht abgefangene Ausnahmen zu erstellen und es zu verwenden - wenn die Methode verbessert wird, um mehr Informationen in einer zukünftigen Version zu erfassen, sollte ich in der Lage sein um dies zu nutzen, ohne diesen Code zu pflegen. Ich will das Rad nicht einfach neu erfinden! – Adam

+0

Ihre Lösung mit doppelter Wahl ist jetzt ziemlich genial! :) Ich muss nur einen Blick darauf werfen, was in 'var r' zurückgegeben wird, da ich den 'Event ID'-Hash auf dem Bildschirm anzeigen möchte, wenn es möglich ist, wenn Benutzer Fehler an das Support-Team melden. – Adam

+0

Es scheint, dass wir noch eine Kette mit einer der beiden Lösungen verketten müssen. Wird ILSpy uns helfen, die Methode zu finden, die das tut? – Adam