2011-07-31 18 views
7

¿Es posible imprimir el nombre del hilo en las declaraciones de registro generadas por java.util.logging.Logger? Una alternativa es hacer algo como lo siguiente:nombre del hilo de impresión usando java.util.logging

logger.info(thread.getName() +" some useful info"); 

pero es repetitivo y el marco de registro debe manejarlo.

+0

Creo que usar log4j o slf4j será más limpio que las soluciones sugeridas en las respuestas. :) – Diablo

Respuesta

7

embarazoso, pero parece java.util.logging no puede hacer esto ...

El valor predeterminado java.util.logging.SimpleFormatter no tiene la capacidad de registrar el nombre del hilo en absoluto. El java.util.logging.FileHandler admite pocos marcadores de posición de plantilla, ninguno de ellos es el nombre del subproceso.

java.util.logging.XMLFormatter es la más cercana, pero sólo registra ID del tema:

<record> 
    <date>2011-07-31T13:15:32</date> 
    <millis>1312110932680</millis> 
    <sequence>0</sequence> 
    <logger></logger> 
    <level>INFO</level> 
    <class>java.util.logging.LogManager$RootLogger</class> 
    <method>log</method> 
    <thread>10</thread> 
    <message>Test</message> 
</record> 

Si cree que nos estamos acercando - no estamos. La clase LogRecord solo contiene la ID del hilo, no su nombre, no es muy útil.

1

Algunos servidores de aplicaciones registran implícitamente el ID del hilo (sé de WebSphere). Puede crear su propio LogFormatter. Los registros pasados ​​al formateador contienen el ID del hilo, vea here. Implementé ese enfoque para Tomcat varias veces, pero también funcionará en entornos Java SE.

BTW: El nombre del subproceso no está disponible para LogRecord.

1

java.util.logging tiene muchas peculiaridades curiosas. se puede añadir un API de fachada para modificar sus comportamientos

public class Log 

    Logger logger; 

    static public Log of(Class clazz) 
     return new Log(Logger.getLogger(clazz.getName())); 

    public void error(Throwable thrown, String msg, Object... params) 
    { 
     log(ERROR, thrown, msg, params); 
    } 

    void log(Level level, Throwable thrown, String msg, Object... params) 
    { 
     if(!logger.isLoggable(level)) return; 

     // bolt on thread name somewhere 
     LogRecord record = new LogRecord(...); 
     record.setXxx(...); 
     ... 
     logger.log(record); 
    } 

---- 

static final Log log = Log.of(Foo.class); 
.... 
log.error(...); 

personas utilizan el registro de Java sobre todo porque no quieren tener dependencias de 3 ª parte. Es por eso que no pueden depender de fachadas de registro existentes como apache's o slf4j.

2

Tuve un problema similar. Como aquí la respuesta a How to align log messages using java.util.logging se puede extender java.util.logging.Formatter sino conseguir LogRecord#getThreadID() se puede obtener el nombre del hilo invocando Thread.currentThread().getName() así:

public class MyLogFormatter extends Formatter 
{ 

    private static final MessageFormat messageFormat = new MessageFormat("[{3,date,hh:mm:ss} {2} {0} {5}]{4} \n"); 

    public MyLogFormatter() 
    { 
     super(); 
    } 

    @Override 
    public String format(LogRecord record) 
    { 
     Object[] arguments = new Object[6]; 
     arguments[0] = record.getLoggerName(); 
     arguments[1] = record.getLevel(); 
     arguments[2] = Thread.currentThread().getName(); 
     arguments[3] = new Date(record.getMillis()); 
     arguments[4] = record.getMessage(); 
     arguments[5] = record.getSourceMethodName(); 
     return messageFormat.format(arguments); 
    } 

} 
+7

¿No pondrá esto el nombre del subproceso del subproceso que llama al formateador y no el nombre de subproceso del subproceso que creó la entrada del registro? Supongo que podrían ser iguales en algunas situaciones, pero no hay garantía. – pauli

1

Un par de las respuestas anteriores sugieren que LogRecord.getThreadId() devuelve un identificador de hilo significativo, y todo lo que nos falta es una forma de correlacionar eso con el nombre del hilo.

Desafortunadamente LogRecord.getThreadId() devuelve un valor int que no corresponde a la identificación larga del subproceso que indujo el mensaje de registro.

Así que no podemos usar ManagementFactory.getThreadMXBean() para resolver el nombre de la secuencia. Resulta en nombres de hilos aleatorios.

Si está seguro de que su instalación de registro siempre formatea en el mismo hilo que la persona que llama, puede crear un formateador personalizado como se propuso anteriormente y llamar a Thread.currentThread(). GetName().

Parece que una fachada de registro o una biblioteca de terceros son las únicas opciones completamente seguras.

-1

Para complementar @ respuesta l245c4l: En lugar de utilizar SimpleFormatter() utiliza:

//fileHandler.setFormatter(new SimpleFormatter()); 

class MyFormatter extends Formatter { 
    private final MessageFormat messageFormat = new MessageFormat("{0,date}, {0,time} {1} {2}: {3} [T:{4}] {5}\n"); 

    public String format(LogRecord record) 
    { 
     Object[] arguments = new Object[6]; 
     arguments[0] = new Date(record.getMillis()); 
     arguments[1] = record.getSourceClassName(); 
     arguments[2] = record.getSourceMethodName(); 
     arguments[3] = record.getLevel(); 
     arguments[4] = Long.toString(Thread.currentThread().getId()); 
     arguments[5] = record.getMessage(); 

     return messageFormat.format(arguments); 
    } 
} 

fileHandler.setFormatter(new MyFormatter()); 

Logger myLogger = Logger.getLogger("<LOGGER_NAME>"); 
myLogger.addHandler(fileHandler); 

donde T:{4} es el ID del tema (argumento 4).

Cuestiones relacionadas