2010-09-30 14 views
11

Buscamos utilizar SLF4J, pero una cosa que encontramos fue que no se puede especificar el nivel como un argumento, es decirSLF4J nivel de registro como argumento

Logger.log(Level.INFO, "messsage"); 

Tienes que hacer esto

logger.info("message"); 

Esto impide pasar todo a través de un método, por lo que puede agregar otras propiedades a todos los mensajes de registro de una clase.

public class Test 
{ 
    public Test(SomeObj obj) 
    { 
     log(Level.INFO, "message"); 
    } 

    public void anotherMethod() 
    { 
     log(Level.DEBUG, "another message"); 
    } 
    private void log(Level level, String message) 
    { 
     logger.log(level, message + obj.someString()); 
    } 
} 

¿Hay alguna manera de lograrlo con SLF4j?

+1

pase la cadena "INFO" y "DEPURAR", y use la reflexión para invocar el método correcto, ¡es broma! – irreputable

+0

De hecho, es muy miope y lamentable que la mayoría (probablemente todos) los madereros contemporáneos sigan ese paradigma arcaico – matanster

Respuesta

6

La respuesta es No. Consulte this discussion.

+0

. Hay una forma de hacerlo, pero implica obtener un control del registrador nativo que slf4j encontró. - mira mi respuesta a continuación. – PaulG

8

Escriba un contenedor alrededor de la llamada slf4j y cree su propia enumeración para los seis niveles de registro. Luego, en su contenedor, use un interruptor para llamar a la llamada slf4j correcta.

void myLog(Level level, String message) 
{ 
    switch (level) 
    { 
    case FATAL: 
    log.fatal(message); 
    break; 
    case ERROR: 
    log.error(message); 
    break; 
    .... 
    } 
} 
1

Bueno, técnicamente SLF4J no le ofrece un método logger.log (Nivel, mensaje). Pero encontré una forma de evitar eso. [editar: utiliza la introspección]

Utilizando el fragmento de código a continuación, puede obtener el registrador nativo que slf4j encontró y envolvió para usted en el tiempo de ejecución. Si recuerda, slf4j es simplemente un envoltorio alrededor de una implementación slf4j de otro proveedor (ya sea, jdkLogging, Log4J, JCL, etc.). Así que aquí:

public Object getNativeLogger(org.slf4j.Logger logger) { 
    Object result = null; 
    if (logger.getClass().getName().equals("org.slf4j.impl.Log4jLoggerAdapter")) { 
     try { 
     Field f = Log4jLoggerAdapter.class.getDeclaredField("logger"); 
     f.setAccessible(true); 
     result = (org.apache.log4j.Logger)f.get(logger); 
     } 
     catch(Exception e) { 
     System.out.println("Unable to access native log4j logger"); 
     } 
    } 
    else if (logger.getClass().getName().equals("org.slf4j.impl.JDK14LoggerAdapter")) { 
     try { 
     Field f = Jdk14Logger.class.getDeclaredField("logger"); 
     f.setAccessible(true); 
     result = (Jdk14Logger)f.get(logger); 
     } 
     catch(Exception e) { 
     System.out.println("Unable to access native log4j logger"); 
     } 
    } 
    else if (..... other native loggers slf4j supports).... 
    } 
    return result; 
} 

A continuación, se puede utilizar de esta manera:

Object l = getNativeLogger(mySlf4jLogger); 
    if (l instanceof org.apache.log4j.Logger) { 
     org.apache.log4j.Logger logger = (org.apache.log4j.Logger) l; 
     logger.log(CUSTOMLog4JLevel, message); 
    } 
    else if(.... other implementations that you care about ...)... 

Así, mientras que no es técnicamente dentro slf4j, es posible hacerlo utilizando slf4j como su interfaz de registro primario.

2

Su uso grita por el patrón de delegación. Básicamente, usted CUÑA su propia implementación de Logger entre su código y SLF4J y "extender" los métodos pertinentes:

class MyLogger implements Logger { 

    Logger realLogger; 
    Object userData; 


    MyLogger(Class clazz, Object userData){ 
     this.realLogger = LoggerFactory.getLogger(clazz); 
    } 

    public void debug(String msg) { 
     realLogger.debug(msg + userData.someString()); 
    } 

    // many more methods, perhaps per java.lang.reflect.Proxy 
} 

Esta es su uso en el código de negocio como este:

public class Test 
{ 
    Logger log; 

    public Test(SomeObj obj) 
    { 
     log = new MyLogger(Test.class, obj); 
     log.logInfo("message"); 
    } 

    public void anotherMethod() 
    { 
     logDebug("another message"); 
    } 
} 

Para la reutilización óptima de la MyLogger clase SomeObj debe usar Object.toString() o debe implementar una interfaz que MyLogger puede usar para obtener el apéndice del mensaje.

Cuestiones relacionadas