2011-09-16 12 views
241

È possibile eseguire quanto segue utilizzando ELMAH?Come utilizzare ELMAH per registrare manualmente gli errori

logger.Log(" something"); 

che sto facendo qualcosa di simile:

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

Questa eccezione non sarà registrata automaticamente dal ELMAH, perché è stata gestita.

+1

Per riferimento futuro, ho scritto un post su esattamente questo: [registrazione degli errori di programmazione] (http://docs.elmah.io/logging-errors-programmatically/). Anche il mio [ELMAH Tutorial] (http://blog.elmah.io/elmah-tutorial/) ha alcune informazioni a riguardo. – ThomasArdal

risposta

383

metodo di scrittura di registro diretto, lavorando dal ELMAH 1.0:

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

ELMAH 1.2 introduce un'API più flessibile:

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

C'è una differenza tra le due soluzioni:

  • Raise metodo applica le regole di filtro ELMAH all'eccezione. Il metodo Log no.
  • Raise è basato su abbonamento ed è in grado di registrare un'eccezione nei vari logger.
+1

qual è la differenza tra il tuo metodo e gli altri? – Omu

+0

Funziona da ELMAH 1.0 –

+0

c'è qualche differenza tra la registrazione e l'aumento? – Omu

16
catch(Exception ex) 
{ 
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 
} 
28

È possibile utilizzare il metodo Elmah.ErrorSignal() per registrare un problema senza sollevare un'eccezione.

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

    // Continue 
} 
14

Sì, è possibile. ELMAH è stato progettato per intercettare le eccezioni non gestite. Tuttavia è possibile segnalare un'eccezione a ELMAH tramite la classe ErrorSignal. Queste eccezioni non vengono lanciate (non vengono visualizzate), ma vengono inviate solo a ELMAH (e ai sottoscrittori dell'evento Raise della classe ErrorSignal).

Un piccolo esempio:

protected void ThrowExceptionAndSignalElmah() 
{ 
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException()); 
} 
87

Suggerirei di completare la chiamata a Elmah in una semplice classe di wrapper.

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

Quindi basta chiamarlo ogni volta che è necessario registrare un errore.

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

Questo offre i seguenti vantaggi:

  • Non è necessario ricordare questa sintassi un po 'arcaica della chiamata Elmah
  • Se si dispone di molte DLL non è necessario fare riferimento Elmah Core da ogni singolo - e basta mettere questo nella propria DLL 'System'.
  • Se è necessario eseguire una gestione speciale o si desidera semplicemente inserire un punto di interruzione per eseguire il debug degli errori, è necessario disporre di un'unica posizione.
  • Se ti sposti da Elmah, puoi semplicemente cambiare un posto.
  • Se si desidera mantenere la registrazione degli errori legacy che si desidera conservare (ho solo un semplice meccanismo di registrazione degli errori collegato a delle interfacce utente che non ho immediatamente il tempo di rimuovere).

Nota: ho aggiunto una proprietà 'contextualMessage' per informazioni contestuali. Puoi omettere questo se preferisci, ma lo trovo molto utile. Elmah annulla automaticamente le eccezioni in modo che l'eccezione sottostante venga comunque segnalata nel log ma il contextualMessage sarà visibile quando si fa clic su di esso.

+1

Ottima risposta. Forse ELMAH dovrebbe implementare qualcosa di simile fuori dagli schemi. A volte è davvero difficile eseguire il debug di un errore senza contesto. – ra00l

+2

Mi piacciono tutti ma ingoio gli errori secondari con '// uh oh! continua così! Se la mia gestione degli errori sta fallendo, voglio sapere. Voglio che faccia rumore. –

+3

@JeremyCook Sono d'accordo, ma con l'avvertenza che se non stai attento le routine di gestione degli errori falliti tendono a chiamarsi e poi a saltare (oh e stavo anche chiamando un'API di terze parti per registrare l'errore). Probabilmente non avrei dovuto lasciare questo per questa risposta, ma ho avuto brutte esperienze con una cosa del genere prima che sia affermato –

11

Stavo cercando di fare la stessa cosa in un thread che avevo iniziato a mettere in coda la posta dalla mia applicazione MVC4, in quanto tale non avevo HttpContext disponibile quando è stata sollevata un'eccezione. Per fare questo ho finito con i seguenti basa su questa domanda e un'altra risposta trovato su qui: elmah: exceptions without HttpContext?

nel file di configurazione ho specificato il nome di un'applicazione:

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

Poi nel codice (come la risposta fornita sopra, ma senza la HttpContext) si può passare nulla al posto di un HttpContext:

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

Mi piace la tua soluzione; tuttavia, non sono in grado di risolvere "Elmah". nel mio progetto. Ho provato ad aggiungere "usando Elmah;" nel mio codice, ma non esiste nel mio contesto attuale. – Taersious

+0

@Taersious Che aspetto ha il tuo 'packages.config'? Vedete qualcosa di simile: '' '' ' ''? Hai installato con NuGET? – Matthew

+0

Vorrei dire di sì, ma il mio progetto è attualmente bloccato nel controllo del codice sorgente. Ho implementato elmah manualmente dal file di configurazione di esempio nel progetto. – Taersious

2

In alcuni casi CurrentHttpContext potrebbero non essere disponibili.

Definire

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

Usa

public class MyClass 
{ 
    readonly ILogger _logger; 

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

    public void MethodOne() 
    { 
     try 
     { 

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

Stavo cercando di scrivere messaggi personalizzati in tronchi ELMAH utilizzando Signal.FromCurrentContext() Raise (ex).; e ha scoperto che queste eccezioni siano gorgogliare fino, ad esempio:

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

Inoltre non vedo come ELMAH supporta diversi livelli di registrazione - è possibile disattivare la registrazione dettagliata da un'impostazione web.config?

+1

Se rilevi un'eccezione e non la butti di nuovo, le eccezioni non danno bolle. Forse fraintendermi? ELMAH non supporta diversi livelli di registrazione. È solo per errori. – ThomasArdal

+0

Grazie, Thomas. Questo è esattamente quello che stavo cercando di confermare –