Pregunta

Tenemos varios trabajos que se ejecutan simultáneamente y que deben usar la misma información de configuración para log4j.Todos volcan los registros en un archivo usando el mismo agregador.¿Hay alguna manera de que cada trabajo nombre dinámicamente su archivo de registro para que permanezcan separados?

Gracias
Tomás

¿Fue útil?

Solución

¿Puedes pasar una propiedad del sistema Java para cada trabajo?Si es así, puedes parametrizar así:

java -Dmy_var=somevalue my.job.Classname

Y luego en tu log4j.properties:

log4j.appender.A.File=${my_var}/A.log

Podría completar la propiedad del sistema Java con un valor del entorno del host (por ejemplo) que identificaría de forma única la instancia del trabajo.

Otros consejos

Si los nombres de los trabajos se conocen de antemano, puede incluirlos cuando realice la llamada a getLogger().Luego puede vincular diferentes anexos a diferentes registradores, con nombres de archivos separados (u otros destinos).

Si no puede saber el nombre del trabajo con anticipación, puede configurar el registrador en tiempo de ejecución en lugar de usar un archivo de configuración:

FileAppender appender = new FileAppender();
appender.setFileName(...);
appender.setLayout(...);
Logger logger = Logger.getLogger("com.company.job."+jobName);
logger.addAppender(appender);

Tenemos algo similar implementado en nuestro sistema.Almacenamos los registradores específicos en un HashMap e inicializamos los apéndices para cada uno de ellos según sea necesario.

He aquí un ejemplo:

public class JobLogger {
private static Hashtable<String, Logger> m_loggers = new Hashtable<String, Logger>();
private static String m_filename = "...";  // Root log directory

public static synchronized void logMessage(String jobName, String message)
{
    Logger l = getJobLogger(jobName);
    l.info(message);
}

public static synchronized void logException(String jobName, Exception e)
{
    Logger l = getJobLogger(partner);
    l.info(e.getMessage(), e);
}

private static synchronized Logger getJobLogger(String jobName)
{
    Logger logger = m_loggers.get(jobName);
    if (logger == null) {
        Layout layout = new PatternLayout("...");
        logger = Logger.getLogger(jobName);
        m_loggers.put(jobName, logger);
        logger.setLevel(Level.INFO);
        try {
            File file = new File(m_filename);
            file.mkdirs();
            file = new File(m_filename + jobName + ".log");
            FileAppender appender = new FileAppender(layout, file.getAbsolutePath(), false);
            logger.removeAllAppenders();
            logger.addAppender(appender);
    }
        catch (Exception e)
    { ... }
    }
    return logger;
}
}

Luego, para usar esto en tu trabajo sólo tienes que usar una entrada de una línea como esta:

JobLogger.logMessage(jobName, logMessage);

Esto creará un archivo de registro para cada nombre de trabajo y lo colocará en su propio archivo con ese nombre de trabajo en el directorio que especifique.

Puede jugar con otros tipos de agregados y demás, tal como está escrito, continuará agregando hasta que se reinicie la JVM, lo que puede no funcionar si ejecuta el mismo trabajo en un servidor que siempre está activo, pero esto da una idea general de cómo puede trabajar.

Puede hacer que cada trabajo establezca NDC o MDC y luego escribir un anexo que varíe el nombre según el valor de NDC o MDC.Crear un nuevo appender no es demasiado difícil.También puede haber un apéndice que se ajuste a los requisitos en el entorno limitado de log4j.Empezar a buscar en http://svn.apache.org/viewvc/logging/log4j/trunk/contribs/

Podrías escribir tu propio agregador que constituya su propio nombre de archivo, tal vez usando [File.createTempFile](http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String)) método.Si el FileAppender La clase se escribió correctamente, deberías poder ampliarla, o RollingFileAppender—y anular el getFile método para devolver uno que elija en función de las nuevas propiedades que desee agregar.

Sobre la base de shaditLa respuesta.Si se puede identificar cada trabajo mediante qué método principal de clase se inició, puede usar la propiedad del sistema sun.java.command que contiene el nombre completo de la clase iniciada.Por ejemplo así:

log4j.appender.LOGFILE.File=${sun.java.command}.log

Lo uso junto con un Appender de archivo de marca de tiempo como esto:

log4j.appender.LOGFILE=TimestampFileAppender
log4j.appender.LOGFILE.TimestampPattern=yyyy_MM_dd__HH_mm
log4j.appender.LOGFILE.File=${sun.java.command}_{timestamp}.log

De esta manera, cuando estoy desarrollando en Eclipse, obtengo un nuevo archivo de registro para cada nuevo proceso que ejecuto, identificado por el nombre de la clase con el método principal y la hora en que se inició.

Tom, podrías especificar anexos para cada trabajo.Supongamos que tienes 2 trabajos correspondientes a dos paquetes java diferentes com.tom.firstbatch y com.tom. secondbatch, tendrías algo como esto en log4j.xml:

   <category name="com.tom.firstbatch">
      <appender-ref ref="FIRST_APPENDER"/>
   </category>
   <category name="com.tom.secondtbatch">
      <appender-ref ref="SECOND_APPENDER"/>
   </category>

Puede configurar log4j mediante programación cuando inicializa el trabajo.

También puede configurar el archivo log4j.properties en tiempo de ejecución a través de una propiedad del sistema.Desde el manual:

Establezca la variable de cadena de recurso en el valor de log4j.configuración propiedad del sistema.La forma preferida de especificar el archivo de inicialización predeterminado es a través de la propiedad del sistema log4j.configuration.En caso de que la propiedad del sistema log4j.configuration no esté definida, establezca el recurso de variable de cadena en su valor predeterminado "log4j.properties".

Suponiendo que está ejecutando los trabajos desde diferentes comandos de Java, esto les permitirá usar diferentes archivos log4j.properties y diferentes nombres de archivo para cada uno.

Sin un conocimiento específico de cómo se ejecutan sus trabajos, ¡es difícil decirlo!

puede implementar lo siguiente:

  • Un titular de ThreadLocal para la identidad de su trabajo.
  • Amplíe FileAppender, su FileAppender debe mantener un mapa que contenga un QuietWriter para cada identidad de trabajo.En el método subAppend, obtienes la identidad de tu trabajo de ThreadLocal, buscas (o creas) QuietWriter y escribes en él...

Puedo enviarte algún código por correo si lo deseas...

log4j.logger.com.foo.admin =, adminfileAppender log4j.logger.com.foo.report =, reportFileAppender

Es otra forma de hacer esta tarea..aquí com.foo.admin es el nombre completo del paquete

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top