A partir de JBoss AS 6, le serveur n’utilise plus Log4J pour ses logs internes, mais sa propre solution de logging : JBoss LogManager. Cette solution est une extension de l’API java.util.logging. Par conséquent, ses concepts sont très proches de ceux de Log4J, avec quelques petites améliorations.
Comme j.u.l et Log4J, JBoss LogManager utilise des Loggers, pour lesquels on configure le niveau (Level) de sortie. Enfin, on configure les éléments de sortie, appelés ici Handlers. Tout ceci se configure dans un fichier jboss-logging.xml dans le répertoire deploy de JBoss.
Configuration
La configuration se fait par un fichier jboss-logging.xml dans le répertoire deploy du profil démarré (default, all,…). Le contenu de ce fichier n’est pas très éloigné de celui d’un fichier de configuration de Log4J, avec un format un peu différent.
Dans la première partie, on configure les handlers, puis les loggers pour finir avec le root-logger. Par défaut, les traces sont envoyées vers la sortie standard (console-handler) et vers le fichier log/server.log, à partir du niveau INFO. Comme pour JBoss AS 5, le répertoire de log peut être modifié avec l’option -Djboss.server.log.dir, ainsi que le niveau avec l’option -Djboss.server.log.threshold.
Loggers
Logger
Pour chaque logger, on spécifie le niveau et, éventuellement, de handlers. En somme, rien de bien différent de Log4J. On retrouve aussi la même notion d’additivity.
<logger category="org.jboss.system.server.Server">
<level name="INFO"/>
<handlers>
<handler-ref name="CONSOLE"/>
</handlers>
</logger>
Root logger
On retrouve aussi le logger racine.
<root-logger>
<level name="${jboss.server.log.threshold:INFO}"/>
<handlers>
<handler-ref name="CONSOLE"/>
<handler-ref name="FILE"/>
</handlers>
</root-logger>
Avec cette configuration, l’option -Djboss.server.log.threshold passée au lancement de JBoss permet de modifier le niveau de sortie global.
Additivité
La notion d’additivity de Log4J se retrouve sous forme d’un attribut use-parent-handlers.
<logger category="org.jboss.bootstrap" use-parent-handlers="false">
<level name="INFO"/>
<handlers>
<handler-ref name="CONSOLE"/>
</handlers>
</logger>
Handlers
Les handlers sont les sorties pour les traces. On retrouve ici le même vocabulaire que pour java.util.logging, mais les techniques ressemblent à celles de Log4J : console, fichier avec rotation périodique, fichier avec rotation sur la taille,… La grande différence avec Log4J est l’utilisation de balises typées.
Console
Pour envoyer les traces dans la sortie standard, on utilise la balise <console-handler>. On peut limiter les traces à un niveau minimum. Les possibilités de mise en forme sont détaillées plus bas.
<console-handler name="CONSOLE" autoflush="true" target="System.out">
<level name="INFO"/>
<formatter>
<pattern-formatter pattern="..."/>
</formatter>
</console-handler>
Fichier à rotation périodique
Pour envoyer les traces dans un fichier et assurer une rotation périodique, on utilise la balise <periodic-rotating-file-handler> et on précise le nom du fichier, le mode ajout / remplacement et le suffixe. Comme pour Log4J, le suffixe est ajouté aux fichiers sauvegardé après la rotation ; il sert aussi à spécifier la période de rotation. Par défaut, la rotation est quotidienne.
<periodic-rotating-file-handler
file-name="${jboss.server.log.dir}/server.log" suffix=".yyyy-MM-dd"
name="FILE" autoflush="true" append="true">
<formatter>
<pattern-formatter pattern="..."/>
</formatter>
</periodic-rotating-file-handler>
Fichier à rotation sur la taille
Pour envoyer les traces dans un fichier et assurer une rotation périodique, on utilise la balise <size-rotating-file-handler> et on précise la taille de chaque fichier et le nombre de fichiers conservés.
<size-rotating-file-handler
file-name="${jboss.server.log.dir}/server.log" rotate-size="500k" max-backup-index="5"
name="FILE" autoflush="true" append="true">
<formatter>
<pattern-formatter pattern="..."/>
</formatter>
</size-rotating-file-handler>
Sortie asynchrone
Pour que les traces sortent sans bloquer le programme, on les fait passer par un handler asynchrone, via la balise <async-handler>. On lui associe ensuite les sorties concrètes.
<async-handler name="ASYNC">
<sub-handlers>
<handler-ref name="FILE"/>
<handler-ref name="CONSOLE"/>
</sub-handlers>
</async-handler>
Gestion des erreurs
Dans chaque handler, on trouve généralement un gestionnaire d’erreur de type <only-once/> qui évite le bégaiement en cas d’erreur de logging.
<foo-handler name="FOO">
<error-manager>
<only-once/>
</error-manager>
...
</foo-handler>
Autres handlers
Il est possible d’intégrer n’importe quel handler qu respecte l’API j.u.l.
<handler name="FOO" class="org.sewatech.logging.handler.MyHandler">
...
</handler>
Appenders Log4J
Enfin, JBoss LogManager est capable de bénéficier de toute la richesse de son ancêtre, car il propose un handler qui redirige vers un appender Log4J.
<log4j-appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
<properties>
<property name="to">admin@admin.sewatech.net</property>
<property name="from">jboss@admin.sewatech.net</property>
<property name="subject">JBoss AS 6 Sever Errors</property>
<property name="SMTPHost">smtp.sewatech.net</property>
<property name="bufferSize">10</property>
</properties>
<formatter>
<pattern-formatter pattern="..."/>
</formatter>
</log4j-appender>
On peut ainsi envoyer les traces vers une base de données, un sujet JMS, le réseau,…
Formatter
Conversions
JBoss LogManager supporte à peut prêt les mêmes formats que le PatternLayout de Log4J. On retrouve la même façon de spécifier le format, avec les mêmes caractères de conversion :
-
c = nom du logger
-
d = date éventuellement formattée selon SimpleDateFormat
-
F = nom du fichier source
-
C = nom de la classe
-
M = nom de la méthode
-
L = n° de ligne
-
l = localisation : fichier source + classe + méthode + n° de ligne
-
m = message avec stacktrace
-
p = niveau
-
r = durée depuis le démarrage
-
t = nom du thread
-
x = NDC
-
X = MDC
-
n = séparateur de ligne
Par exemple, %d %-5p [%c] (%t) %m%n
est compatible avec JBoss LogManager et Log4J.
JBoss LogManager a introduit quelques conversion supplémentaires, en particulier pour mieux afficher les exceptions :
-
s = message sans stacktrace
-
e = stacktrace simple
-
E = stacktrace étendue
Dans le mode étendu, LogManager essaie d’extraire le nom de l’archive et la version d’implémentation ou de spécification correspondant à chaque ligne du stack trace. Cela peut faciliter certains diagnostics, mais peut aussi dégrader les performances en cas de nombreuses stack traces .
Ainsi, le format ` "%d %-5p [%c] (%t) %m%n" ` peut avantageusement être remplacé par ` "%d %-5p [%c] (%t) %s%E%n" ` ou ` "%d %-5p [%c] (%t) %s%e%n" `.
Il me reste encore un caractère à étudier :
-
k = clé de ressource === Segments
Les conversions %c et %C sont à segments, c’est-à-dire qu’elles sont constituées de mots séparés par des caractères '.'. Pour ce type de conversion, on peut sélectionner les n derniers mots : ` "%c{1}" `.
Justification
Toutes les conversions sont justifiable. Plus précisément, elles peuvent être justifiée, tronquées et alignées. Là aussi, la façon de spécifier le format ressemble énormément à Log4J : ` %20.30c ` ou ` %-20.30c `. La bonne nouvelle, c’est que la façon de tronquer est différente de celle de Log4J. En effet, avec ` %.30m `, LogManager conserve le début du message alors que Log4J en conservait la fin.
Filtres
Comme dans java.util.logging, il est possible de filtrer les logs au niveau des handlers ou des loggers (bien que pour ces derniers, je n’ai pas réussi à les faire fonctionner).
JBoss LogManager fournit une série de filtres, avec les balises qui correspondent.
-
accept
-
deny
-
match : correspond
<filter>
<match pattern="Started"/>
</filter>
-
level
<filter>
<level level="INFO"/>
</filter>
-
level-range
<filter>
<level-range min-level="DEBUG" max-level="WARN"/>
</filter>
Il fournit aussi des filtres pour combiner d’autres filtres.
-
not
-
all
-
any
Enfin, il fournit des filtres de transformation.
-
replace
-
change-level
Utilisation autonome
JBoss LogManager peut être utilisé comme logger pour n’importe quelle application. Pour cela, il faut configurer l’application pour que celui-ci remplace le LogManager de java.util.logging. La configuration se fait alors dans un fichier logging.properties standard. Celui contenu dans bin/run.jar de JBoss AS 6 peut servir d’exemple.
Conclusion
JBoss AS 6 n’utilise plus Apache Log4J, mais JBoss LogManager. Les concepts sont les mêmes, mais la configuration change légèrement. JBoss LogManager peut utiliser Log4J, mais n’en dépend que de façon optionnelle.
Pour plus de détails, le meilleur endroit, au moment ou j’écris ces lignes, est le schéma du fichier (/deployers/jboss-logging.deployer/logging-service-metadata.jar/META-INF/schema).