Kann man mit ELMAH folgendes tun?
logger.Log(" something");
Ich mache so etwas:
try
{
// Code that might throw an exception
}
catch(Exception ex)
{
// I need to log error here...
}
Diese Ausnahme wird nicht automatisch von ELMAH protokolliert, da sie behandelt wurde.
Direktes Protokollschreibverfahren, das seit ELMAH 1.0 funktioniert:
try
{
some code
}
catch(Exception ex)
{
Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
}
ELMAH 1.2 führt eine flexiblere API ein:
try
{
some code
}
catch(Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
Es gibt einen Unterschied zwischen den beiden Lösungen:
Raise
-Methode wendet ELMAH-Filterregeln auf die Ausnahme an. Log
-Methode funktioniert nicht.Raise
ist abonnementbasiert und kann eine Ausnahme in den verschiedenen Loggern protokollieren.Ich würde empfehlen, den Anruf an Elmah in einer einfachen eigenen Wrapper-Klasse zu wickeln.
using Elmah;
public static class ErrorLog
{
/// <summary>
/// Log error to Elmah
/// </summary>
public static void LogError(Exception ex, string contextualMessage=null)
{
try
{
// log error to Elmah
if (contextualMessage != null)
{
// log exception with contextual information that's visible when
// clicking on the error in the Elmah log
var annotatedException = new Exception(contextualMessage, ex);
ErrorSignal.FromCurrentContext().Raise(annotatedException, HttpContext.Current);
}
else
{
ErrorSignal.FromCurrentContext().Raise(ex, HttpContext.Current);
}
// send errors to ErrorWS (my own legacy service)
// using (ErrorWSSoapClient client = new ErrorWSSoapClient())
// {
// client.LogErrors(...);
// }
}
catch (Exception)
{
// uh oh! just keep going
}
}
}
Dann rufen Sie es einfach an, wenn Sie einen Fehler protokollieren möchten.
try {
...
}
catch (Exception ex)
{
// log this and continue
ErrorLog.LogError(ex, "Error sending email for order " + orderID);
}
Dies hat folgende Vorteile:
Hinweis: Ich habe eine 'contextualMessage'-Eigenschaft für Kontextinformationen hinzugefügt. Sie können dies weglassen, wenn Sie möchten, aber ich finde es sehr nützlich. Elmah packt automatisch Ausnahmen aus, sodass die zugrunde liegende Ausnahme immer noch im Protokoll gemeldet wird. Wenn Sie jedoch darauf klicken, wird die contextualMessage angezeigt.
Sie können die Elmah.ErrorSignal () - Methode verwenden, um ein Problem zu protokollieren, ohne eine Ausnahme auszulösen.
try
{
// Some code
}
catch(Exception ex)
{
// Log error
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
// Continue
}
catch(Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
Ja, es ist möglich. ELMAH wurde entwickelt, um nicht behandelte Ausnahmen abzufangen. Sie können jedoch über die Klasse ErrorSignal eine Ausnahme an ELMAH melden. Diese Ausnahmen werden nicht ausgelöst (blase nicht auf), sondern nur an ELMAH (und an Abonnenten des Raise-Ereignisses der ErrorSignal-Klasse).
Ein kleines Beispiel:
protected void ThrowExceptionAndSignalElmah()
{
ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
}
Ich habe versucht, dasselbe in einem Thread zu tun, mit dem ich Mail aus meiner MVC4-Anwendung in eine Warteschlange gestellt hatte, da mir HttpContext nicht zur Verfügung stand, als eine Ausnahme ausgelöst wurde. Um dies zu tun, endete ich mit der folgenden Frage basierend auf dieser Frage und einer anderen Antwort, die hier zu finden ist: elmah: Ausnahmen ohne HttpContext?
In der Konfigurationsdatei habe ich einen Anwendungsnamen angegeben:
<elmah>
<security allowRemoteAccess="false" />
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/>
</elmah>
Dann können Sie im Code (wie in der Antwort oben, aber ohne den HttpContext) null anstelle eines HttpContext übergeben:
ThreadPool.QueueUserWorkItem(t => {
try {
...
mySmtpClient.Send(message);
} catch (SomeException e) {
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(e));
}
});
Manchmal ist CurrentHttpContext
nicht verfügbar.
Definieren
public class ElmahLogger : ILogger
{
public void LogError(Exception ex, string contextualMessage = null, bool withinHttpContext = true)
{
try
{
var exc = contextualMessage == null
? ex
: new ContextualElmahException(contextualMessage, ex);
if (withinHttpContext)
ErrorSignal.FromCurrentContext().Raise(exc);
else
ErrorLog.GetDefault(null).Log(new Error(exc));
}
catch { }
}
}
Benutzen
public class MyClass
{
readonly ILogger _logger;
public MyClass(ILogger logger)
{
_logger = logger;
}
public void MethodOne()
{
try
{
}
catch (Exception ex)
{
_logger.LogError(ex, withinHttpContext: false);
}
}
}
Ich bin auf ASP.NET-Kern und ich verwende ElmahCore.
Um Fehler manuell zu protokollieren mit HttpContext (in der Steuerung), schreiben Sie einfach:
using ElmahCore;
...
HttpContext.RiseError(new Exception("Your Exception"));
In einem anderen Teil Ihrer Anwendung ohne HttpContext:
using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));
Ich habe versucht, benutzerdefinierte Meldungen mit Hilfe von Signal.FromCurrentContext () in elmah-Protokolle zu schreiben. Raise (ex); und festgestellt, dass diese Ausnahmen sprudeln, zB:
try
{
...
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
// this will write to the log AND throw the exception
}
Außerdem sehe ich nicht, wie elmah verschiedene Protokollierungsstufen unterstützt. Kann ich die ausführliche Protokollierung mit einer web.config-Einstellung ausschalten?