Log4j, configurer une application Web pour utiliser un chemin relatif

j'ai une webapp java qui doit être déployée sur les machines Win ou Linux. Je veux maintenant ajouter log4j pour la journalisation et j'aimerais utiliser un chemin relatif pour le fichier log car je ne veux pas changer le chemin du fichier à chaque déploiement. Le conteneur sera probablement Tomcat, mais pas nécessairement.

Quelle est la meilleure façon de faire ça?

78
demandé sur Iker Jimenez 2008-10-19 22:32:01

10 réponses

Tomcat définit un catalina.Maison Propriété du système. Vous pouvez l'utiliser dans vos propriétés log4j fichier. Quelque chose comme ceci:

log4j.rootCategory=DEBUG,errorfile

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

sur Debian (y compris Ubuntu), ${catalina.home} ne fonctionnera pas car cela pointe sur /usr/share/tomcat6 qui n'a pas de lien vers /var/log/tomcat6. Ici, il suffit d'utiliser ${catalina.base} .

si vous utilisez un autre conteneur, essayez de trouver une propriété système similaire, ou définissez la vôtre. Définir la propriété du système variera par plate-forme, et le contenant. Mais pour Tomcat sur Linux / Unix je créerais un setenv.sh dans le répertoire CATALINA_HOME/bin. Il contiendrait:

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

puis votre log4j.propriétés:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log
99
répondu Steve K 2013-11-26 10:36:17

Je l'ai finalement fait de cette façon.

a ajouté un ServletContextListener qui fait ce qui suit:

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

puis dans le log4j.fichier de propriétés:

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

en le faisant de cette façon Log4j va écrire dans le bon dossier tant que vous ne l'utilisez pas avant que la propriété du système" rootPath " ait été définie. Cela signifie que vous ne pouvez pas l'utiliser à partir du ServletContextListener lui-même, mais vous devriez pouvoir l'utiliser à partir de n'importe où ailleurs dans l'application.

il devrait fonctionner sur chaque conteneur web et OS car il n'est pas dépendant d'une propriété de système spécifique à un conteneur et il n'est pas affecté par des problèmes de chemin spécifiques à OS. Testé avec les conteneurs Web Tomcat et Orion et sur Windows et Linux et il fonctionne très bien jusqu'à présent.

Qu'en pensez-vous?

52
répondu Iker Jimenez 2008-10-20 10:52:18

si vous utilisez le ressort vous pouvez:

1) Créer un fichier de configuration log4j, par exemple" /WEB-INF/classes/log4j-myapp.propriété" Ne l'appelez pas " log4j.propriétés "

exemple:

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

nous allons définir "myWebapp-instance-root" plus tard sur le point (3)

2) spécifiez l'emplacement de la configuration dans web.xml:

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

3) préciser un unique nom de la variable pour la racine de votre webapp, par exemple "myWebapp-instance-root "

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

4) Ajouter un Log4jConfigListener:

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

Si vous choisissez un nom différent, n'oubliez pas de le changer dans log4j-myapp.les propriétés aussi.

Voir mon article (en italien seulement... mais il doit être compréhensible): http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring

UPDATE (2009/08/01) J'ai traduit mon article en anglais: http://www.megadix.it/node/136

14
répondu Megadix 2009-08-01 09:50:41

Juste un commentaire sur Iker solution.

ServletContext est une bonne solution pour votre problème. Mais je ne pense pas que ce soit bon pour le maintien. La plupart des fichiers de journalisation doivent être sauvegardés longtemps.

puisque ServletContext fait le fichier sous le fichier déployé, il sera supprimé lorsque le serveur est redéployé. Je suggère d'utiliser le dossier parent de rootPath au lieu du premier enfant.

6
répondu lizi 2017-05-23 12:34:30

ne se connecte pas à log4j en utilisant simplement le répertoire racine de L'application si vous ne spécifiez pas de répertoire racine dans la propriété fileappender path? Vous devez donc pouvoir utiliser:

log4j.appender.fichier.File=logs / Myrog.log

Cela fait longtemps que je n'ai pas fait de développement Web Java, mais cela semble être le plus intuitif, et ne se heurte pas non plus à d'autres logs malheureusement nommés qui écrivent à ${catalina.home}/répertoire logs.

4
répondu Spencer Kormos 2008-10-20 15:20:39

si vous utilisez Maven, j'ai une excellente solution pour vous:

  1. éditez votre pom.le fichier xml doit inclure les lignes suivantes:

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

    ici, vous définissez logDirectory propriété spécifique à la famille OS.

  2. Utilisation déjà définie logDirectory propriété dans log4j.properties fichier:

    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. C'est ça!

P.S.: je suis sûr que cela peut être réalisé en utilisant Ant, mais malheureusement je n'ai pas assez d'expérience avec elle.

1
répondu alex.antaniuk 2013-04-17 18:55:52

ma suggestion est que le fichier journal doit toujours être journalisé au-dessus du contexte racine de la webApp, donc dans le cas où nous redéployons la webApp, nous ne voulons pas outrepasser les fichiers journaux existants.

1
répondu user553633 2013-09-11 15:07:45

comme commentaire supplémentaire sur https://stackoverflow.com/a/218037/2279200 - cela peut casser, si l'application Web démarre implicitement D'autres Servlettextlistener's, qui peuvent être appelés plus tôt et qui essayent déjà d'utiliser log4j - dans ce cas, la configuration de log4j sera lue et analysée avant que la propriété déterminant le répertoire racine du journal ne soit définie => les fichiers journaux apparaîtront quelque part au-dessous du répertoire courant (le répertoire courant au début tomcat).

Je ne pouvais que penser à suivre la solution à ce problème: - renommez votre log4j.Propriétés (ou logj4.xml) vers quelque chose que log4j ne lira pas automatiquement. - Dans votre filtre de contexte, après avoir défini la propriété, appelez la classe DOM / PropertyConfigurator helper pour vous assurer que votre log4j -.{xml,propriétés} est lu - Réinitialiser la configuration log4j (IIRC il y a une méthode pour le faire)

C'est un peu la force brute, mais il me semble que c'est le seul moyen de le rendre étanche à l'eau.

1
répondu Wolfgang Liebich 2017-05-23 11:54:51

ma solution est similaire à la solution D'Iker Jimenez , mais au lieu d'utiliser System.setProperty(...) j'utilise org.apache.log4j.PropertyConfigurator.configure(Properties) . Pour cela, j'ai aussi besoin que log4j ne puisse pas trouver sa configuration par elle-même et que je la charge manuellement (deux points décrits dans la réponse de Wolfgang Liebich "1519120920 ).

cela fonctionne pour Jetty et Tomcat, standalone ou run à partir D'IDE, nécessite une configuration zéro, permet de mettre les journaux de chaque application dans leur propre dossier, peu importe le nombre d'applications à l'intérieur du conteneur (qui est le problème avec la solution System ). De cette façon, on peut aussi mettre le fichier de configuration log4j n'importe où dans l'application web (par exemple, dans un projet, nous avions tous les fichiers de configuration dans WEB-INF/ ).

détails:

  1. j'ai mes propriétés dans le fichier log4j-no-autoload.properties dans classpath (par exemple dans mon projet Maven c'est à l'origine dans src/main/resources , gets conditionnés en WEB-INF/classes ),
  2. il a le fichier appender configuré comme par exemple:

    log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender
    log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log
    ...
    
  3. et j'ai un écouteur de contexte comme celui-ci (qui devient beaucoup plus court avec la syntaxe" 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(...)
        }
        ...
    }
    
1
répondu starikoff 2017-05-23 12:10:38

vous pouvez spécifier le chemin relatif vers le fichier journal, en utilisant le répertoire de travail :

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

ceci est indépendant du conteneur servlet et ne nécessite pas de passer la variable personnalisée à l'environnement du système.

1
répondu Dimitar II 2017-04-17 22:01:25