Como configurar vários log4j para diferentes guerras em um único EAR?
-
11-09-2019 - |
Pergunta
Eu tenho um EAR com estruturas como:
APP.ear
- APP1.war
- WEB-INF/classes/log4j.properties
- APP2.war
- WEB-INF/classes/log4j.properties
- app1-ejb.jar
- app2-ejb.jar
- log4j.jar
- spring.jar
- commons-lang.jar (...and other jar)
Eu quero que cada WAR para ter seu próprio registo de aplicação. Mas parece que a configuração acima não funciona. Log para APP1 e APP2 vai para log do APP1. Existe uma maneira de criar logs de aplicativos separados?
Solução
Acontece que é impossível devido ao carregador de classe. A hierarquia do carregador de classe é semelhante:
carregador de classe de aplicativo -> Ejb carregador de classe -> guerra carregador de classe
Para ter um log sepearte para a guerra indivíduo, pode-se colocar guerra dentro log4j.jar e deixar o log4j usa o carregador de classe guerra. Mas como ambos app1-ejb.jar e app2-ebj.jar também precisa usar log4j, o log4j.jar só pode ser colocado no nível superior. Assim, o log4j está no nível carregador de classe do aplicativo.
Eu posso especificar uma única configuração log4j para fazer logon pacote diferente para diferentes arquivos. Mas para a biblioteca comum como a primavera, o log não pode ser sepearted.
Outras dicas
A razão por que não funcionou porque o log4j está presente no local raiz, mas deixar que cada guerra têm um log4j.jar em seu diretório WEB-INF / lib e remova o log4j.jar a partir da raiz.
Para obter mais informações sobre isso, consulte o meu artigo blog sobre este http://techcrawler.wordpress.com/
Você também pode fazer isso alterando dinamicamente a propriedade de arquivo no arquivo de propriedades usando o PropertyConfigurator no código.
Logback é uma solução viável para resolver este problema. Depois de ter olhar em torno de diferentes hacks para fazer este trabalho com log4j, decidimos mudar para Logback. Eu usei a seguinte configuração com Logback frasco dentro do webapp.
Um arquivo Logback dentro do webapp que incluem um arquivo externo:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="10 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<contextName>${project.artifactId}</contextName>
<jmxConfigurator />
<include file="${logback.configuration.filepath}" />
</configuration>
${logback.configuration.filepath}
é substituído durante Maven filtrando pelo caminho exato, externo ao webapp do arquivo de configuração (algo como /opt/server/conf/loback.included.conf ).
E, em seguida, o conteúdo do logback.included.conf
(este arquivo é parte do projetct, entregue com build-helper:attach-artifact
, então ${project.artifactId}
também é substituído durante a filtragem Maven):
<?xml version="1.0" encoding="UTF-8" ?>
<included>
<appender name="file" class="ch.qos.logback.core.FileAppender">
<file>/var/log/server/${project.artifactId}.log</file>
<encoder>
<pattern>[@/%contextName] %date{ISO8601} [%-5level] %thread:[%logger] %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="file" />
</root>
</included>
Apenas limitação, o conteúdo do arquivo incluído deve ser compatível com a do includer. Apenas escrever regras de fato.