java - ejemplo - Log4j, configurando una aplicación web para usar una ruta relativa
log4j guardar en archivo (10)
¿Log4j no usa el directorio raíz de la aplicación si no especifica un directorio raíz en la propiedad path de FileAppender? Entonces deberías poder usar:
log4j.appender.file.File = logs / MyLog.log
Ha pasado un tiempo desde que realicé el desarrollo web de Java, pero parece ser el más intuitivo y tampoco colisiona con otros registros desafortunadamente nombrados que escriben en el directorio $ {catalina.home} / logs.
Tengo una aplicación web Java que debe implementarse 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. El contenedor probablemente sea Tomcat pero no necesariamente.
¿Cuál es la mejor manera de hacer esto?
Como comentario adicional en Iker''s , esto puede fallar, si la aplicación web inicia implícitamente otros ServletContextListener''s, que pueden llamarse antes y que ya intentan usar log4j, en este caso, el La configuración de log4j se leerá y analizará antes de que la propiedad determine que el directorio raíz del registro está configurado => los archivos de registro aparecerán en algún lugar debajo del directorio actual (el directorio actual cuando se inicia tomcat).
Solo puedo pensar en seguir la 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 ayuda DOM / PropertyConfigurator para asegurarse de que se lea su log4j -. {Xml, properties} - Restablezca la configuración de log4j (IIRC hay un método para hacerlo)
Esto es un poco de fuerza bruta, pero creo que es la única forma de hacerlo estanco.
En caso de que estés usando Maven, tengo una gran solución para ti:
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í define la propiedad de
logDirectory
específicamente para la familia del sistema operativo.Use la propiedad
logDirectory
ya definida en el archivolog4j.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
- ¡Eso es!
PD: estoy seguro de que esto se puede lograr usando Ant pero desafortunadamente no tengo suficiente experiencia con él.
Finalmente lo hice de esta manera.
Se 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 que no la use antes de que se haya establecido la propiedad del sistema "rootPath". Esto significa que no puede usarlo desde ServletContextListener, pero debería poder usarlo desde cualquier otro lugar de la aplicación.
Debería funcionar en todos los contenedores web y sistemas operativos, ya que no depende de una propiedad del sistema específica del contenedor y no se ve afectada por problemas de ruta específicos del sistema operativo. Probado con contenedores web Tomcat y Orion, y en Windows y Linux, y funciona bien hasta el momento.
¿Qué piensas?
Mi solución es similar a la solution Iker Jimenez, pero en lugar de usar System.setProperty(...)
utilizo org.apache.log4j.PropertyConfigurator.configure(Properties)
. Para eso también necesito que log4j no pueda encontrar su configuración por sí mismo y lo cargo manualmente (ambos puntos se describen en la answer Wolfgang Liebich).
Esto funciona para Jetty y Tomcat, independiente o ejecutado desde IDE, no requiere configuración, permite colocar los registros de cada aplicación en su propia carpeta, sin importar cuántas aplicaciones haya dentro del contenedor (que es el problema con la solución basada en el System
). De esta forma, 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 teníamos todos los archivos de configuración dentro de WEB-INF/
).
Detalles:
- Tengo mis propiedades en el archivo
log4j-no-autoload.properties
en el classpath (por ejemplo, en mi proyecto Maven está originalmente ensrc/main/resources
, se empaqueta enWEB-INF/classes
), Tiene el appender de archivos configurado como, por ejemplo:
log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log ...
Y tengo un oyente de contexto como este (se vuelve mucho más corto 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(...) } ... }
Mi sugerencia es que el archivo de registro siempre se registre sobre el contexto raíz de la aplicación web, por lo que en caso de que volvamos a implementar la aplicación web, no queremos sobrescribir los archivos de registro existentes.
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.
Si usa Spring, puede:
1) cree un archivo de configuración log4j, por ejemplo, "/WEB-INF/classes/log4j-myapp.properties" NO lo 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 webapp, 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 en log4j-myapp.properties también.
Ver 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 Iker''s solución Iker''s .
ServletContext
es una buena solución para su problema. Pero no creo que sea bueno para mantener. La mayoría de las veces, los archivos de registro se deben guardar durante mucho tiempo.
Dado que ServletContext
hace que el archivo esté debajo del archivo desplegado, se eliminará cuando se vuelva a desplegar el servidor. Mi sugerencia es ir con la carpeta principal de rootPath en lugar del primer hijo.
Tomcat establece una propiedad del sistema catalina.home. Puede usar esto en su 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 apunta a / usr / share / tomcat6 que no tiene ningún vínculo a / var / log / tomcat6. Aquí solo usa ${catalina.base}
.
Si usa otro contenedor, intente encontrar una propiedad similar del sistema o defina la suya propia. Establecer 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