Usando ELMAH con MongoDB

ELMAH (Error Logging Modules and Handlers) es una librería para almacenar logs de las excepciones que se producen en nuestra aplicación. Esta librería podemos utilizarla en aplicaciones ASP.NET y tiene muchas opciones interesantes. Por ejemplo podemos conectarnos de forma remota para ver los errores o utilizarla con aplicaciones ya existentes sin tener que recompilar. Podéis ver todas las características de ELMAH en su página de Google Code.

Si queréis ver una completa explicación de como usarlo con SQL Server, gestionar los errores, o incluso enviarlos por correo, no os perdáis la entrada en el blog de @panicoenlaxbox.

Además de SQL Server, podemos configurar ELMAH con otros proveedores de bases de datos. Podemos usar PostgreSQL, Oracle, MySQL y como no MongoDB.

Veamos cómo.

Componentes necesarios

  • Obviamente, lo primero que necesitamos es un servidor MongoDB arrancado y funcionando. Recordad que en mi Tutorial de MongoDB, explico como instalar y usar MongoDB.
  • También nos hace falta un proyecto ASP.NET. Por ejemplo, yo he usado para este artículo una aplicación MVC 5.
  • Y para acabar, nos hacen falta los paquetes ELMAH, el driver de MongoDB para C#, y ELMAH on MongoDB. Instalarlos es muy sencillo, ya que desde NuGet bastará con hacer un Install-Package elmah.mongodb para que se instalen todas las dependencias.

Y ya está. Una vez tengamos todo preparado, tan solo tenemos que configurar ELMAH, para que guarde los datos en nuestro servidor MongoDB

Configurando ELMAH

De alguna manera, le tenemos que decir a ELMAH, donde debe guardar los datos de los errores. Es tan fácil como ir al Web.config de nuestra aplicación, y buscar la siguiente entrada:

<connectionstrings><add name="elmah-mongodb" connectionstring="server=localhost;database=elmah;"></add></connectionstrings>

El problema es que la cadena de conexión que se ha añadido al Web.config al añadir los paquetes desde NuGet, no tiene mucho que ver con una cadena de conexión a MongoDB. En la documentación podéis ver el formato que debe tener. Así que en base a eso, cambiamos nuestra sección connectionStrings.

<connectionstrings><add name="elmah-mongodb" connectionstring="mongodb://localhost:27666/elmah"></add></connectionstrings>

La cadena de conexión empieza por mongodb, seguida por el servidor (en este caso localhost), el puerto, y para finalizar, la base de datos. Si la base de datos elmah no existe, se creará automáticamente.

Para almacenar los errores detectados en la página, ELMAH creará también una colección llamada Elmah. Esta colección será de tipo Capped. Estas colecciones son muy útiles cuando solo necesitamos almacenar los datos más recientes, por lo que son ideales para guardar datos de logs.

Las colecciones capped, tienen un tamaño máximo. Si queremos también pueden tener un número máximo de documentos. Cuándo se alcance uno de estos límites, se borrarán los documentos más antiguos. Así se consigue espacio para añadir los nuevos.

Como ELMAH crea automáticamente la colección, no podemos establecer un tamaño máximo personalizado (o número máximo de documentos) de forma directa. Pero esto es sencillo de corregir. Bastará con borrar la colección y volverla a crear desde la consola de MongoDB con un comando como el siguiente:

db.createCollection("Elmah", {capped:true, size:10485760, max:300});

Como podéis ver, estamos creando una nueva colección, con un tamaño máximo size en bytes, y un número max de documentos. En este caso 300 documentos.

Simulando un error para probar ELMAH

Para probar que todo funciona, vamos a simular un error. Con una aplicación de MVC 5 sin demasiada funcionalidad, es algo tan sencillo como introducir una URL que no existe. Eso generará un error 404 que será capturado por ELMAH.

El error quedará registrado en la colección Elmah. Si hacemos un find podremos ver los errores que se han producido. Por ejemplo:

{
    "_id" : ObjectId("533d2766c8596f27b0504823"),
    "ApplicationName" : "/LM/W3SVC/16/ROOT",
    "host" : "CYLON-MACHINE",
    "type" : "System.Web.HttpException",
    "source" : "System.Web.Mvc",
    "message" : "No se encuentra el controlador de la ruta de acceso '/test' o no implementa IController.",
    "detail" : "System.Web.HttpException (0x80004005): No se encuentra el controlador de la ruta de acceso '/test' o no implementa IController.\r\n   en System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)\r\n   en System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)\r\n   en System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)\r\n   en System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)\r\n   en System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)\r\n   en System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)\r\n   en System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()\r\n   en System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)",
    "user" : "",
    "time" : ISODate("2014-04-03T09:18:28.551Z"),
    "statusCode" : 404,
    "webHostHtmlMessage" : "",
    "serverVariables" : [ 
        [ 
            "ALL_HTTP", 
            "HTTP_CONNECTION:keep-alive\r\nHTTP_ACCEPT:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nHTTP_ACCEPT_ENCODING:gzip,deflate,sdch\r\nHTTP_ACCEPT_LANGUAGE:es-ES,es;q=0.8,en;q=0.6\r\nHTTP_HOST:localhost:63972\r\nHTTP_USER_AGENT:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36\r\n"
        ], 
        [ 
            "ALL_RAW", 
            "Connection: keep-alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: es-ES,es;q=0.8,en;q=0.6\r\nHost: localhost:63972\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36\r\n"
        ], 
        [ 
            "APPL_MD_PATH", 
            "/LM/W3SVC/16/ROOT"
        ],
        [ 
            "HTTP_CONNECTION", 
            "keep-alive"
        ], 
        [ 
            "HTTP_ACCEPT", 
            "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
        ], 
        [ 
            "HTTP_ACCEPT_ENCODING", 
            "gzip,deflate,sdch"
        ], 
        [ 
            "HTTP_ACCEPT_LANGUAGE", 
            "es-ES,es;q=0.8,en;q=0.6"
        ], 
        [ 
            "HTTP_HOST", 
            "localhost:63972"
        ], 
        [ 
            "HTTP_USER_AGENT", 
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36"
        ]
    ],
    "queryString" : null,
    "form" : null,
    "cookies" : null
}

El JSON devuelto tiene más datos en el campo array serverVariables, pero lo he reducido un poco para que sea más legible.

Conclusiones

ELMAH es una herramienta muy potente para controlar los errores de nuestras aplicaciones ASP.NET. Pero además con MongoDB nos podemos aprovechar de la utilidad de las colecciones capped, que encajan perfectamente en este tipo de herramientas.



Recuerda que puedes ver el índice del tutorial y acceder a todos los artículos de la serie desde aquí.



¿Quiéres que te avisemos cuando se publiquen nuevas entradas en el blog?

Suscríbete por correo electrónico o por RSS