Compression de log Tomcat 6 avec log4j 1.2

Le sujet est largement débattu mais il n’est pas trivial de trouver la solution de bout en bout. Diversité des cas, obsolescence de Tomcat 6 ou de log4j 1.2 ? En tout cas voici comment on peut mettre en place la compression de log de Tomcat 6 à l’aide de log4j 1.2.15 !

D’abord pourquoi mettre en place de la compression de log ? La log de Tomcat (ex catalina.out) ne devrait contenir que peu de messages et seulement de rare erreurs, non ? La diversité des programmeurs peut amener ces log à grossir et les framework qui génèrent des URL mal formées existent (caractère illégal). La rotation des fichiers de log si elle limite la taille ne permet pas de garder un historique c’est pourquoi je lui préfère la compression.

La documentation de Tomcat 6 permet de mettre en place rapidement log4j 1.2.17 et de disposer de la log de  Tomcat configurée par un fichier log4j.properties. L’activation de la compression des log se fait par l’utilisation de l’appender RollingFileAppender mais il ne s’agit pas de celui du paquet log4j mais plutôt du sous-paquet rolling (en gras dans l’exemple suivant). Ensuite il faut choisir la politique de rotation basée sur le temp TimeBasedRollingPolicy et enfin en spécifiant un motif de nom de fichier avec extension gz ou zip, le fichier sera compressé. Pour tester immédiatement la compression des log catalina.out, vous pouvez utiliser le fichier de configuration suivant où le niveau de log est passé à DEBUG et génère un fichier compressé par seconde.

log4j.rootLogger=DEBUG, CATALINA

# Define all the appenders
log4j.appender.CATALINA=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.CATALINA.File=${catalina.base}/logs/catalina.
log4j.appender.CATALINA.RollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy
log4j.appender.CATALINA.RollingPolicy.ActiveFileName =${catalina.base}/logs/catalina.log
log4j.appender.CATALINA.RollingPolicy.FileNamePattern=${catalina.base}/logs/catalina.%d{yyyyMMdd.HHmmss}.gz
log4j.appender.CATALINA.Append=true
log4j.appender.CATALINA.Encoding=UTF-8
log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout
log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.LOCALHOST=org.apache.log4j.DailyRollingFileAppender
log4j.appender.LOCALHOST.File=${catalina.base}/logs/localhost.
log4j.appender.LOCALHOST.Append=true
log4j.appender.LOCALHOST.Encoding=UTF-8
log4j.appender.LOCALHOST.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.LOCALHOST.layout = org.apache.log4j.PatternLayout
log4j.appender.LOCALHOST.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.MANAGER=org.apache.log4j.DailyRollingFileAppender
log4j.appender.MANAGER.File=${catalina.base}/logs/manager.
log4j.appender.MANAGER.Append=true
log4j.appender.MANAGER.Encoding=UTF-8
log4j.appender.MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.HOST-MANAGER=org.apache.log4j.DailyRollingFileAppender
log4j.appender.HOST-MANAGER.File=${catalina.base}/logs/host-manager.
log4j.appender.HOST-MANAGER.Append=true
log4j.appender.HOST-MANAGER.Encoding=UTF-8
log4j.appender.HOST-MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.HOST-MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.HOST-MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

# Configure which loggers log to which appenders
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=INFO, LOCALHOST
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager]=\
  INFO, MANAGER
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager]=\
  INFO, HOST-MANAGER

Cette configuration fonctionne avec log4j 1.2.17 mais pas seulement. En remplaçant le jar log4j.jar par celui de la version 1.2.16, cela fonctionne aussi. En rétrogradant en version 1.2.15 il faudra utiliser un fichier de configuration au format XML (car le support du fichier dde conf en propriété a été introduit dans la version suivante 1.2.16). Voici un exemple de fifichier de configuration au format XML:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="//jakarta.apache.org/log4j/">
  <appender name="console"> 
      <param name="file" value="${catalina.base}/logs/catalina."/>        
       <rollingPolicy>
      <param name="FileNamePattern" value="${catalina.base}/logs/catalina.%d{yyyyMMdd.HHmmss}.gz"/>
      <param name="ActiveFileName" value="${catalina.base}/logs/catalina.log" />
    </rollingPolicy>
    <layout> 
      <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/> 
    </layout> 
  </appender> 

  <root> 
    <priority value ="debug" /> 
    <appender-ref ref="console" /> 
  </root>
  
</log4j:configuration>

Comment faire passser les gros gateaux (Big cookies) ?

Au début de ma carrière en pleine bulle internet, tout le monde autour de moi pronait la gestion des sessions web des utilisateur par le serveur. L’utilisation de cookies n’était pas une pratique en odeur de sainteté à cause des limitations imposé par le navigateur. Ainsi les framework que j’ai utilisé ou développé se contentaient de laisser le conteneur web soit poser un cookie de session (quelques octets) soit si le client n’acceptait pas de cookie de passer une paramètre d’url.

J’ai trouvé à l’époque que la spécification des session par les Servlet était amplement suffisante dans la plupart des cas et que dans certaines circonstances, s’appuyer sur les mécanisme existant quitte à les étendre par des sessions en base de données, offrait une solution robuste et fiable.

De nos jours plus personne ne développe de framework propriétaire. Donc lorsque l’on rentre sur un nouveau projet soit il utilise un framework du marché qui est alors passé indubitablement par le choix des sessions côté serveur, soit on utilise un framework propriétaire. Dans ce dernier cas vous pouvez être amené à devoir utiliser massivement les cookies.

Voici donc quelque conseille pour faire passer les gros gâteaux.

Tout d’abord il faut augmenter la taille du header http que le serveur sera capable de gérer. Dans la configuration d’apache cela se traduit par la directive LimitRequestFieldsize dans le fichier httpd.conf . Si vous utililsez tomcat il faudra ajouter une valeur plus grande que les 4096 par défaut à l’attribut maxHttpHeaderSize du connecteur HTTP. Par contre si vous utilisez un connecteur AJP pour relier un apache à un tomcat, vous devrez sans doute jouer du paramètre packetSize du connecteur AJP pour spécifier une valeur supérieur aux 8192 par défaut. Pensez alors également à modifier également le fichier workers.properties de apache pour changer la valeur due paramètre max_packet_size du worker qui pointe vers le connecteur AJP.

Voilà en somme les quelques ingrédients essentiels qui donneront du goût à votre cuisine et fairont passer les gros gateaux !