2.0.0-rc.1 • Published 5 years ago

@nalv/logger v2.0.0-rc.1

Weekly downloads
1
License
ISC
Repository
github
Last release
5 years ago

@nalv/logger

Un logger de uso general. Desarrollado en Typescript y publicado en npmjs.com compilado junto a las definiciones del código (files.d.ts).

npm version

Tabla de contenidos

Uso

/* Javascript */
const nalvLogger = require('@nalv/logger')
//const { Logger, SimpleFormat, JSONFormat, ConsolePlugin, FilePlugin } = require('@nalv/logger')

/*
 * Crea la instancia del logger
 * */
const logger = new nalvLogger.Logger({
  level: 'debug', // Nivel con el que se 
  //levels: [...], // Ocupar los niveles por defecto
  //format: new nalvLogger.SimpleFormat({ datetime: true, console: { colors: false} }), // Para plugins sin "format"
  plugins: [
  new nalvLogger.ConsolePlugin({
    //level: 'debug', // Se hereda
    format: new nalvLogger.SimpleFormat({
      datetime: false,
      console: {
        colors: true
      }
    })
  }),
    new nalvLogger.FilePlugin({
    level: 'warning', // Se cambia el nivel desde donde se inician a guardar los logs en este plugin
      filename: path.join(__dirname, 'logs.txt'),
      format: new nalvLogger.JSONFormat({
        beautify: false
      })
    })
  ]
})
/* Typescript / ES6 (quitar el tipado) */
import { Logger, SimpleFormat, JSONFormat, ConsolePlugin, FilePlugin } from '@nalv/logger'

/*
 * Crea la instancia del logger
 * */
const logger: Logger = new Logger({
  level: 'debug', // Nivel con el que se 
  //levels: [...], // Ocupar los niveles por defecto
  //format: new SimpleFormat({ datetime: true, console: { colors: false} }), // Para plugins sin "format"
  plugins: [
  new ConsolePlugin({
    //level: 'debug', // Se hereda
    format: new SimpleFormat({
      datetime: false,
      console: {
        colors: true
      }
    })
  }),
    new FilePlugin({
    level: 'warning', // Se cambia el nivel desde donde se inician a guardar los logs en este plugin
      filename: path.join(__dirname, 'logs.txt'),
      format: new JSONFormat({
        beautify: false
      })
    })
  ]
})

Logging

En @nalv/logger el logger corresponde a un objeto para contener la instancia que se usará gestionar el logging en la aplicación.

Crear un logger

Para crear una instancia de logger, debes usar:

/* Javascript */
const nalvLogger = require('@nalv/logger')
//const { Logger, SimpleFormat } = require('@nalv/logger')
const logger = new nalvLogger.Logger({
  format: new nalvLogger.SimpleFormat(),
  level: 'debug'
})
/* Typescript / ES6 (quitar el tipado) */
import { Logger, SimpleFormat } from '@nalv/logger'

const logger: Logger = new Logger({
  format: new SimpleFormat(),
  level: 'debug'
})

Donde el objeto new Logger({...}) tiene un formato del tipo:

Llave (key)TipoValor inicialDescripción
levelsArray<level>Niveles por defectoLos niveles de logs que tendrá.
levelString'debug'Desde que nivel se registrarán los logs.
formatBaseFormatnew BaseFormat()Formato que se usará para mostrar los logs.
pluginsArray<plugin>[ new ConsolePlugin() ]Plugins que usará el logger.

Usar un logger

Para usar un logger simplemente se debe llamar al level desde la instancia creada.

// Forma de uso
log(level: string, message: string, data?: object, ...args: any[])
levelName(message: string, data?: any, ...args: any[])
info(message: string, data?: any, ...args: any[])
// Mismo resultado
logger.log('info', 'Registro para los plugins registrados.', { obj: 'info adicional (para plugins y formats)' }, ...args)
logger.levelName('Registro para los plugins registrados.', { obj: 'info adicional (para plugins y formats)' }, ...args)
logger.info('Registro para los plugins registrados.', { obj: 'info adicional (para plugins y formats)' }, ...args)
ParametroValor inicialDescripciónFunción
levelundefinedNivel para el que se generará el log.logger.log
messageundefinedMensaje que se enviará al log.logger.loglogger.levelName
data?nullInformación adicional que se le enviará al log.Esta información la recibe el plugin y el formater, por lo que la puede ocupar para generar condiciones.logger.loglogger.levelName
...args[]Información adicional. Al igual que data esta información la recibirán los plugins y formaters.logger.loglogger.levelName

Niveles

Los niveles de log son esas "paredes" que se van "saltando" cuando se necesita llegar mas lejos. Osea, si se tienen 4 paredes (niveles):

  • pared1 (level1)
  • pared2 (level2)
  • pared3 (level3)
  • pared4 (level4)

Al saltar la pared4, también se saltarán las paredes inferiores 1-2-3, pero si se salta la pared2, solo se saltarán 1 y 2 (que son sus inferiores).

Niveles por defecto

Cada vez que se crea una instancia de logger, éste tiene un argumento para establecer los niveles que tendrá. En caso de que no se envíen (como es el valor por defecto) se usarán los que establece el paquete:

levels: [
  { code: 0, name: 'Emergency', alias: 'emergency', extra: { color: 'magenta'} },
  { code: 1, name: 'Alert', alias: 'alert', extra: { color: 'red' } },
  { code: 2, name: 'Critical', alias: 'critical', extra: { color: 'red' } },
  { code: 3, name: 'Error', alias: 'error', extra: { color: 'red' } },
  { code: 4, name: 'Warning', alias: 'warning', extra: { color: 'yellow' } },
  { code: 5, name: 'Notice', alias: 'notice', extra: { color: 'cyan' } },
  { code: 6, name: 'Information', alias: 'info', extra: { color: 'green' } },
  { code: 7, name: 'Debug', alias: 'debug', extra: { color: 'grey' } }
],

Los niveles por defecto para los loggers estan definidos en RFC 5424.

Niveles personalizados

También es posible crear niveles personalizados, para ello se debe seguir el formato:

{ code: 0, name: 'Nombre nivel', alias: 'newlevel', extra: { color: 'magenta'} }
Llave (key)Descripción
codeEl código que tendrá el nuevo nivel. Si se ejecuta un log con este código, se ejecutarán los plugins que tengan igual o menos código.
nameNombre del código.
aliasAlias del código. Además, es el nombre de la función que se usará con el logger: new Logger().alias.
extra.colorColor que representará al nivel. Ciertos plugins pueden utilizarlo (como ConsolePlugin).Los colores disponibles se rigen por el paquete colors en npm.

Donde su inserción sería en la creación del logger:

/* Javascript */
const nalvLogger = require('@nalv/logger')
//const { Logger, SimpleFormat } = require('@nalv/logger')
const logger = new nalvLogger.Logger({
  format: new nalvLogger.SimpleFormat(),
  level: 'debug',
  levels: [
    { code: 0, name: 'Emergency', alias: 'emergency', extra: { color: 'magenta'} },
    { code: 1, name: 'Alert', alias: 'alert', extra: { color: 'red' } },
    { code: 2, name: 'Critical', alias: 'critical', extra: { color: 'red' } },
    { code: 3, name: 'Error', alias: 'error', extra: { color: 'red' } },
    { code: 4, name: 'Warning', alias: 'warning', extra: { color: 'yellow' } },
    { code: 5, name: 'Notice', alias: 'notice', extra: { color: 'cyan' } },
    { code: 6, name: 'Information', alias: 'info', extra: { color: 'green' } },
    { code: 7, name: 'Debug', alias: 'debug', extra: { color: 'grey' } }
  ],
})
/* Typescript / ES6 (quitar el tipado) */
import { Logger, SimpleFormat } from '@nalv/logger'

const logger: Logger = new Logger({
  format: new SimpleFormat(),
  level: 'debug',
  levels: [
    { code: 0, name: 'Emergency', alias: 'emergency', extra: { color: 'magenta'} },
    { code: 1, name: 'Alert', alias: 'alert', extra: { color: 'red' } },
    { code: 2, name: 'Critical', alias: 'critical', extra: { color: 'red' } },
    { code: 3, name: 'Error', alias: 'error', extra: { color: 'red' } },
    { code: 4, name: 'Warning', alias: 'warning', extra: { color: 'yellow' } },
    { code: 5, name: 'Notice', alias: 'notice', extra: { color: 'cyan' } },
    { code: 6, name: 'Information', alias: 'info', extra: { color: 'green' } },
    { code: 7, name: 'Debug', alias: 'debug', extra: { color: 'grey' } }
  ],
})

Formatos

Los "formats" o formatos son los objetos e instancias de éstos que son los encargados de darle partes al logging. Es posible usar los formats que vienen incluidos en el paquete, además también se pueden crear formats personalizados en caso de que los disponibles no cumplan con los requerimientos del proyecto.

La construcción de la instancia para un formato se establecería así (ejemplo en base al formato JSONFormat):

/* Javascript */
const nalvLogger = require('@nalv/logger')
//const { Logger, JSONFormat } = require('@nalv/logger')

// En la creación del logger
const logger = new nalvLogger.Logger({
  format: new nalvLogger.JSONFormat(),
  level: 'debug'
})

// Una vez ya creado el logger, junto a un plugin
logger.addPlugin(
  new nalvLogger.ConsolePlugin({
    format: new nalvLogger.JSONFormat()
  })
)
/* Typescript / ES6 (quitar el tipado) */
import { Logger, JSONFormat, ConsolePlugin } from '@nalv/logger'

const logger: Logger = new Logger({
  format: new JSONFormat(),
  level: 'debug'
})

// Una vez ya creado el logger, junto a un plugin
logger.addPlugin(
  new ConsolePlugin({
    format: new JSONFormat()
  })
)

Formato: JSON

Este formato transforma a JSON la información recibida por el logger.

// Agregar el format
logger.addPlugin(new ConsolePlugin({ format: new JSONFormat({ beautify: false }) }))
// Log
logger.notice('Actualizando la información del sistema.')
// Resultado
{"datetime":"2018/02/05 06:32:53","level":"notice","message":"Actualizando la información del sistema."}
// Agregar el format
logger.addPlugin(new ConsolePlugin({ format: new JSONFormat({ beautify: true }) }))
// Log
logger.notice('Actualizando la información del sistema.')
// Resultado
{
  "datetime": "2018/02/05 06:48:06",
  "level": "notice",
  "message": "Los paquetes fueron actualizados correctamente!"
}

Opciones de construcción de new JSONFormat({ }): | Llave (key) | Valor inicial | Descripción | |-|-|-| | beautify | false | Transformar a un formato JSON ordenado. |

Formato: Simple

Mostrar el log de una manera simple y entendible.

// Agregar el format
logger.addPlugin(new ConsolePlugin({ format: new SimpleFormat({ datetime: false }) }))
// Log
logger.notice('Actualizando la información del sistema.')
// Resultado
[  NOTICE   ] Actualizando la información del sistema!
// Agregar el format
logger.addPlugin(new ConsolePlugin({ format: new SimpleFormat({ datetime: true }) }))
// Log
logger.notice('Actualizando la información del sistema.')
// Resultado
[2018/02/05 06:57:10] [  NOTICE   ] Actualizando la información del sistema.

Opciones de construcción de new SimpleFormat({ }): | Llave (key) | Valor inicial | Descripción | |-|-|-| | datetime | true | Mostrar la fecha y hora en que fue enviado el log. | | console.colors | false | Mostrar colores en los mensajes.Si se establece en true pintará el texto según el color correspondiente al nivel. |

Crear formatos personalizados

Si se requiere de un formato con características que no tengan los que trae el paquete, es posible crear sus propios formatos. Esto se hace mediante el objeto BaseFormat.

Ejemplo

Un formato básico (este ejemplo agrega espacios al principio de la cadena enviada en los logs), sería:

/* Javascript */
const nalvLogger = require('@nalv/logger')
//const { BaseFormat, Message } = require('@nalv/logger')

class PersonalFormat extends nalvLogger.BaseFormat {

  options = {}
  
  constructor(options) {
    super()
    this.options.padStart = options.padStart || 16
  }

  format(data) {
    data.message = data.message.padStart(this.options.padStart)
    return data
  }

}

exports.format = PersonalFormat
/* Typescript / ES6 (quitar el tipado y ciertas características como las interfaces, entre otras) */
import { BaseFormat, Message } from '@nalv/logger'

export interface PersonalFormatOptions {
  padStart?: number,
}

export class PersonalFormat extends BaseFormat {

  // Opciones recibidas
  options: PersonalFormatOptions = {}

  constructor(options: PersonalFormatOptions = {}) {
    super()
    this.options.padStart = options.padStart || 16
  }

  format(data: Message): Message {
    data.message = data.message.padStart(this.options.padStart)
    return data
  }

}

Se debe extender de la clase BaseFormat. El constructor será como cualquier clase, incluyendo las opciones que tendrá el nuevo "format" entre sus parámetros (esto es libre, no tiene mucho que ver con la creación en si de un format.

Método format

Para que el nuevo formato pueda hacer una transformación con la información recibida, debe tener un método público llamado format, esta función recibe un parámetro que corresponde con la información recibida al ejecutar un log logger.info('prueba'). La información que contiene este argumento es un objeto con: | Llave (key) | Descripción | Ejemplo | Valor según el ejemplo | |-|-|-|-| | level | Nivel que se esta imprimiendo | logger.info('imprimir') | 'info' | | message | Mensaje que se esta imprimiendo | logger.info('imprimir') | 'imprimir' | | data | Información adicional enviada | logger.info('mensaje', {mas: 'info'}) | {mas: 'info'} | | args | Argumentos adicionales enviados | logger.info('', {}, 'otros', {msg: 'argumentos'}) | ['otros', {msg: 'argumentos'}] |

Éste método debe retornar un objeto con el mismo formato del primer argumento, pero con la información ya modificada. Este objeto lo recibirá el plugin y hará uso de ella según corresponda.

Uso

Para usar el formato personalizado debe ser llamado como los "nativos" del paquete:

/* Javascript */
const nalvLogger = require('@nalv/logger')
const personalFormat = require('./personal-format').format

const logger = new nalvLogger.Logger({
  format: new PersonalFormat({ padStart: 32 }),
  level: 'debug'
})
/* Typescript / ES6 (quitar el tipado) */
import { Logger } from '@nalv/logger'
import { PersonalFormat } from './personal-format'

const logger: Logger = new Logger({
  format: new PersonalFormat({ padStart: 32 }),
  level: 'debug'
})

Plugins

Los "plugins" son los sujetos encargados de utilizar la información enviada cuando se ejecuta un log, para que quede en un registro según el plugin haya sido programado.

Todos los plugins tienen una configuración base que se hereda de BasePlugin: | Llave (key) | Descripción | |-|-| | level | Desde que nivel se comenzarán a ejecutar los logs para este plugin. | | format | El formato que tendrán los logs al ejecutarse en este plugin. |

Plugin: Console

Registrar los logs en la consola donde se ejecuta el proceso de la aplicación.

Opciones de construcción de new ConsolePlugin({ }): | Llave (key) | Descripción | |-|-| | - | Este plugin no tiene opciones adicionales. Solo se limita a las opciones que hereda de BasePlugin, ver aquí.

Plugin: File

Registrar los logs en archivos.

Opciones de construcción de new FilePlugin({ }): | Llave (key) | Descripción | |-|-| | filename | Path del archivo que se usará para el registro de los logs. |

Crear plugins personalizados

Ejemplo

Para el ejemplo recrearemos el plugin ConsolePlugin "nativo" del paquete, que sirve para mostrar los logs en la consola donde se este ejecutando el proceso de la aplicación.

/* Javascript */
const nalvLogger = require('@nalv/logger')

class ConsolePlugin extends nalvLogger.BasePlugin {
  
  constructor(setting, additional) {
    super(setting, additional)
  }

  log(data) {
  console.log(data.message)
  }

}

exports.plugin = ConsolePlugin
/* Typescript / ES6 (quitar el tipado) */
import { BasePlugin, Message, PluginSetting } from '@nalv/logger'

export class ConsolePlugin extends BasePlugin {

  constructor(setting: PluginSetting = {}, additional?: any) {
    super(setting, additional)
  }

  log(data: Message) {
    console.log(data.message)
  }

}

Se debe extender de la clase BasePlugin.

Método constructor

A diferencia de los formats, los plugins deben enviar información a su clase parent BasePlugin ya que todos los plugins tienen una base estricta de funcionamiento que parte desde el constructor.

Los argumentos que recibe son mínimo el primero, que corresponde con la configuración que tendrá el plugin. Por ejemplo, para el plugin FilePlugin este argumento incluiría filename que representa al path del archivo que se usará para guardar los logs.

Además de esto, el primer argumento puede recibir información "nativa" de todos los plugins (osea, que todos los plugins deben tener, por consecuencia de BasePlugin. Para ver estos argumentos, mira aquí.

Para el caso de FilePlugin, incluiríamos la configuración del plugin: | Llave (key) | Descripción | |-|-| | filename | Path del archivo que se usará para guardar la información de logs recibidos. |

Método log

El método log es el que se ejecuta cuando se llama un log. Es quien debe plasmar la información en un fichero (para el caso de FilePlugin), la consola (para ConsolePlugin) o algún otro receptor (no limitado).

Recibe un parámetro que corresponde con la información generada por el log. Este objeto es el que envía el format una vez hizo su trabajo. Para ver detalles de este objeto, revisa aquí.

Este método no esta obligado ni necesita retornar información.

Logger por defecto

El paquete incluye un logger ya creado, pensado en un uso global (una aplicación en general, compartir el mismo logger entre módulos). Para ocuparlo se debe llamar al objeto Log desde '@nalv/logger', osea:

const nalvLogger = require('@nalv/logger')
const Log = nalvLogger.Log // const { Log } = require('@nalv/logger')
// import { Log } from '@nalv/logger' // Para Typescript y ES6

Log.info('logger por defecto con info')

Métodos

Sus métodos son limitados en comparación a un logger creado de manera "oficial", aunque hay ciertos métodos que hacen que su funcionamiento sea igual al de éstos.

Método setLogger

Si quieres establecer al logger otro logger para ocupar su configuración (por ejemplo), puedes mediante el método setLogger:

let newlogger = new Logger()
Log.setLogger(newlogger)

Método getLogger

Obtener el logger que se esta ocupando. Por defecto ocupa un logger vacío, con la configuración por defecto new Logger().

Con esto, se puede ingresar al objeto logger:

Log.getLogger().log('nivelPersonalizado', 'mensaje a guardar')
Log.getLogger().nivelPersonalizado('mensaje a guardar')

Métodos de log

Existen ciertos métodos disponibles para ejecutar logs, éstos se establecieron según los niveles por defecto y no se pueden cambiar. Estos son:

  • Log.emergency
  • Log.alert
  • Log.critical
  • Log.error
  • Log.warn
  • Log.notice
  • Log.info
  • Log.debug

Si se quiere ocupar logs de niveles que no están en el log por defecto, se debe ocupar el método getLogger