web-dev-qa-db-fra.com

Comment utiliser ELMAH pour enregistrer manuellement les erreurs

Est-il possible de faire ce qui suit en utilisant ELMAH?

logger.Log(" something");

Je fais quelque chose comme ça:

try 
{
    // Code that might throw an exception 
}
catch(Exception ex)
{
    // I need to log error here...
}

Cette exception ne sera pas automatiquement enregistrée par ELMAH, car elle a été gérée.

254
Omu

Méthode d'écriture directe du journal, fonctionnant depuis ELMAH 1.0:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
}

ELMAH 1.2 introduit une API plus flexible:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}

Il y a une différence entre les deux solutions:

  • La méthode Raise applique les règles de filtrage ELMAH à l'exception. La méthode Log ne fonctionne pas.
  • Raise est basé sur un abonnement et peut enregistrer une exception dans plusieurs enregistreurs.
403
Andrey Kamaev

Je recommanderais de placer l'appel à Elmah dans une classe de wrapper simple.

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

Ensuite, appelez-le chaque fois que vous devez enregistrer une erreur.

try {
   ...
} 
catch (Exception ex) 
{
    // log this and continue
    ErrorLog.LogError(ex, "Error sending email for order " + orderID);
}

Cela présente les avantages suivants:

  • Vous n'avez pas besoin de vous rappeler cette syntaxe légèrement archaïque de l'appel d'Elmah
  • Si vous avez plusieurs DLL, vous n'avez pas besoin de référencer Elmah Core à partir de chacune d'elles - et de simplement mettre cela dans votre propre DLL 'Système'.
  • Si vous avez besoin de faire une manipulation spéciale ou si vous voulez juste mettre un point d'arrêt pour corriger les erreurs, vous avez tout à la même place.
  • Si jamais tu t'éloignes d'Elmah, tu peux changer d'un endroit.
  • Si vous souhaitez conserver la journalisation des erreurs héritée (un simple mécanisme de journalisation des erreurs est lié à certaines interfaces utilisateur que je n'ai pas le temps de supprimer immédiatement).

Remarque: j'ai ajouté une propriété 'contextualMessage' pour les informations contextuelles. Vous pouvez l'omettre si vous préférez, mais je le trouve très utile. Elmah décompresse automatiquement les exceptions afin que l'exception sous-jacente soit toujours signalée dans le journal, mais que le message contextuel soit visible lorsque vous cliquez dessus.

90
Simon_Weaver

Vous pouvez utiliser la méthode Elmah.ErrorSignal () pour enregistrer un problème sans déclencher une exception.

try
{
    // Some code
}
catch(Exception ex)
{
    // Log error
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

    // Continue
}
29
bigtv
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
19
Darin Dimitrov

Oui c'est possible. ELMAH a été conçu pour intercepter les exceptions non gérées. Cependant, vous pouvez signaler une exception à ELMAH via la classe ErrorSignal. Ces exceptions ne sont pas levées (ne font pas de bulles), mais sont uniquement envoyées à ELMAH (et aux abonnés de l'événement Raise de la classe ErrorSignal).

Un petit exemple:

protected void ThrowExceptionAndSignalElmah()
{
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
}
14
Christophe Geers

Je cherchais à faire la même chose dans un fil. J'avais commencé à mettre les messages en attente à partir de mon application MVC4; par conséquent, je n'avais pas le HttpContext disponible lorsqu'une exception était déclenchée. Pour ce faire, je me suis retrouvé avec ce qui suit sur la base de cette question et d’une autre réponse trouvée ici: elmah: des exceptions sans HttpContext?

Dans le fichier de configuration, j'ai spécifié un nom d'application:

<elmah>
    <security allowRemoteAccess="false" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/>   
</elmah>

Ensuite, dans le code (comme la réponse fournie ci-dessus, mais sans le HttpContext), vous pouvez passer null à la place d'un HttpContext:

ThreadPool.QueueUserWorkItem(t => {
     try {
         ...
         mySmtpClient.Send(message);
     } catch (SomeException e) {
         Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(e));
     }
 });
13
Matthew

Parfois, CurrentHttpContext peut ne pas être disponible. 

Définir

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 { }
    }
}

Utilisation

public class MyClass
{
    readonly ILogger _logger;

    public MyClass(ILogger logger)
    {
        _logger = logger;
    }

    public void MethodOne()
    {
        try
        {

        }
        catch (Exception ex)
        {
            _logger.LogError(ex, withinHttpContext: false);
        }
    }
}
3
tchelidze

Je suis sur noyau ASP.NET et j'utilise ElmahCore.

Pour consigner manuellement les erreurs avec HttpContext (dans le contrôleur), écrivez simplement:

using ElmahCore;
...
HttpContext.RiseError(new Exception("Your Exception"));

Dans une autre partie de votre application sans HttpContext:

using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));
1
A. Morel

J'essayais d'écrire des messages personnalisés dans les journaux elmah à l'aide de Signal.FromCurrentContext (). Raise (ex); et a constaté que ces exceptions sont remontées, par exemple:

try
{
    ...
}
catch (Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
    // this will write to the log AND throw the exception
}

En outre, je ne vois pas comment elmah prend en charge différents niveaux de journalisation - est-il possible de désactiver la journalisation détaillée par un paramètre web.config?

0
Valery Gavrilov