
Compartir:
Antiguo desarrollador .NET Advocate @Vonage, ingeniero de software poliglota full-stack, AI/ML
Registro adaptable de bibliotecas con Microsoft.Extensions.Logging
Cómo aprendí a dejar de preocuparme y a amar el registro
En mi carrera, he trabajado en diferentes proyectos .NET de mediana a gran escala. En cada proyecto he visto un tipo diferente de registrador, ¡y normalmente todos ellos utilizaban más de un registrador!
Normalmente, la historia es algo así: "Al principio no podíamos decidir qué registrador queríamos usar, así que construimos uno propio. Luego nos dimos cuenta de que la forma en que habíamos implementado el registro no era la más eficiente, así que cambiamos a X logger a medida que la aplicación crecía. No queríamos volver atrás y eliminar el antiguo registrador porque eso implicaría tocar todos los archivos de nuestra solución, así que simplemente lo eliminamos de los lugares donde el antiguo registrador estaba causando problemas, y a partir de ahora vamos a utilizar X logger para todo".
Como ya he dicho, se trata de un problema sorprendentemente común, que podemos evitar abstrayendo el registrador del registro.
Inicio de sesión en la biblioteca Nexmo .NET
Recientemente he estado echando un vistazo a Nexmo's .NET Server SDK y he estado limpiando algunas cosas. Mientras lo hacía me di cuenta de que nuestro framework de logging LibLog ha sido obsoleto.
Esta herramienta era genial, ya que abstraía el registrador de la operación de registro. Permitía a cualquiera que desarrollara con nuestro SDK traer su propio logger. Siempre y cuando su registrador fuera compatible, podría tener el registrador del SDK en su registrador de elección sin ninguna intervención (que en realidad podría ser un pro o un contra dependiendo de cómo se mire).
Debido a que LibLog está obsoleto, me vi obligado a buscar en otra parte una herramienta de registro que satisficiera nuestras necesidades. Afortunadamente, no tuve que buscar mucho.
Avanzando con Microsoft.Extensions.Logging
El (relativamente) nuevo Microsoft.Extensions.Logging ha dado en el clavo en cuanto a funcionalidad. Con el paquete de extensión, puede simplemente instalar el paquete NuGet, junto con cualquier marco de registro que haya elegido utilizar, configurar una fábrica y crear el registrador.
Esto se adapta a nuestro caso de uso, ya que no queremos que nuestros registros se entrecrucen automáticamente con los de nuestros usuarios y, al mismo tiempo, no queremos dictar a nuestros usuarios exactamente dónde, cómo y con qué marco se capturarán los registros.
Así que ahora con nuestro próximo lanzamiento de la versión principal, 5.0.0, usted será capaz de activar cualquier nivel o categoría que desee dentro del SDK dinámicamente simplemente intercambiando la Fábrica Logger en el SDK.
Creación de registradores con Microsoft.Extensions.Logging
Construir el proveedor de registros
Dos componentes sustentan Microsoft.Extensions.Logging: ILoggerFactory y ILogger. La fábrica genera los registradores y el registrador realiza el registro.
Estos dos componentes se utilizan en la clase LogProvider para permitirnos crear un logger completamente dinámico y extensible para la librería, permitiendo al desarrollador traer su propio logger.
public static class LogProvider
{
private static IDictionary<string, ILogger> _loggers = new Dictionary<string, ILogger>();
private static ILoggerFactory _loggerFactory = new LoggerFactory();
public static void SetLogFactory(ILoggerFactory factory)
{
_loggerFactory?.Dispose();
_loggerFactory = factory;
_loggers.Clear();
}
public static ILogger GetLogger(string category)
{
if (!_loggers.ContainsKey(category))
{
_loggers[category] = _loggerFactory?.CreateLogger(category)?? NullLogger.Instance;
}
return _loggers[category];
}
}En nuestro modelo, creamos una clase estática llamada LogProvider con dos campos: _loggers, un diccionario que contiene el logger para cada categoría, y _loggerFactory, que construye los loggers.
También hay dos métodos: SetLogFactory, que se deshace del antiguo LogFactory y establece la fábrica de logs en la nueva fábrica de logs pasada, y GetLogger, que comprueba los _loggers para ver si el logger de esa categoría ha sido creado, y crea uno si no lo ha hecho.
Uso del proveedor de registros
Ahora al inicio de cualquier método del que queramos hacer un log simplemente tenemos que llamar a GetLogger con la categoría apropiada:
var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); Registro
A partir de aquí simplemente tenemos que utilizar el logger como cualquier otro logger que hayamos visto antes. Por ejemplo:
logger.LogInformation("Available authentication: {0}", string.Join(",", authCapabilities));Esto registrará como información las capacidades de autenticación disponibles en cualquier formato que haya proporcionado a su registrador.
Configuración de registradores adaptativos
Ahora que hemos cubierto la creación y utilización de los registradores, vamos a ver cómo configurarlos para hacer lo que nos gustaría.
Seleccione su proveedor de registros
Una de las ventajas de Microsoft.Extensions.Logging es que es independiente del proveedor de registros que utilices. Mientras el proveedor de registro implemente la interfaz ILogProvider puede ser lo que quiera. Y desde la perspectiva del desarrollador que intenta aprovecharlo, es incluso más sencillo. La mayoría de los principales proveedores de registro de terceros que es probable que utilices (por ejemplo, Log4Net, Serilog, NLog, etc.) tienen paquetes de extensión que hacen que añadir el registrador deseado sea sencillo.
Registro en la consola con Serilog
Para demostrar cómo podemos construir estos loggers, vamos a tomar el ejemplo de registro de la consola con Serilog. Para ello se creará una necesidad de los siguientes paquetes NuGet:
Microsoft.Extensions.Logging
Serilog.Extensions.Logging
Serilog.Sinks.Console
A continuación hará lo siguiente:
Crear un nuevo LoggerFactory que será lo que utilicemos para crear
Crear un nuevo LoggerConfiguration que establecerá la configuración Serilog
Llamar a la función AddSerilog en la fábrica
Crear un registrador de la categoría 'test
Cerrar sesión
Encadenados, esto parece:
var log = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm} [{Level}] ({Name:l}) {Message}\n")
.CreateLogger();
var factory = new LoggerFactory();
factory.AddSerilog(log);
ILogger logger = factory.CreateLogger("test");
logger.LogInformation("Hello world");Muy limpio y sencillo.
Ahora para interactuar con el Nexmo SDK, en lugar de crear un logger después de configurar la fábrica, simplemente establece el LogFactory en el Log Provider a la fábrica de logs que creaste y agregaste a Serilog, y verás el logging venir a través del SDK.
var log = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm} [{Level}] ({Name:l}) {Message}\n")
.CreateLogger();
var factory = new LoggerFactory();
factory.AddSerilog(log);
LogProvider.SetLogFactory(factory);Et Voila-nuestro propio registrador de bibliotecas altamente configurable.
Beneficios
Microsoft.Extensions.Logging nos permite evitar el escenario de pesadilla de empezar un proyecto usando un logger y necesitar, por cualquier razón, cambiar a otro.
Si quieres usar tu propio logger puedes hacerlo, incluso usando las Extensiones de Logging. Todo lo que necesitas hacer es implementar la interfaz ILogProvider con el logger que quieras usar y añadirlo a la fábrica.