Log4j, configurando um aplicativo da web para usar um caminho relativo
-
03-07-2019 - |
Pergunta
Eu tenho um java webApp que precisa ser implantado em máquinas Win ou Linux. Agora, quero adicionar log4j para o log e gostaria de usar um caminho relativo para o arquivo de log, pois não quero alterar o caminho do arquivo em cada implantação. O contêiner provavelmente será Tomcat, mas não necessariamente.
Qual é a melhor maneira de fazer isso?
Solução 2
Eu finalmente fiz isso dessa maneira.
Adicionado um ServletContextListener que faz o seguinte:
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
System.setProperty("rootPath", context.getRealPath("/"));
}
Então, no arquivo log4j.properties:
log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log
Ao fazê -lo dessa maneira, o Log4J gravará na pasta certa, desde que você não o use antes que a propriedade do sistema "rootpath" seja definida. Isso significa que você não pode usá -lo no próprio ServletContextListener, mas poderá usá -lo de qualquer outro lugar do aplicativo.
Ele deve funcionar em todos os contêineres da Web e SO, pois não depende de uma propriedade do sistema específica do contêiner e não é afetada por problemas de caminho específicos do SO. Testado com contêineres da Web Tomcat e Orion e no Windows e Linux e funciona bem até agora.
O que você acha?
Outras dicas
Tomcat define uma propriedade Catalina.Home System. Você pode usar isso no seu arquivo de propriedades log4j. Algo assim:
log4j.rootCategory=DEBUG,errorfile
log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log
No Debian (incluindo o Ubuntu), ${catalina.home}
Não funcionará porque esse ponto em/usr/share/tomcat6, que não tem link para/var/log/tomcat6. Aqui basta usar ${catalina.base}
.
Se você estiver usando outro contêiner, tente encontrar uma propriedade do sistema semelhante ou definir a sua. A configuração da propriedade do sistema varia de acordo com a plataforma e o contêiner. Mas para o tomcat no Linux/Unix, eu criaria um setenv.sh no diretório Catalina_home/bin. Ele conteria:
export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"
Então seus log4j.properties seriam:
log4j.rootCategory=DEBUG,errorfile
log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log
Se você usar a primavera, pode:
1) Crie um arquivo de configuração log4j, por exemplo, "/web-inf/classes/log4j-myapp.properties" Não nomeie "log4j.properties"
Exemplo:
log4j.rootLogger=ERROR, stdout, rollingFile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=${myWebapp-instance-root}/WEB-INF/logs/application.log
log4j.appender.rollingFile.MaxFileSize=512KB
log4j.appender.rollingFile.MaxBackupIndex=10
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.rollingFile.Encoding=UTF-8
Definiremos "MyWebApp-Instance-Root" mais tarde no ponto (3)
2) Especifique o local da configuração em web.xml:
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>
3) Especifique um único Nome da variável para a raiz do seu WebApp, por exemplo, "MyWebApp-Instance-Root"
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>myWebapp-instance-root</param-value>
</context-param>
4) Adicione um log4jconfigListener:
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
Se você escolher um nome diferente, lembre-se de alterá-lo no log4j-myapp.properties.
Veja meu artigo (apenas italiano ... mas deve ser compreensível):http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring
Atualização (2009/08/08)Eu traduzi meu artigo para o inglês:http://www.megadix.it/node/136
Apenas um comentário sobre Iker's solução.
ServletContext
é uma boa solução para o seu problema. Mas não acho que seja bom para manter. Na maioria das vezes, os arquivos de log devem ser salvos por muito tempo.
Desde ServletContext
Faz o arquivo no arquivo implantado, ele será removido quando o servidor for reimpletado. Minha sugestão é ir com a pasta pai do Rootpath em vez de uma criança uma.
O log4j não usa o diretório raiz do aplicativo se você não especificar um diretório raiz na propriedade Path do seu FilePpender? Então você deve apenas poder usar:
log4j.appender.file.file = logs/mylog.log
Faz um tempo desde que eu fiz o desenvolvimento da web do Java, mas isso parece ser o mais intuitivo e também não colide com outros logs, infelizmente nomeados, escrevendo para o diretório $ {catalina.home}/logs.
Como um comentário adicional sobre https://stackoverflow.com/a/218037/2279200 - Isso pode quebrar, se o aplicativo da web iniciar implicitamente outros servletContextListener, que poderão ser chamados anteriormente e que já tentam usar o LOG4J - neste caso, a configuração do LOG4J será lida e analisada já antes da propriedade que determina o diretório da raiz do log. => Os arquivos de log aparecerão em algum lugar abaixo do diretório atual (o diretório atual ao iniciar o tomcat).
Eu só conseguia pensar em seguir a solução para este problema: - renomeie seu arquivo log4j.properties (ou logj4.xml) para algo que o log4j não lerá automaticamente. - No seu filtro de contexto, depois de definir a propriedade, ligue para a classe DOM/PropertyConfigurator auxiliar para garantir que seu log4j -. {Xml, Propriedades} seja lido - redefinir a configuração log4j (IIRC, existe um método para fazer isso)
Essa é uma força um pouco bruta, mas as mexem é a única maneira de torná -la estanque.
Caso você esteja usando o maven, tenho uma ótima solução para você:
Edite seu arquivo pom.xml para incluir as seguintes linhas:
<profiles> <profile> <id>linux</id> <activation> <os> <family>unix</family> </os> </activation> <properties> <logDirectory>/var/log/tomcat6</logDirectory> </properties> </profile> <profile> <id>windows</id> <activation> <os> <family>windows</family> </os> </activation> <properties> <logDirectory>${catalina.home}/logs</logDirectory> </properties> </profile> </profiles>
Aqui você define
logDirectory
propriedade especificamente para a família OS.Use já definido
logDirectory
Propriedade emlog4j.properties
Arquivo:log4j.appender.FILE=org.apache.log4j.RollingFileAppender log4j.appender.FILE.File=${logDirectory}/mylog.log log4j.appender.FILE.MaxFileSize=30MB log4j.appender.FILE.MaxBackupIndex=10 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%x] %-5p [%t] [%c{1}] %m%n
- É isso!
PS: Tenho certeza de que isso pode ser alcançado usando ANT, mas infelizmente não tenho experiência suficiente com isso.
Minha sugestão é que o arquivo de log deve sempre ser registrado acima do contexto raiz do WebApp; portanto, caso reimpletemos o WebApp, não queremos substituir os arquivos de log existentes.
Minha solução é semelhante ao de Iker Jimenez solução, mas em vez de usar System.setProperty(...)
eu uso org.apache.log4j.PropertyConfigurator.configure(Properties)
. Para isso, também preciso que o log4j não consiga encontrar sua configuração por conta própria e eu a carrego manualmente (ambos os pontos descritos no Wolfgang Liebich's responda).
Isso funciona para o jetty e o tomcat, independente ou correr do IDE, requer configuração zero, permite colocar os registros de cada aplicativo em sua própria pasta, não importa quantos aplicativos dentro do contêiner (que é o problema com o System
-solução baseada). Dessa forma, também se pode colocar o arquivo de configuração log4j em qualquer lugar dentro do aplicativo da web (por exemplo, em um projeto, todos nós tínhamos arquivos de configuração dentro WEB-INF/
).
Detalhes:
- Eu tenho minhas propriedades no
log4j-no-autoload.properties
arquivo no caminho de classe (por exemplo, no meu projeto Maven, é originalmentesrc/main/resources
, é empacotado emWEB-INF/classes
), Ele tem o Appender de arquivo configurado como por exemplo:
log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log ...
E eu tenho um ouvinte de contexto como este (fica muito mais curto com a sintaxe "Try-With-Resource" do Java 7):
@WebListener public class ContextListener implements ServletContextListener { @Override public void contextInitialized(final ServletContextEvent event) { Properties props = new Properties(); InputStream strm = ContextListener.class.getClassLoader() .getResourceAsStream("log4j-no-autoload.properties"); try { props.load(strm); } catch (IOException propsLoadIOE) { throw new Error("can't load logging config file", propsLoadIOE); } finally { try { strm.close(); } catch (IOException configCloseIOE) { throw new Error("error closing logging config file", configCloseIOE); } } props.put("webAppRoot", event.getServletContext().getRealPath("/")); PropertyConfigurator.configure(props); // from now on, I can use LoggerFactory.getLogger(...) } ... }
Você pode especificar um caminho relativo para o arquivo de log, usando o diretório de trabalho:
appender.file.fileName = ${sys:user.dir}/log/application.log
Isso é independente do contêiner do servlet e não requer a passagem de variável personalizada para o ambiente do sistema.