El logging siempre ha sido una característica fundamental en toda aplicación, ya que da información importante sobre errores, funcionamiento, auditoría, uso de la aplicación entre otros aspectos, y si bien existen diversas herramientas para ello, ultimamente he estado trabajando con Serilog y de verdad que me ha gustado bastante.


Serilog provee una forma bastante robusta para guardar los logs de forma estructurada (y si, no como en muchos casos un montón de información que luego es bastante compleja de manejar), adicionalmente, por medio de los Sinks que son basicamente conectores a sistemas de almacenamiento es posible configurar en dónde se quiere guardar la información (archivos de texto, bases de datos, Azure DocumentDB, etc).

Y bueno, iniciemos... lo primero es añadir Serilog al proyecto, para ello por Nuget añadimos los dos siguientes paquetes:

Serilog

Serilog.Extensions.Logging

Ahora, en la clase Startup en el constructor configuramos Serilog:


Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .Enrich.FromLogContext()
                .CreateLogger();

Y en el método Configure, añadimos Serilog al loggerFactory con la siguiente línea:


loggerFactory.AddSerilog();

El siguiente paso es ir al HomeController, declarar la dependencia del logger e inyectarla en el constructor utilizando el mecanismo de inyección de dependencias provisto por ASPNET Core, y logueamos un pequeño texto en la acción Index:


using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace MvcCoreAndSerilog.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            _logger.LogInformation("Log information using Serilog :)");
            return View();
        }
    }
}


Y en este momento la pregunta es...y dónde puedo ver ese mensaje?? Bueno, anteriormente comenté que Serilog cuenta con un mecanismo llamemosle conector conocido como Sink el cual permite definir en donde sequiere almacenar los logs (la lista de Sinks disponibles la puedes ver en: https://github.com/serilog/serilog/wiki/Provided-Sinks), y uno de los puntos interesantes es que es posible configurar más de 1 Sinks, pero iniciemos con uno sencillo para escribir en un archivo de texto (si, el clásico :)), para ello añadimos la siguiente referencia utilizando Nuget:

Serilog.Sinks.RollingFile

Y ahora es solo conectar el Sinks en Serilog, así que de nuevo en la clase Startup vamos al constructor, y en la configuración de Serilog, antes de llamar .CreateLogger() utilizando el método WriteTo. le decimos que Sinks usar, en este caso RollingFile y la ruta del archivo:


Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .Enrich.FromLogContext()
    .WriteTo.RollingFile(@"C:\temp\log.log")
    .CreateLogger();

Vuelvan a probar, y abran el archivo generado y allí podrán ver todo lo que se está logueando.

Ahora, vamos a añadir otro Sinks, en este caso el de Azure DocumentDB, así que de nuevo por Nuget añadimos:

Serilog.Sinks.AzureDocumentDB

Y de nuevo, en la configuración del logger, por medio del método WriteTo. conectamos/configuramos el Sinks de DocumentDB, en este caso utilizando el URI del servicio y la primary key que puedes obtener en el portal de Azure:

DocumentDB Keys

Y en la configuración del logger:


Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .Enrich.FromLogContext()
    .WriteTo.RollingFile(@"C:\temp\log.log")
    .WriteTo.AzureDocumentDB("URI", "PRIMARY_KEY")
    .CreateLogger();

Ejecutando de nuevo la aplicación, y validando en el portal de Azure, en el servicio de DocumentDB, automáticamente se ha creando una colección con el nombre Logs y una base de datos llamada Diagnostics en dónde se están almacenando los logs, en este caso como documentos (recuerda que DocumentDB es una base de datos NoSQL de tipo documental), podemos el Query Explorer para ver la información:

DocumentDB Query Explorer

Bien, ya sabemos como añadir un Sinks a Serilog, pero... y que más podemos hacer con el?

Pues no solo tenemos la posibilidad de hacer log de información, tenemos disponible diferentes eventos para guardar como:

  • LogError
  • LogCritical
  • LogDebug
  • LogTrace
  • LogWarning
  • LogInformation

Adicionalmente, es posible loguear objetos, y Serilog se encarga de "serializar" correctamente nuestro objeto, para verlo en acción he creado una sencilla clase llamada Product con tres propiedades:


public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Category { get; set; }
}

Y ahora, en la acción Index de nuestro HomeController creamos un objeto de tipo Product y lo añadimos al log:


public IActionResult Index()
{
    var product = new Product
    {
        Id = 1,
        Name = "Serilog",
        Category = "Logging"
    };

    _logger.LogInformation("Log information using Serilog :)");
    _logger.LogInformation("Product to log {@Product}", product);
    return View();
}

Como no hace parte del post, te recomiendo que revises la documentación de Serilog para entender correctamente como se guarda el objecto: Serilog Structured Data

Bueno, luego de ejecutar la aplicación, vamos a DocumentDB, buscamos el registro que acabamos de guardar y vean lo bien estructurado que se ha guardado el objeto Product:

DocumentDB

Listo, ya tenemos configurado Serilog con dos Sinks en ASPNET Core.

Saludos.


Y no se olviden de compartir :)