miércoles, 14 de noviembre de 2018

LoggerFactory

En un reciente proyecto en el que he estado trabajando este año, necesité un buen sistema de log (bitácora o entradas en un diario), como de costumbre busqué si había alguno para Xojo/Real basic, al no encontrar uno que fuera flexíble y no "encadenado" a un particular componente o recurso, decidí crear mi propio logger: LoggerFactory.

A propósito, en computación un Logger es un software que genera mensajes y opcionalmente los almacena para reportar o analizar luego, puede encontrar información de sus inicios aquí y más aquí, un buen ejemplo de donde o para qué utilizarlo pueden ser los logs de servidores, en especial los servidores web; ellos almacenan mucha información de los clientes para después analizarlos con servicios muy comunes en web-hostings. A propósito, talvez se preguntaran: para que utilizar los logs de servidor si tengo otras herramientas como google analitics? pues esas otras herramientas funcionan sólo en navegadores de "buen comportamiento" como chrome, pero existen miles de herramientas para acceder a servidores web para sólo ver las cabeceras del archivo html o sin sus links, imágenes, javascripts, css, etc, o cuando escribe un "downloader" usando HTTPSocket.

Como regla general se deben monitorear los logs para optimizar, corregir o defenderse contra ataques, de ahi la importancia de un buen Logger.


Debería cumplir estas (entre otras) características:
  1. Fácil de usar
  2. Extensible
  3. Asincrónico
  4. Varias salidas por nivel
  5. Personalizar formato de salida

Basandome an algunos muy buenos loggers, entre otros java.util.logging y MacOS Logging cree LoggerFactory, (existe LoggerFactory para java, pero es más un wrapper (envoltorio) a otros loggers) el cual resultó ser bastante sencillo y corto de codificar, en realidad menos de 900 líneas de código, con las características que quería para mi proyecto y además me pudiera servir para cualquier otro proyecto.

Ejemplo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  Dim logger As LoggerFactory.Logger= LoggerFactory.Get(CurrentMethodName)
  '...
  logger.Info "this is a info"
  '...
  logger.Debug "this is a debug"
  '...
  logger.Trace "this is a trace"
  '...
  logger.Error "this is a error"
  '...
  logger.Warn "this is a warning"
  '...
  logger.Fatal "this is a fatal"


LoggerFactory usa estos niveles: ALL, DEBUG, ERROR, FATAL, INFO, TRACE, WARN


Por defecto, LoggerFactory está configurado para consola y System.DebugLog, Funciona sin ninguna modificación en proyectos Consola y Desktop, no he probado en web. Puede configurarse en cualquier momento de la aplicación pero lo normal es hacerlo al inicio, ejemplo:


1
2
3
  LoggerFactory.Adders.Append New LoggerFactory.ConsoleAdder(LoggerFactory.TypeLevel.ALL)

  LoggerFactory.Adders.Append New LoggerFactory.FileLogAdder(LoggerFactory.TypeLevel.ALL)

En el anterior código, he configurado un "Adder" para consola y otro para archivo, aquí es donde explico lo de Adders, Adders es la forma para "adicionar" salidas (mensajes) configurando el nivel, o si es salida a un archivo, características del archivo, por ejemplo. Los Adders básicos son:

  • ConsoleAdder: Salidas por consola (sólo en proyectos consola, obiamente)
  • SystemDebugLogAdder: El típico System.DebugLog
  • SystemLogAdder: El System.Log
  • FileLogAdder: Salidas a un archivo

Lo interesante es que podemos, por ejemplo, configurar salidas de tipo DEBUG a SystemDebugLogAdder, además salidas de tipo ERROR a un archivo, cambiar el formato de salida o inclusive crear mis propios Adders, lo único que tengo que hacer es crear una sub-clase de LoggerFactory.Adder y sobreescribir el método "Log"; con eso puedo crear una salida a, por ejemplo una base de datos o un servicio web; sólo configurando los Adders, sin cambiar nada más.


Una característica interesante de los Adders es que puedo configurar el formato de salida, así:


1
2
3
  Dim addFile As New LoggerFactory.FileLogAdder(LoggerFactory.TypeLevel.ALL)

  addFile.Format= "%d"+ SEP+ "%t"+ SEP+ "%l"+ SEP+ "%c"+ SEP+ "[%a]"+ SEP+ "%m"

Donde las etiquetas pueden ser:

%d: Date
%t: Time
%l: Level
%c: Counter
%u: SubSystem
%a: Category
%i: ID
%o: ObjectID
%e: EventType
%m: Message

Y "SEP" es una propiedad del adder, por defecto es TAB [Chr(9) en ASCII] y también se puede configurar.


Además el FileLogAdder puede ser configurado con "roll over" o re-iniciar, con la propiedad FileLogAdder.FileType y puede ser: al mismo archivo, anual, mensual, diario, por hora, o por el tamaño (por ejemplo que el archivo log sea de máximo 10M (10 megabytes) de tamaño y automáticamente asigne nombres secuenciales a los archivos)


Por último, hablemos de "Formatter", cuando escribimos mensajes, normalmete necesitamos adicionar valores de variables (números, por ejemplo) y darles un formato, por ejemplo en una variable llamada "miVariable" tenemos un valor de 1250 y queremos mostar un texto como: "Valor: 1,250", en xojo existe la función Str() o Format() y podemos asignar a una variable de tipo String, sin embargo puedo hacerlo también de la siguiente manera:


1
2
3
Dim miVariable As Single= 1250

logger.Debug "Valor: %-###,###.##f", miVariable // Salida: "Valor: 1,250"

Con la ventaja que los textos son más legibles y pueden ser almacenados en una constante para, por ejemplo, localizarlos en otro idioma.

Otros ejemplos:


1
2
3
4
5
6
  Dim n1 As UInt64= 202002021101
  Dim n2 As Double= 12.3456
  Dim n3 As Single= -12345.6789
  Dim s1 As String= "world"
  logger.Debug "i = %2d, n1= %u, n2= %3.5f, hello %s, single= %-###,##0.0###f - %{pub}s", _
  i, n1, n2, s1, n3, "test"

Las etiquetas pueden ser:

%d: Signed integers
%u: Unsigned integers
%f: Signed doubles/singles
%s: Strings


Otras características interesantes son el manejo de Sub-Sistemas y la precisión de tiempo de hasta nanosegundos, pero eso quedará para otra ocasión, si le interesa o tiene alguna sugerencia o pregunta, por favor contácteme o comente. hasta la próxima.



Gracias a Javier Mendéz por sus recomendaciones.





No hay comentarios:

Publicar un comentario