Pergunta

Temos vários trabalhos que são executados simultaneamente que tem que usar a mesma informação de configuração para log4j. Estão todos despejar os logs em um arquivo usando o mesmo appender. Existe uma maneira de ter cada trabalho citar dinamicamente seu arquivo de log para que fiquem separados?

Graças
Tom

Foi útil?

Solução

Você pode passar uma propriedade do sistema Java para cada trabalho? Se assim for, você pode parametrizar como esta:

java -Dmy_var=somevalue my.job.Classname

E, em seguida, em seus log4j.properties:

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

Você poderia preencher a propriedade do sistema Java com um valor de ambiente do host (por exemplo) que identificam o exemplo do trabalho.

Outras dicas

Se os nomes de trabalho são conhecidos antes do tempo, você poderia incluir o nome do trabalho quando você faz a chamada getLogger (). Você, então, pode ligar diferentes appenders a diferentes loggers, com nomes de arquivos separados (ou outros destinos).

Se você não pode saber o nome do trabalho antes do tempo, você pode configurar o logger em tempo de execução em vez de usar um arquivo de configuração:

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

Temos algo semelhante implementado em nosso sistema. Nós armazenamos os madeireiros específicos em um HashMap e inicializar appenders para cada um deles, conforme necessário.

Aqui está um exemplo:

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;
}
}

Em seguida, usar isso em seu trabalho, você apenas tem que usar uma entrada de uma linha como esta:

JobLogger.logMessage(jobName, logMessage);

Isto irá criar um arquivo de log para cada nome do trabalho e soltá-lo em seu próprio arquivo com aquele nome de trabalho em qualquer diretório que você especificar.

Você pode mexer com outros tipos de appenders e tal, como está escrito vai continuar acrescentando até que a JVM é reiniciado, que pode não funcionar se você executar o mesmo trabalho em um servidor que está sempre para cima, mas isso dá a idéia geral de como ele pode trabalhar.

Você pode ter cada conjunto de trabalho NDC ou MDC e, em seguida, escrever um appender que varia o nome com base no valor NDC ou MDC. Criando um novo appender não é muito difícil. Também pode haver um appender que vai caber a conta na caixa de areia log4j. Comece a olhar em http://svn.apache.org/viewvc/logging/ log4j / trunk / contribs /

Você pode escrever seu próprio appender que compõe o seu próprio nome de arquivo, talvez usando o [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 / . Se a classe FileAppender foi escrito corretamente, você deve ser capaz de estendê-lo-ou RollingFileAppender e substituir o método getFile voltar um que você escolher com base em qualquer nova propriedades que você gostaria de adicionar.

Com base na resposta shadit 's. Se cada trabalho pode ser identificado pelo método principal que class' foi iniciado, você pode usar a propriedade sun.java.command sistema que contais o nome completo da classe começou. Por exemplo como este:

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

Eu usá-lo juntamente com um TimestampFileAppender assim:

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

Desta forma, quando eu estou desenvolvendo no Eclipse eu conseguir um novo arquivo de log para cada novo processo que eu corro, identificado pelo nome de classe da classe com o método principal e o tempo que foi iniciado.

Tom você ter precisado especificar e appenders para cada trabalho. Vamos que você tem 2 empregos correspondentes a dois pacotes Java diferentes com.tom.firstbatch e com.tom.secondbatch, você teria algo como isso em log4j.xml:

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

Você poderia log4j programaticamente configure quando você iniciar o trabalho.

Você também pode definir o arquivo log4j.properties em tempo de execução através de uma propriedade do sistema. Do manual:

Defina a variável de seqüência de recurso para o valor do log4j.configuration propriedade do sistema. A maneira preferida para especificar o arquivo de inicialização padrão é através da propriedade do sistema log4j.configuration. No caso do log4j.configuration propriedade do sistema não está definido, em seguida, definir o recurso cadeia variável aos seus "log4j.properties" valor padrão.

Assumindo que você está executando os trabalhos de comandos java diferentes, isso vai permitir-lhes utilizar diferentes arquivos log4j.properties e nomes de arquivos diferentes para cada um.

Sem o conhecimento específico de como seus trabalhos são executados é difícil dizer!

Você pode implementar seguinte:

  • Suporte A ThreadLocal para a identidade de seu trabalho.
  • Estender FileAppender, seu FileAppender tem que manter um Mapa segurando uma Quietwriter para cada identidade de trabalho. Em subAppend método, você começa a identidade do seu trabalho a partir do ThreadLocal, você olha para cima (ou criar) o Quietwriter e escrever para ela ...

Eu posso enviar-lhe algum código por correio se você deseja ...

log4j.logger.com.foo.admin =, AdminFileAppender log4j.logger.com.foo.report =, ReportFileAppender

É uma outra maneira de fazer esta tarefa .. aqui com.foo.admin é o nome completo do pacote

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top