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?

Foi útil?

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ê:

  1. 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.

  2. Use já definido logDirectory Propriedade em log4j.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
    
  3. É 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:

  1. Eu tenho minhas propriedades no log4j-no-autoload.properties arquivo no caminho de classe (por exemplo, no meu projeto Maven, é originalmente src/main/resources, é empacotado em WEB-INF/classes),
  2. 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
    ...
    
  3. 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.

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