Este tutorial explica cómo personalizar la generación de logs en Spring Boot para poder explotarlos de manera cómoda y efectiva.
Índice de contenidos
- 1. Introducción
- 2. Entorno
- 3. Logging en Spring Boot
- 4. Personalización de Logback
- 4.1. Ficheros implicados
- 4.2. Contenidos de los ficheros
- 4.3. Configuración por perfil
- 5. Un caso práctico
- 6. Conclusiones
- 7. Referencias
1. Introducción
Spring Boot además de un framework de desarrollo de aplicaciones Java orientadas a microservicios, es un entorno de ejecución completo y autocontenido para nuestras aplicaciones.
Cuando ejecutamos una aplicación Spring Boot, las opciones de logging por defecto pueden ser suficientes en un
entorno de desarrollo, pero obviamente en producción se quedan cortas y es necesario controlar qué log se genera y cómo y dónde se guarda.
El objetivo es ser más efectivos a la hora de detectar, identificar y diagnosticar problemas en las aplicaciones
que están en un entorno de pruebas, preproducción o producción.
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro Retina 15′ (2.5 Ghz Intel Core i7, 16GB DDR3).
- Sistema Operativo: Mac OS Yosemite 10.10
- Entorno de desarrollo: Eclipse MARS.2
- Spring Boot 1.3.3
- Apache Maven 3.3.9
3. Logging en Spring Boot
Spring Boot es muy flexible a la hora de configurar cómo se gestionan los logs.
Esto era de esperar porque a buen seguro cualquier aplicación va a depender de un buen número de librerías,
que a su vez probablemente dependerán de diferentes utilidades de logging.
Afortunadamente, en la actualidad no hay (o no suele haber) dependencias directas con utilidades de logging concretas,
sino con fachadas (patrón facade o adapter según el caso) que abstraen la implementación
concreta del logging, permitiendo además intercambiar implementaciones con bastante facilidad.
Las fachadas más conocidas son commons-logging
y slf4j
(Simple Logging Facade for Java).
El propio Spring utiliza internamente commons-logging
para sus mensajes de log, pero muchas otras librerías
dependen de slf4j
.
Las implementaciones más populares son Log4j,
Java Util Logging y
Logback.
La configuración por defecto de Spring Boot canaliza a Logback los mensajes enviados a través de las fachadas
commons-logging
y slf4j
siempre y cuando Logback esté presente.
Esto último ocurre de manera automática si nuestra aplicación depende de spring-boot-starter-web
o spring-boot-starter-logging
(POMs de Maven).
Cuando el mensaje llega a Logback pueden ocurrir dos cosas (siempre hablando del comportamiento por defecto):
- Si la propiedad
logging.file
tiene algún valor, se enviarán los mensajes al fichero referenciado
por ese valor, ya sea un nombre simple, una ruta relativa o una ruta absoluta.
El fichero se limpiará cuando alcance un tamaño de 10 MB, pero antes se archivará una copia en el mismo directorio
y con el mismo nombre añadiendo un sufijo numérico. - Si la propiedad
logging.file
no tiene valor, los mensajes se enviarán a la salida estándar.
Además, si la salida estándar es el terminal, los mensajes estarán coloreados.
4. Personalización de Logback
4.1. Ficheros implicados
Logback en Spring Boot busca configuraciones en los ficheros logback.xml
o logback-spring.xml
en las raíces del classpath de la aplicación.
Según esto, la manera más sencilla de personalizar Logback es definir un fichero logback-spring.xml
en el
directorio src/main/resources
de cualquiera de los proyectos que componen nuestra aplicación Spring Boot.
Más adelante se explica qué contiene este fichero.
Para facilitar la personalización, Spring Boot proporciona bajo la ruta org/springframework/boot/logging/logback/
varios ficheros include:
defaults.xml
Establece colores de la salida por terminal, patrones de mensajes, conversores de excepciones y filtros para algunos paquetes de infraestructura.
Salvo que tengas una muy buena razón, este fichero debe incluirse siempre.console-appender.xml
Define las características de la salida por terminal (las salidas se llaman appenders en la jerga de logging).
Inclúyelo si necesitas sacar mensajes por terminal.file-appender.xml
Define una salida a ficheros que rotan cuando alcanzan un tamaño de 10 MB, sin límite de número de ficheros.
La ruta del fichero debe establecerse en la propiedadlogging.file
, normalmente en el fichero
src/main/resources/application.properties
de alguno de los proyectos de nuestra aplicación.base.xml
Este fichero incluye a los tres anteriores y establece que todos los mensajes se envíen tanto a la terminal
como al fichero.
La idea es que estos ficheros se importen en logback-spring.xml
según los vayamos necesitando.
4.2. Contenidos de los ficheros
Logback distingue el fichero de configuración principal del resto de ficheros incluídos.
El primero se identifica porque su elemento raíz es , mientras que
en los segundos el elemento raíz es .
Por ejemplo, para definir una configuración que sea idéntica a la que proporciona Spring Boot bastaría con
tener el siguiente fichero logback-spring.xml
:
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> </configuration>
Si nos gusta esa configuración pero queremos añadir un filtro de mensajes, podríamos hacer lo siguiente:
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <logger name="org.springframework" level="INFO"/> </configuration>
Aquí es necesario hacer un pequeño inciso.
En las utilidades de logging, el filtrado de mensajes se basa principalmente en dos criterios:
- Por un lado, el origen del mensaje, o sea, quién ha generado el mensaje, que suele
ser una clase Java identificada por su ruta completa (paquete + nombre). - Por otro lado, el nivel del mensaje, es decir, cómo de importante es.
Consiste en un valor enumerado que va de menos importante a más importante: TRACE, DEBUG, INFO, WARN y ERROR.
Así, los filtros más básicos se definen con el elemento , que representa a los mensajes
emitidos por una clase o paquete Java.
En el ejemplo anterior, el filtro sólo deja pasar los mensajes emitidos por el paquete y subpaquetes de
org.springframework
con un nivel de importancia INFO o superior (WARN y ERROR).
Logback tiene muchísimas posibilidades de configuración, pero eso cae fuera del objetivo de este tutorial.
4.3. Configuración por perfil
Uno de los aspectos más interesantes de Logback en Spring Boot es la posibilidad de definir configuraciones
de logging diferentes según los perfiles activos en la aplicación.
Los perfiles activos se identifican con la propiedad spring.profiles.active
,
por ejemplo en application.properties
o en los parámetros al arrancar la máquina virtual Java.
Para segregar la configuración de logging según perfil se utiliza el elemento .
Por ejemplo, si deseo que el perfil development
tenga salida por consola y el perfil production
salida a fichero, utilizaría esta configuración:
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- Ya no nos sirve base.xml porque queremos separar consola y fichero según el perfil --> <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <!-- Este filtro se aplica a todos los perfiles --> <logger name="org.springframework" level="INFO"/> <springProfile name="<b>development</b>"> <!-- El perfil "development" define una salida por terminal llamada "CONSOLE" --> <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> <!-- Todos los mensajes serán enviados a la salida llamada "CONSOLE". El filtro por defecto establece un nivel mínimo de "DEBUG". --> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> </root> </springProfile> <springProfile name="<b>production</b>"> <!-- El perfil "production" define una salida a fichero llamada "FILE". La ruta se indica en logging.file o logging.path; si no, se guardará en /tmp/spring.log --> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/> <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> <!-- Todos los mensajes se enviarán a la salida llamada "FILE". El filtro por defecto establece un nivel mínimo de "INFO". --> <root level="INFO"> <appender-ref ref="FILE" /> </root> </springProfile> </configuration>
5. Un caso práctico
En un proyecto real se tomó la decisión de configurar dos salidas de mensajes: por consola para el perfil
development
y por fichero para el resto de perfiles.
Los ficheros rotan diariamente (es decir, cada día se archiva el log generado) y se quieren conservar los registros
de los últimos 20 días.
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- Default config and other properties --> <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/> <!-- Profile independent loggers --> <logger name="com.autentia.myapplication" level="DEBUG"/> <logger name="org.springframework" level="INFO"/> <!-- Development profile --> <springProfile name="<b>development</b>"> <appender name="APPENDER" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>utf8</charset> </encoder> </appender> <logger name="org.springframework.security" level="DEBUG"/> </springProfile> <!-- Staging/production profile --> <springProfile name="<b>!development</b>"> <appender name="APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender"> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <file>${LOG_FILE}</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE}.%d</fileNamePattern> <maxHistory>20</maxHistory> </rollingPolicy> </appender> </springProfile> <!-- Root logger --> <root level="INFO"> <appender-ref ref="APPENDER" /> </root> </configuration>
6. Conclusiones
Spring Boot como plataforma para el desarrollo de microservicios y aplicaciones autocontenidas en Java proporciona una
gran cantidad de servicios y obliga a seguir buenas prácticas que aceleran el desarrollo y mejoran la calidad.
Tratándose de un elemento básico en cualquier aplicación, el logging no podía ser menos como ha quedado explicado aquí.
Por su parte, Logback ha sido desarrollado por el creador original de Log4j tras muchos años de experiencia acumulados.
Sus posibilidades y facilidad de personalización son enormes; no dudes en echarle un vistazo al manual.
Antes de terminar, una buena práctica fundamental: nunca dependas de una librería de logging concreta,
utiliza slf4j
o commons-logging
como APIs de logging en tus aplicaciones.
7. Referencias
- Logging en Spring Boot
- Manual de Logback
- Apache Commons Logging
- SLF4J