Un guide sur les ajouts de fichiers mobiles

1. Vue d'ensemble

Bien que les fichiers journaux véhiculent souvent des informations utiles, ils grossissent naturellement avec le temps, et s'ils sont autorisés à croître indéfiniment, leur taille pourrait devenir un problème.

Les bibliothèques de journalisation résolvent ce problème en utilisant des ajouts de fichiers en continu, qui «roulent» ou archivent automatiquement le fichier journal actuel et reprennent la journalisation dans un nouveau fichier lorsque certaines conditions prédéfinies se produisent, évitant ainsi les temps d'arrêt indésirables.

Dans cet article, nous allons explorer comment configurer des appenders de fichiers en continu dans certaines des bibliothèques de journalisation les plus utilisées - Log4j, Log4j2 et Slf4j.

Nous montrerons comment rouler les fichiers journaux en fonction de la taille, de la date / heure et d'une combinaison de taille et de date / heure. Nous montrerons également comment configurer chaque bibliothèque pour compresser automatiquement et supprimer plus tard les anciens fichiers journaux, nous évitant ainsi d'écrire du code d'entretien fastidieux.

2. Notre exemple d'application

Commençons par un exemple d'application qui enregistre certains messages. Ce code est basé sur Log4j mais il peut être facilement modifié pour fonctionner avec Log4j2 ou Slf4j:

import org.apache.log4j.Logger; public class Log4jRollingExample { private static Logger logger = Logger.getLogger(Log4jRollingExample.class); public static void main(String[] args) throws InterruptedException { for(int i = 0; i < 2000; i++) { logger.info("This is the " + i + " time I say 'Hello World'."); Thread.sleep(100); } } }

L'application est assez naïve - elle écrit certains messages en boucle, avec un court délai entre les itérations. Avec 2000 boucles à exécuter et une pause de 100 ms dans chaque boucle, l'application devrait prendre un peu plus de trois minutes pour se terminer.

Nous utiliserons cet exemple pour illustrer plusieurs fonctionnalités de différents types d'appendeurs de fichiers de roulement.

3. Appendeurs de fichiers déroulants dans Log4j

3.1. Dépendances de Maven

Tout d'abord, pour utiliser Log4j dans votre application, ajoutez cette dépendance au fichier pom.xml de votre projet :

 log4j log4j 1.2.17  

Pour utiliser les ajouts supplémentaires fournis par apache-log-extras que nous utiliserons dans les exemples suivants, ajoutez la dépendance suivante, en veillant à utiliser la même version que nous avons déclarée pour Log4j afin de garantir une compatibilité totale:

 log4j apache-log4j-extras 1.2.17  

Vous pouvez trouver la dernière version de Log4j et Apache Log4j Extras sur Maven Central.

3.2. Déplacement en fonction de la taille du fichier

Dans Log4j, comme dans les autres bibliothèques de journalisation, le roulement de fichier est délégué à l'appender. Examinons la configuration d'un ajout de fichier roulant dans Log4j qui roule en fonction de la taille du fichier:

Ici, nous avons configuré Log4j pour rouler le fichier journal lorsque sa taille atteint 5 Ko, à l'aide du paramètre MaxFileSize . Nous avons également demandé à Log4j de conserver un maximum de deux fichiers journaux cumulés à l'aide du paramètre MaxBackupIndex .

Lorsque nous avons exécuté notre exemple d'application, nous avons obtenu les fichiers suivants:

27/11/2016 10:28 138 app.log 27/11/2016 10:28 5.281 app.log.1 27/11/2016 10:28 5.281 app.log.2 

Qu'est-il arrivé? Log4j a commencé à écrire dans le fichier app.log . Lorsque la taille du fichier dépassait la limite de 5 Ko, Log4j déplaçait app.log vers app.log.1 , créait un tout nouveau app.log vide et continuait d'écrire de nouveaux messages de journal dans app.log .

Ensuite, une fois que le nouveau app.log a dépassé la limite de 5 Ko, ce processus de roulement a été répété. Cette fois, app.log.1 a été déplacé vers app.log.2, laissant de la place pour un autre nouveau app.log vide .

Le processus de roulement a été répété plusieurs fois pendant l'exécution, mais comme nous avons configuré notre appender pour conserver au plus deux fichiers laminés, il n'y a pas de fichier appelé app.log.3 .

Nous avons donc résolu l'un des problèmes d'origine car nous sommes maintenant en mesure de définir une limite sur la taille des fichiers journaux produits.

D'autre part, lorsque nous avons vérifié la première ligne de app.log.2 , elle contenait le message lié à la 700e itération, ce qui signifie que tous les messages du journal précédents avaient été perdus:

2016-11-27 10:28:34 INFO This is the 700 time I say 'Hello World'. 

Voyons si nous pouvons proposer une configuration mieux adaptée à un environnement de production, où la perte de messages de journal ne peut pas être considérée comme la meilleure approche.

Pour ce faire, nous allons utiliser d'autres appenders Log4j plus puissants, flexibles et configurables, livrés dans un package dédié appelé apache-log4j-extras .

Les ajouts contenus dans cet artefact offrent de nombreuses options pour affiner le roulement du journal et introduisent les concepts distincts de politique de déclenchement et de politique de roulement . La politique de déclenchement décrit quand un roulement doit se produire, tandis que la politique de roulement décrit comment le roulement doit être effectué. Ces deux concepts sont essentiels pour les fichiers journaux de roulement et sont également utilisés plus ou moins explicitement par d'autres bibliothèques, comme nous le verrons bientôt.

3.3. Roulage avec compression automatique

Revenons à l'exemple Log4j et améliorons notre configuration en ajoutant la compression automatique des fichiers roulés pour économiser de l'espace:

Avec l' élément de politique de déclenchement , nous avons déclaré que le roulement devrait se produire lorsque le journal dépasse la taille de 5 120 octets.

Dans la balise de stratégie de roulement , le paramètre ActiveFileName indique le chemin des fichiers journaux principaux contenant les derniers messages et le paramètre FileNamePattern spécifie un modèle décrivant quel doit être le chemin des fichiers laminés. Notons qu'il s'agit bien d'un modèle car l'espace réservé spécial % i sera remplacé par l'index du fichier roulé.

Notons également que FileNamePattern se termine par une extension « .gz» . Chaque fois que nous utilisons une extension associée à un format compressé pris en charge, nous aurons les anciens fichiers compressés sans effort supplémentaire de notre part.

Maintenant, lorsque nous exécutons l'application, nous obtenons un ensemble différent de fichiers journaux:

03/12/2016 19:24 88 app.1.log.gz ... 03/12/2016 19:26 88 app.2.log.gz 03/12/2016 19:26 88 app.3.log.gz 03/12/2016 19:27 70 app.current.log 

The file app.current.log is where the last logs occurred. Previous logs have been rolled and compressed when their size reached the set limit.

3.4. Rolling Based on Date and Time

In other scenarios, you may want to configure Log4j to roll the files based on the date and time of the log messages instead of the size of the file. In a web application, for instance, you may want to have all the log messages issued in one day in the same log file.

To do that, you can use the TimeBasedRollingPolicy. With this policy, it is mandatory to specify a template for the path of the log file that contains a time-related placeholder. Each time a log message is issued, the appender verifies what the resulting log path would be, and if it differs from the last used path, then a roll will occur. Here's a quick example that configures such an appender:

3.5. Rolling Based on Size and Time

Combining the SizeBasedTriggeringPolicy and the TimeBasedRollingPolicy, you can obtain an appender that rolls based on date/time, and when the size of the file reaches the set limit, it rolls based on size too:

When we ran our application with this setup, we obtained the following log files:

03/12/2016 19:25 234 app.19-25.1481393432120.log.gz 03/12/2016 19:25 234 app.19-25.1481393438939.log.gz 03/12/2016 19:26 244 app.19-26.1481393441940.log.gz 03/12/2016 19:26 240 app.19-26.1481393449152.log.gz 03/12/2016 19:26 3.528 app.19-26.1481393470902.log

The file app.19-26.1481393470902.log is where current logging takes place. As you can see, all the logs in the interval between 19:25 and 19:26 are stored in multiple compressed log files with names starting with “app.19-25″. The “%i” placeholder is replaced by an ever increasing number.

4. Rolling File Appenders in Log4j2

4.1. Maven Dependencies

To use Log4j2 as our preferred logging library, we need to update our project's POM with the following dependency:

 org.apache.logging.log4j log4j-core 2.7 

As usual, you can find the latest version on Maven Central.

4.2. Rolling Based on File Size

Let's change our example application to use the Log4j2 logging libraries and let's explore now how we can set up file rolling based on the size of the log file in the log4j2.xml configuration file:

  %d{yyyy-MM-dd HH:mm:ss} %p %m%n       

In the Policies tag, we specified all the triggering policies we want to apply. OnStartupTriggeringPolicy triggers a roll every time the application starts, which could be useful for stand-alone applications. We then specified a SizeBasedTriggeringPolicy stating that a roll should occur whenever the log file reaches 5KB.

4.3. Rolling Based on Date and Time

Using the policies offered by Log4j2, let's set up an appender to roll and compress the log file based on time:

  %d{yyyy-MM-dd HH:mm:ss} %p %m%n    

Here the key is the use of TimeBasedTriggeringPolicy that allows us to use time-related placeholders in the template of the rolled file names. Note that since we needed only a single triggering policy, we do not have to use the Policies tag as we did in the previous example.

4.4. Rolling Based on Size and Time

As previously described, a more compelling scenario is to roll and compress log files based on both time and size. Here is an example of how we can set up Log4j2 for this task:

  %d{yyyy-MM-dd HH:mm:ss} %p %m%n             

With this configuration, we stated that a roll should occur based on time and size. The appender is able to understand what time interval we're referring to because of the pattern used for the file name, “app.%d{MM-dd-yyyy-HH-mm}.%i.log.gz”, which implicitly sets a roll to occur every minute and compresses the rolled file.

We also added a DefaultRolloverStrategy to delete old rolled files matching certain criteria. We configure ours to delete files that match the given pattern when they are older than 20 days.

4.5. Maven Dependencies

To use Log4j2 as our preferred logging library, we need to update our project's POM with the following dependency:

 org.apache.logging.log4j log4j-core 2.7 

As usual, you can find the latest version on Maven Central.

5. Rolling File Appenders in Slf4j

5.1. Maven Dependencies

When you want to use Slf4j2 with a Logback backend as logging libraries, add this dependency to your pom.xml:

 ch.qos.logback logback-classic 1.1.7 

As usual, you can find the latest version on Maven Central.

5.2. Rolling Based on File Size

Let's see now how to use Slf4j instead, with its default back-end Logback. Let's explore how we can set up file rolling in the configuration file logback.xml, which is placed in the application's classpath:

 target/slf4j/roll-by-size/app.log  target/slf4j/roll-by-size/app.%i.log.zip 1 3 1MB   5KB   %-4relative [%thread] %-5level %logger{35} - %msg%n   

Again we encounter the concept of rolling policy. The basic mechanism is the same as that used by Log4j and Log4j2. The FixedWindowRollingPolicy allows us to use an index placeholder in the name pattern of the rolled file.

When the size of the log file grows over the configured limit, a new file is allocated, and the old content is stored as the first file of the list, shifting the existing ones one place further.

5.3. Rolling Based on Time

In Slf4j, we can roll a log file based on time using the provided TimeBasedRollingPolicy. This policy allows us to specify the template name of the rolling file using time and date related placeholders:

 target/slf4j/roll-by-time/app.log  target/slf4j/roll-by-time/app.%d{yyyy-MM-dd-HH-mm}.log.zip  20 1MB   %d{yyyy-MM-dd HH:mm:ss} %p %m%n  

5.4. Rolling Based on Size and Time

If you need to roll a file both based on both time and size, you can use the provided SizeAndTimeBasedRollingPolicy. When using this policy, you must specify both a time-related placeholder and an index placeholder.

Chaque fois que la taille du fichier journal pendant un certain intervalle de temps dépasse la limite de taille configurée, un autre fichier journal avec la même valeur pour l'espace réservé lié au temps mais avec un index incrémenté est créé:

 target/slf4j/roll-by-time-and-size/app.log   target/slf4j/roll-by-time-and-size/app.%d{yyyy-MM-dd-mm}.%i.log.zip  5KB 20 1MB   %d{yyyy-MM-dd HH:mm:ss} %p %m%n  

6. Conclusion

Comme nous l'avons vu, l'utilisation d'une bibliothèque de journalisation pour rouler les fichiers vous évite de devoir gérer manuellement les fichiers journaux, vous permettant de vous concentrer sur le développement de votre logique métier. Les ajouts de fichiers roulants sont un outil précieux qui devrait être dans la boîte à outils de chaque développeur.

Comme d'habitude, vous trouverez les sources sur GitHub, où les exemples d'applications présentés dans cet article sont configurés pour se connecter à l'aide de plusieurs configurations de roulement différentes afin de vous permettre de trouver une bonne configuration de base à peaufiner davantage en fonction de vos besoins.