Gestion des logs sous Spring Boot
Spring Boot offre un panel d’outils très intéressant pour la mise en production et le suivi applicatif. Ce qui nous intéresse ici plus particulièrement c’est la gestion des logs et la manière de pouvoir les consulter facilement et de manière sécurisé depuis un appel HTTP. Pour cela nous allons nous aider de deux composants:
- Le framework de logging LogBack pour la gestion des logs de sortie
- L’outil de monitoring et de management Actuator
LogBack
Initialisation
LogBack est nativement incorporé dans Spring Boot via la dépendance spring-boot-starter
, elle même incorporée dans toute dépendance de type starter comme celle que nous utilisons: spring-boot-starter-web
. Logback utilise SLF4J (Simple Logging Facade for Java) comme interface native et s’implémente de la manière suivante dans une classe Java:
package com.ingeniance.appformation.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class LoggingController {
Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping("/")
public String index() {
logger.trace("A TRACE Message");
logger.debug("A DEBUG Message");
logger.info("An INFO Message");
logger.warn("A WARN Message");
logger.error("An ERROR Message");
return "This is a logging example controller.";
}
}
Vous pouvez maintenant retrouver toutes ces informations dans votre console à l’exécution de votre application Java.
Passons maintenant à l’étape suivante qui est d’externaliser vers un fichier le résultat de ces logs.
Configuration
LogBack incorpore un fichier de configuration qui peut utiliser les propriétés de l’environnement de Spring. Pour cela il suffit d’avoir dans notre classpath
un fichier nommé de la manière suivante : logback-spring.xml
. Il faut ensuite ajouter dans notre application.yml
les éléments suivants :
logging:
path: logs
file: ${logging.path}/myapplication.log
level:
root: WARN
org.springframework.web: ERROR
com.ingeniance: TRACE
org.hibernate: ERROR
pattern:
console: "%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable"
file: "%d %p %C{1.} [%t] %m%n"
L’élément important à retenir ici est la définition de logging.file
qui indique à Spring Boot de gérer un fichier de log.
level
définit le niveau de log pour chaque dépendance listée.pattern
permet d’appliquer un format d’affichage des logs pour chaque support de sortie ainsi qu’une colorisation syntaxique dans le cas d’une sortie Console.
Notre sortie Console aura cette fois l’allure suivante :
Remarquez l’utilisation des paramètres Spring pour injecter le path dans logging.file
.
Spring Boot offre également de définir un niveau de log par défaut, surchargeable par ceux définit dans notre application.properties
. Il suffit de déclarer l’injection de la ressource suivante dans notre fichier logback-spring.xml
<include resource="org/springframework/boot/logging/logback/base.xml"/>
Pour notre besoin final, nous devons pouvoir paramétrer des logs pouvant être archivés via une rolling policy et suivant un format et des règles bien précises. Notre fichier logback-spring.xml
aura alors la forme suivante:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
</layout>
</appender>
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</encoder>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily and when the file reaches 5 MegaBytes -->
<fileNamePattern>${LOG_PATH}/archived/apt_%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
</configuration>
Attention cependant, dans notre cas nous utilisons application.properties
pour définir un certains nombres de paramètres dont notamment logging.file
. Vous allez retrouver dans de nombreux tutoriaux le path du fichier de log a placer dans votre fichier logback-spring.xml
de la manière suivante :
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>myapplication.log</file>
...
Ceci est à proscrire si vous ne voulez pas générer un conflit de déclaration entre application.properties
et le fichier de configuration de Logback.
Nous n’avons survolé qu’une petite partie des possibilités offertes par Logback, mais vous avez également la possibilité de définir des niveaux de logs en fonction des environnements, ou plus finement en fonction des dépendances par type de sortie.
Actuator
Maintenant que nous avons un fichier de logs maintenu dans notre application, il serait appréciable de pouvoir le consulter depuis notre environnement de production dans le cas où un bug applicatif aurait été détecté. Spring Boot dispose d’un outil de monitoring nommé Actuator. Dans notre cas, il va nous servir à exposer le contenu de nos fichiers de logs depuis une requête HTTP sécurisée.
Initialisation
Vous devez dans un premier temps importer la dépendance d’Actuator. Sous Maven importez la dépendance starter de la manière suivante :
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
Actuator met à disposition tout un tas de services définis par des endpoints et accessibles par défaut depuis l’URL: http://localhost:<port>/actuator/<endpoint>. Le endpoint qui nous intéresse est logfile
qui affiche le fichier de logs défini depuis la propriété logging.file
.
Depuis application.yml
ajoutez la configuration suivante :
endpoints:
enabled: false
logfile:
enabled: true
management:
context-path: /management
security:
enabled: false
roles: ROLE_ADMIN
Plusieurs notions sont abordées ici.
endpoints.enabled
désactive l’ensemble des endpoints d’Actuator, évitant ainsi l’affichage d’informations sensibles.endpoints.logfile.enabled
permet en revanche d’activer uniquement celui-ci.management.context-path
permet de modifier l’URL par défaut par celle-ci: http://localhost:<port>/management/<endpoint>.management.security.enabled
permet de désactiver la gestion de sécurité par Actuator et permet de la déporter vers celle utilisée par notre application.management.security.roles
permet d’ajouter des rôles supplémentaires pour l’accès aux endpoints. Par défaut, le rôle définit estACTUATOR
.
Faites attention cependant car la configuration spécifiée précédemment est celle sous Spring Boot 1.X. Dans le cas de Spring Boot 2.X, un remaniement des paramètres est à prévoir :
management:
endpoint:
logfile:
enabled: true
endpoints:
enabled-by-default: false
web:
base-path: /management
exposure:
include: "*"
security:
enabled: false
roles: ROLE_ADMIN
Sécurisation
Actuator est maintenant configuré et permet d’afficher depuis une URL notre fichier de logs. Nous avons ajouté un rôle d’administration et indiqué la prise en main de la sécurité par un composant externe. Pour surcharger les règles d’accès à notre application il suffit d’ajout un @Bean
de type WebSecurityConfigurerAdapter
et d’ajouter @Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
pour surcharger les règles de sécurité d’Actuator (ce dernier point n’est plus nécessaire sous Spring Boot 2.X).
@Configuration
@EnableWebSecurity
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
}
}
Nous indiquons ainsi que toute personne essayant d’accéder à l’URL http://localhost:<port>/management/ doit posséder un rôle de type ADMIN
.
Conclusion
Vous avez vu dans cet article:
- Le moyen de mettre en place des loggings au sein d’une application Java.
- D’améliorer l’affichage dans la Console et de modifier le niveau de vos logs par dépendance.
- D’externaliser et d’archiver de manière efficace les logs à l’aide de LogBack.
- D’installer Actuator pour consulter les logs depuis un appel HTTP de manière sécurisée.
Ressources
- Documentation Spring Boot 2.1.X / Logging: https://docs.spring.io/spring-boot/docs/2.1.x/reference/htmlsingle/#boot-features-logging
- Documentation Spring Boot 1.5.X / Actuator: https://docs.spring.io/spring-boot/docs/1.5.x/reference/htmlsingle/#production-ready
- Documentation Spring Boot 2.1.X / Actuator: https://docs.spring.io/spring-boot/docs/2.1.x/reference/htmlsingle/#production-ready