Mostrando entradas con la etiqueta log4j. Mostrar todas las entradas
Mostrando entradas con la etiqueta log4j. Mostrar todas las entradas

jueves, marzo 05, 2015

Async loggin with log4j 1.x

If you are reading this surely you have found out that using AsyncAppender its not clearly documented and most of your google results lead you to some log4j 2.X.

Ok, in that case this is the right post for you.

Lets take an ordinary (synchronous) file logger from Log4j 1.x ( tested with 1.2.17) and wrap it up with a 'cool' AsyncAppender. :D.

Considering that you have

import org.slf4j.Logger
...
static Logger log = LoggerFactory.getLogger("MyLogger");

You turn your internal sync appender into an async with:

static {
  AsyncAppenderBuilder.wrapAsyncAppender(log, "MyAppndrName")
}

Then use just like a regular logger

The helping class looks like this:

Hope it helps!
Iván.

jueves, febrero 12, 2015

Grails in prod with an external log4j properties

Maybe you have tried to config your Grails app so you can:


  • Use the default logging configuration inside Config.groovy for test or dev.
  • Use an external log4j.properties file in production.


It's quite frustating and it is not so well documented.
After some digging I came up with a quite elegant solution:

Config.groovy:
----------------------------

import grails.util.Environment

if(Environment.current!=Environment.PRODUCTION){
  // log4j configuration
  log4j = {
    ...
  }
}


resources.groovy:
----------------------------

import grails.util.Environment

if(Environment.current==Environment.PRODUCTION){
  log4jConfigurer(org.springframework.beans.factory.config.MethodInvokingFactoryBean) {
    targetClass = "org.springframework.util.Log4jConfigurer"
    targetMethod = "initLogging"
    arguments = ["classpath:resources/log4j.properties"]
  }
} 


log4j.properties (src/resources/log4j.properties):
----------------------------
  //whatever make sense to you

Please remember NOT to forget your imports or otherwise it wont work.

Hope it helps!

PD: Grails 3.0 is about to see the light and ...well who kows!. This solution is right for Grails 2.x family.

viernes, febrero 15, 2013

Desmontando Log4j

Buenas, a quién queremos engañar, la mayoría llevamos años haciendo configuraciones de Log4j gracias a Google, copiando y pegando cachos hasta que funciona...técnicamente es lo que se conoce como "programming by coincidence".

Así que la idea de este post es romper eso y explicar de forma semi-humana como se configura un log4j para que haga lo que queramos.

Lo primero es que todo esto esta explicado con detalle y de forma fantástica aquí: http://logging.apache.org/log4j/1.2/manual.html

Preámbulo

Ahora mis explicaciones, en log4j sólo hay 3 conceptos:
  • Logger: Indica la configuracion de logging para una categoria, son jerarquicos y se ponen nombres de paquetes/clases. Se puede/No se puede
  • Appenders: Sitios donde se puede escribir. ¿Dónde?
  • Layouts: Patrón de escritura del log. ¿Cómo?
Y dado el siguiente código de ejemplo:

Class Perro{
  def log=Logger.getLogger(Perro.class) //   ....   log.debug("Aqui estoy")  ... 

la librería tiene que resolver 2 preguntas:
  • El mensaje está enabled, es decir, ¿esta autorizado para pasar?
  • Donde lo tiro?

1. ¿Esta autorizado este mensaje?

Para responder esta pregunta hay que entender que existen distintos niveles de log, están ordenados y son los siguientes:

fatal > error > warn > info > debug > trace

Al mismo tiempo cada logger puede tener un nivel asignado o heredar el nivel de su padre de forma que el mensaje estará "enabled" si su mensaje es igual o superior al nivel autorizado.

Suena raro pero es lo mismo que se hace en PortAventura cuando se dice que para pasar al Dragon Khan hay que medir más de 1,30m, lo mismo.  





  Ok, y como se calcula el nivel asociado a un logger?

Pues dado que es jerarquico y funciona como los nombres de paquetes de las clases se puede construir una tabla como la siguiente:

LEVEL ESCRITO LEVEL CALCULADO
root error error
nortia warn warn
nortia.Pepe warn
nortia.hijo debug
nortia.hijo.Pepito debug debug

Ahora que sabes el nivel de un logger ya puedes decidir si eso pasa o no pasa, es decir escribe o no escribe.

2. ¿Donde se escribe?

La última parte es ver donde se escribe el mensaje que hayas puesto, en este punto hay que entender que del mismo modo que un logger tiene un único nivel calculado, un logger puede tener N appenders asociados:

log4j.rootLogger=DEBUG, myConsola, myFichero, myOtroFichero

dicho lo cual hay que seguir una regla muy sencilla
Por defecto se escribe en todos los appenders asociados a la jerarquía del logger  
Dicho lo cual te sale otra tabla que completa a la anterior:

ESCRITO ADDITIVITY CALCULADO
root Console Console
nortia Fich1 Fich1, Console
nortia.Pepe Fich1, Console
nortia.hijo Fich2 false Fich2
nortia.hijo.Pepito Fich2

3. Lo quiero en otro fichero solo...

En ocasiones puedes querer que las clases de tal paquete loggen en tal fichero, para evitar que esos mensajes salgan por todos los logger de la jerarquía basta con indicarlo con el flag de additivity

log4j.additivity.nortia.hijo = false

4.Resumen

En resumen:
  • Logger: 1 nivel escrito o calculado por logger
  • El mensaje esta "enabled" si es "más alto" que nivel calculado ese logger
  • Appenders: N por logger
  • El mensaje se escribe en todos los logger de la jerarquia salvo que uses additivity=false.