Separar logs de aplicações no JBoss é uma tarefa comum e existem alguns modos de fazer isso:
1. Adicionando uma Category ao $JBOSS_CONF/conf/jboss-log4j.xml pegando todos o package da aplicação e usando um Appender específico. Por exemplo:
<category name="net.rafaelliu">
<priority value="INFO" />
<appender-ref ref="BLOG_LOG"/>
</category>
Embora seja a solução mais fácil, a separação não está perfeita. Como estamos separando por pacotes, um erro no Hibernate por exemplo, ainda vai ser escrito no server.log, mesmo tendo sido lançado pela aplicação.
2. Usando Filters é possível criar um TCLFilter para pegar apenas logs de determinada aplicação. Basta criar um Appender específico:
<appender name="BLOG_LOG" class="org.jboss.logging.appender.DailyRollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="${jboss.server.log.dir}/blog.log"/>
<param name="Append" value="true"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
</layout>
<!-- filter -->
<filter class="org.jboss.logging.filter.TCLFilter">
<param name="AcceptOnMatch" value="true"/>
<param name="DeployURL" value="blog.war"/>
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"></filter>
</appender>
O problema aqui é que, embora o log seja gravado separadamente (inclusive de pacotes do Hibernate, por exemplo), ele será gravado duas vezes: uma vez no blog.log que definimos e uma vez no server.log do JBoss. Isso resulta em mais IO e mais espaço em disco.
3. Empacotando um log4j na própria aplicação, em WEB-INF/lib, é possível inverter o classloader e fazer com que as configurações do log4j valham apenas para sua aplicação:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>
net.rafaelliu:loader=blog.war
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>
Feito isso, é preciso criar o log4j.properties (ou xml) normalmente:
log4j.rootLogger=${jboss.server.log.threshold}, fileout
log4j.appender.fileout=org.apache.log4j.DailyRollingFileAppender
log4j.appender.fileout.File=${jboss.server.log.dir}/blog.log
log4j.appender.fileout.Append=true
log4j.appender.fileout.DatePattern='.'yyyy-MM-dd
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
log4j.appender.fileout.layout.ConversionPattern=%d %-5p [%c] (%t) %m%n
O log4j faz parse de system properties, que podem ser usadas no arquivo de configuração. Uma observação importante é que não é possível usar classes do JBoss aqui! Isso causaria ClassCastExceptions. Algumas dicas:
- No JBoss 5, use o
jboss.server.log.dir e o jboss.server.log.threshold. Isso facilitará o deploy da sua aplicação em outros ambientes;
- Use o mesmo Appender do jboss-log4j (provavelmente uma classe da JBoss estará lá, veja o equivalente da Apache). Isso deixa os logs do JBoss e das aplicações sincronizados, facilitando o correlacionamento de erros;
O problema dessa abordagem é que perdemos o “hot deploy” do jboss-log4j.xml, que nos permite alterar o nível de log sem indisponibilidade.
Referências:
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PropertyConfigurator.html
http://viragine.blogspot.com/2009/02/separando-o-log-do-jboss-as-por.html
http://community.jboss.org/wiki/SeparatingApplicationLogs