c# exception-handling elmah error-logging

elmah c#



Cómo usar ELMAH para registrar errores manualmente (8)

A veces, CurrentHttpContext puede no estar disponible.

Definir

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

Utilizar

public class MyClass { readonly ILogger _logger; public MyClass(ILogger logger) { _logger = logger; } public void MethodOne() { try { } catch (Exception ex) { _logger.LogError(ex, withinHttpContext: false); } } }

¿Es posible hacer lo siguiente usando ELMAH?

logger.Log(" something");

Estoy haciendo algo como esto:

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

Esta excepción no será registrada automáticamente por ELMAH, porque fue manejada.


Estaba buscando hacer lo mismo en un hilo que había empezado a poner en cola el correo desde mi aplicación MVC4, por lo que no tenía el HttpContext disponible cuando se generó una excepción. Para hacer esto, terminé con lo siguiente basado en esta pregunta y otra respuesta encontrada aquí: elmah: excepciones sin HttpContext?

En el archivo de configuración especificé un nombre de aplicación:

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

Luego, en el código (como la respuesta proporcionada anteriormente, pero sin el HttpContext) puede pasar nulo en lugar de un HttpContext:

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


Estaba intentando escribir mensajes personalizados en los registros de elmah usando Signal.FromCurrentContext (). Raise (ex); y se encontró que estas excepciones se burbujean, por ejemplo:

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

Además, no veo cómo elmah admite diferentes niveles de registro. ¿Es posible desactivar el registro detallado mediante una configuración web.config?


Método de escritura de registro directo, funcionando desde ELMAH 1.0:

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

ELMAH 1.2 introduce una API más flexible:

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

Hay una diferencia entre las dos soluciones:

  • Raise método de aumento aplica las reglas de filtrado de ELMAH a la excepción. Método de Log no lo hace.
  • Raise se basa en suscripciones y puede registrar una excepción en varios registradores.

Puede usar el método Elmah.ErrorSignal () para registrar un problema sin generar una excepción.

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


Recomiendo envolver la llamada a Elmah en una clase de envoltura 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 } } }

Entonces simplemente llámelo cada vez que necesite registrar un error.

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

Esto tiene los siguientes beneficios:

  • No necesitas recordar esta sintaxis ligeramente arcaica de la llamada de Elmah
  • Si tiene muchas DLL, no necesita hacer referencia a Elmah Core de todas y cada una, y simplemente coloque esto en su propia DLL del ''Sistema''.
  • Si alguna vez necesita realizar un manejo especial o simplemente desea poner un punto de interrupción para depurar errores, lo tiene todo en un solo lugar.
  • Si alguna vez te alejas de Elmah, puedes cambiar de lugar.
  • Si tiene un registro de errores heredado que desea conservar (resulta que tengo un mecanismo de registro de errores simple que está vinculado a algunas interfaces de usuario que no tengo tiempo para eliminar de inmediato).

Nota: He agregado una propiedad ''contextualMessage'' para información contextual. Puedes omitir esto si lo prefieres, pero lo encuentro muy útil. Elmah desenvuelve automáticamente las excepciones para que la excepción subyacente se siga informando en el registro, pero el mensaje contextual será visible cuando haga clic en él.


Sí, es posible. ELMAH fue diseñado para interceptar excepciones no manejadas. Sin embargo, puede señalar una excepción a ELMAH a través de la clase ErrorSignal. Esas excepciones no se lanzan (no se aceleran), sino que solo se envían a ELMAH (y a los suscriptores del evento Raise de la clase ErrorSignal).

Un pequeño ejemplo:

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


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