Pregunta

Tengo una aplicación web java que se debe implementar en máquinas Win o Linux. Ahora quiero agregar log4j para el registro y me gustaría usar una ruta relativa para el archivo de registro ya que no quiero cambiar la ruta del archivo en cada implementación. Lo más probable es que el contenedor sea Tomcat, pero no necesariamente.

¿Cuál es la mejor manera de hacer esto?

¿Fue útil?

Solución 2

Finalmente lo he hecho de esta manera.

Agregó un ServletContextListener que hace lo siguiente:

public void contextInitialized(ServletContextEvent event) {
    ServletContext context = event.getServletContext();
    System.setProperty("rootPath", context.getRealPath("/"));
}

Luego, en el archivo log4j.properties:

log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log

Al hacerlo de esta manera, Log4j escribirá en la carpeta correcta siempre y cuando no lo uses antes de " rootPath " Se ha establecido la propiedad del sistema. Esto significa que no puede usarlo desde el propio ServletContextListener pero debería poder usarlo desde cualquier otro lugar en la aplicación.

Debería funcionar en cada contenedor web y sistema operativo, ya que no depende de una propiedad del sistema específica del contenedor y no está afectado por problemas de ruta específicos del sistema operativo. Probado con contenedores web de Tomcat y Orion y en Windows y Linux, funciona bien hasta ahora.

¿Qué piensas?

Otros consejos

Tomcat establece una propiedad del sistema catalina.home. Puedes usar esto en tu archivo de propiedades log4j. Algo como esto:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log

En Debian (incluido Ubuntu), $ {catalina.home} no funcionará porque eso apunta a / usr / share / tomcat6 que no tiene enlace a / var / log / tomcat6. Aquí solo usa $ {catalina.base} .

Si está utilizando otro contenedor, intente encontrar una propiedad del sistema similar o defina la suya propia. La configuración de la propiedad del sistema variará según la plataforma y el contenedor. Pero para Tomcat en Linux / Unix crearía un setenv.sh en el directorio CATALINA_HOME / bin. Contendría:

export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"

Entonces su log4j.properties sería:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log

Si usas Spring puedes:

1) crea un archivo de configuración log4j, por ejemplo, " /WEB-INF/classes/log4j-myapp.properties" NO le asigne un nombre " log4j.properties "

Ejemplo:

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 " más adelante en el punto (3)

2) Especifique la ubicación de configuración en web.xml:

<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>

3) Especifique un nombre de variable único para la raíz de su aplicación web, por ejemplo. " myWebapp-instance-root "

<context-param>
  <param-name>webAppRootKey</param-name>
  <param-value>myWebapp-instance-root</param-value>
</context-param>

4) Agregue un Log4jConfigListener:

<listener>
  <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

Si elige un nombre diferente, recuerde cambiarlo también en log4j-myapp.properties.

Vea mi artículo (solo en italiano ... pero debería ser comprensible): http://www.megadix.it/content/configurare-path -relativi-log4j-utilizzando-spring

ACTUALIZACIÓN (2009/08/01) He traducido mi artículo al inglés: http://www.megadix.it/node/136

Solo un comentario sobre la solución Iker .

ServletContext es una buena solución para su problema. Pero no creo que sea bueno para el mantenimiento. La mayoría de las veces, los archivos de registro se deben guardar durante mucho tiempo.

Dado que ServletContext hace el archivo debajo del archivo desplegado, se eliminará cuando el servidor se vuelva a implementar. Mi sugerencia es ir con la carpeta principal de rootPath en lugar de la secundaria.

¿Log4j no solo usa el directorio raíz de la aplicación si no especifica un directorio raíz en la propiedad de su FileAppender? Así que deberías poder usar:

log4j.appender.file.File = logs / MyLog.log

Ha pasado un tiempo desde que hice el desarrollo web de Java, pero este parece ser el más intuitivo, y tampoco choca con otros registros con nombres desafortunadamente que se escriben en el directorio $ {catalina.home} / logs.

Como comentario adicional sobre https://stackoverflow.com/a/218037/2279200 , esto puede fallar, si la aplicación web inicia de forma implícita otras ServletContextListener, a las que se puede llamar antes y que ya intentan usar log4j, en este caso, la configuración de log4j se leerá y analizará antes de que se establezca la propiedad que determina el directorio raíz del registro = > los archivos de registro aparecerán en algún lugar debajo del directorio actual (el directorio actual al iniciar Tomcat).

Solo pude pensar en la siguiente solución a este problema: - cambie el nombre de su archivo log4j.properties (o logj4.xml) a algo que log4j no leerá automáticamente. - En su filtro de contexto, después de configurar la propiedad, llame a la clase de ayudante DOM / PropertyConfigurator para asegurarse de que se lea su log4j -. {Xml, propiedades} - Restablecer la configuración de log4j (IIRC hay un método para hacerlo)

Esta es una fuerza bruta, pero creo que es la única forma de hacerlo impermeable.

En caso de que estés usando Maven, tengo una gran solución para ti:

  1. Edite su archivo pom.xml para incluir las siguientes líneas:

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

    Aquí usted define la propiedad logDirectory específicamente para la familia del sistema operativo.

  2. Utilice la propiedad logDirectory ya definida en el archivo log4j.properties :

    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. ¡Eso es!

P.S .: Estoy seguro de que esto se puede lograr usando Ant, pero desafortunadamente no tengo suficiente experiencia con ella.

Mi sugerencia es que el archivo de registro siempre debe registrarse por encima del contexto raíz de la aplicación web, por lo que en caso de que volvamos a implementar la aplicación web, no queremos anular los archivos de registro existentes.

Mi solución es similar a la solución de Iker, pero en lugar de usar System.setProperty (... ) Utilizo org.apache.log4j.PropertyConfigurator.configure (Propiedades) . Para eso también necesito que log4j sea incapaz de encontrar su configuración por sí mismo y lo cargue manualmente (los dos puntos descritos en de Wolfgang Liebich responden ).

Esto funciona para Jetty y Tomcat, independiente o ejecutado desde IDE, requiere una configuración cero, permite colocar los registros de cada aplicación en su propia carpeta, sin importar cuántas aplicaciones se encuentren dentro del contenedor (que es el problema con el System -based solución). De esta manera, también se puede colocar el archivo de configuración log4j en cualquier lugar dentro de la aplicación web (por ejemplo, en un proyecto tuvimos todos los archivos de configuración dentro de WEB-INF / ).

Detalles:

  1. Tengo mis propiedades en el archivo log4j-no-autoload.properties en el classpath (por ejemplo, en mi proyecto de Maven está originalmente en src / main / resources , obtiene empaquetado en WEB-INF / classes ),
  2. Tiene el archivo appender configurado como, por ejemplo,

    log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender
    log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log
    ...
    
  3. Y tengo un oyente de contexto como este (se acorta mucho más con la sintaxis de " try-with-resource & de 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(...)
        }
        ...
    }
    

Puede especificar la ruta relativa al archivo de registro, utilizando el directorio de trabajo :

appender.file.fileName = ${sys:user.dir}/log/application.log

Esto es independiente del contenedor de servlets y no requiere pasar una variable personalizada al entorno del sistema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top