Registro del AccessLog en ElasticSearch vía TCP de un microservicio Spring Boot 2
El Access Log es un log de todas las peticiones HTTP que recibe un servidor web en las que principalmente se registra el endpoint, tiempo de respuesta, http headers, http status code y otras informaciones con el detalle de la request y response de dicha llamada.
En un modelo de microservicios con Spring Boot MVC se levanta un servidor web embebido de tipo Tomcat, Jetty o Undertow, el cual se le puede configurar la generación de logs de tipo Access Log y tener así un registro de todas las peticiones que reciba dicho microservicio.
Por defecto, Spring Boot no genera logs de dicha tipología, dejando únicamente la generación de logs aplicativos generados a partir de un Logger.
En dicho post se quiere mostrar como generar un Access Log por cada microservicio implementado con Spring Boot 2 y realizar el envío de este sobre TCP a un sistema ELK. Todo el código fuente y configuraciones se pueden encontrar en el siguiente repositorio.
https://bitbucket.org/jrovirablog/springboot_tomcat_logs_to_elk/src/master/
El primer paso de todos es configurar nuestro pom.xml con las siguientes dependencias.
La primera de todas corresponde con un Appender que permite envío de logs sobre TCP a Logstash. Para más información sobre dicho Appender, se puede consultar la siguiente entrada del blog.
http://joelrovira.blogspot.com/2019/02/envio-de-logs-en-spring-boot-2-elk.html
La segunda dependencia nos sirve para activar la generación del Access Log.
El siguiente paso es inyectar en el Spring Context un par de Beans a través de una clase @Configuration como podemos ver a continuación.
Se ha añadido un @Profile en dicha clase que nos permita activar o desactivar la generación de Access Log dependiendo de si activamos o no el Spring Profile en el arranque del microservicio.
El fichero de configuración de Access Log en formato Logback lo añadiremos en el directorio conf/ dentro del src/main/resources. Si no se indica en dicho directorio, la generación de Access Log no se realizará. El contenido del fichero es el siguiente.
El Appender usado lo indicamos en el class y se puede encontrar más información sobre dicho Appender en:
https://github.com/logstash/logstash-logback-encoder
El tag fieldNames es opcional, pero si lo incluimos nos permite registrar también las headers de entrada/salida. Queda bajo consideración de cada uno, si es viable incluir dicha información en un entorno productivo.
También hemos añadido un campo nuevo llamado log_type que nos permitirá posteriormente en Logstash discriminar el tipo de log que estamos tratando y poder añadirlo en un índice u otro de Elastic Search.
Observemos que el tag destination nos permite configurar el host y puerto de Logstash donde mandaremos sobre TCP los logs.
Para la parte de logs aplicativos, únicamente mencionar que también añadimos el nuevo campo "log_type" con el valor "log" para que Logstash pueda discriminar si está tratando un registro de log o de acces log.
Con todos estos pasos, únicamente queda arrancar el microservicio pasándole como argumento el spring profile "--spring.profiles.active=accesslog" par activar la generación de Access Log.
La configuración de Logstash para poder crear los índices de Elastic Search es la siguiente.
Como podemos observar, la generación de los índices se realiza en base al valor que hemos informado en el nuevo campo "log_type".
Si queremos visualizar los logs generados en nuestra aplicación en Kibana, solamente nos faltaría crear los Index Pattern correspondientes a las dos tipologías de logs que estamos registrando; log-* y access-*.
En un modelo de microservicios con Spring Boot MVC se levanta un servidor web embebido de tipo Tomcat, Jetty o Undertow, el cual se le puede configurar la generación de logs de tipo Access Log y tener así un registro de todas las peticiones que reciba dicho microservicio.
Por defecto, Spring Boot no genera logs de dicha tipología, dejando únicamente la generación de logs aplicativos generados a partir de un Logger.
En dicho post se quiere mostrar como generar un Access Log por cada microservicio implementado con Spring Boot 2 y realizar el envío de este sobre TCP a un sistema ELK. Todo el código fuente y configuraciones se pueden encontrar en el siguiente repositorio.
https://bitbucket.org/jrovirablog/springboot_tomcat_logs_to_elk/src/master/
El primer paso de todos es configurar nuestro pom.xml con las siguientes dependencias.
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>
La primera de todas corresponde con un Appender que permite envío de logs sobre TCP a Logstash. Para más información sobre dicho Appender, se puede consultar la siguiente entrada del blog.
http://joelrovira.blogspot.com/2019/02/envio-de-logs-en-spring-boot-2-elk.html
La segunda dependencia nos sirve para activar la generación del Access Log.
El siguiente paso es inyectar en el Spring Context un par de Beans a través de una clase @Configuration como podemos ver a continuación.
@Configuration
@Profile("accesslog")
public class AccessLogConfiguration {
@Bean(name = "TeeFilter")
public Filter teeFilter() {
return new ch.qos.logback.access.servlet.TeeFilter();
}
@Bean
public TomcatServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
// put logback-access.xml in src/main/resources/conf
tomcat.addContextValves(new LogbackValve());
return tomcat;
}
}
Se ha añadido un @Profile en dicha clase que nos permita activar o desactivar la generación de Access Log dependiendo de si activamos o no el Spring Profile en el arranque del microservicio.
El fichero de configuración de Access Log en formato Logback lo añadiremos en el directorio conf/ dentro del src/main/resources. Si no se indica en dicho directorio, la generación de Access Log no se realizará. El contenido del fichero es el siguiente.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="LOGSTASH_ACCESS" class="net.logstash.logback.appender.LogstashAccessTcpSocketAppender">
<destination>localhost:5044</destination>
<reconnectionDelay>5 second</reconnectionDelay>
<encoder class="net.logstash.logback.encoder.LogstashAccessEncoder">
<includeCallerData>false</includeCallerData>
<includeContext>false</includeContext>
<shortenedLoggerNameLength>36</shortenedLoggerNameLength>
<fieldNames>
<requestHeaders>request_headers</requestHeaders>
<responseHeaders>response_headers</responseHeaders>
</fieldNames>
<customFields>
{
"log_type": "access"
}
</customFields>
</encoder>
</appender>
<appender-ref ref="LOGSTASH_ACCESS" />
</configuration>
El Appender usado lo indicamos en el class y se puede encontrar más información sobre dicho Appender en:
https://github.com/logstash/logstash-logback-encoder
El tag fieldNames es opcional, pero si lo incluimos nos permite registrar también las headers de entrada/salida. Queda bajo consideración de cada uno, si es viable incluir dicha información en un entorno productivo.
También hemos añadido un campo nuevo llamado log_type que nos permitirá posteriormente en Logstash discriminar el tipo de log que estamos tratando y poder añadirlo en un índice u otro de Elastic Search.
Observemos que el tag destination nos permite configurar el host y puerto de Logstash donde mandaremos sobre TCP los logs.
Para la parte de logs aplicativos, únicamente mencionar que también añadimos el nuevo campo "log_type" con el valor "log" para que Logstash pueda discriminar si está tratando un registro de log o de acces log.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:5044</destination>
<reconnectionDelay>5 second</reconnectionDelay>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeCallerData>false</includeCallerData>
<includeContext>false</includeContext>
<shortenedLoggerNameLength>36</shortenedLoggerNameLength>
<customFields>
{
"log_type": "log"
}
</customFields>
</encoder>
</appender>
<appender name="LOGSTASH_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>500</queueSize>
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="LOGSTASH" />
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>500</queueSize>
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="STDOUT" />
</appender>
<logger name="org.jrovira" level="INFO" additivity="false">
<appender-ref ref="STDOUT_ASYNC" />
<appender-ref ref="LOGSTASH_ASYNC" />
</logger>
<root level="WARN">
<appender-ref ref="STDOUT_ASYNC" />
<appender-ref ref="LOGSTASH_ASYNC" />
</root>
</configuration>
Con todos estos pasos, únicamente queda arrancar el microservicio pasándole como argumento el spring profile "--spring.profiles.active=accesslog" par activar la generación de Access Log.
La configuración de Logstash para poder crear los índices de Elastic Search es la siguiente.
input {
tcp {
port => 5044
codec => json
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "%{[log_type]}-%{+YYYY.MM.dd}"
}
}
Como podemos observar, la generación de los índices se realiza en base al valor que hemos informado en el nuevo campo "log_type".
Si queremos visualizar los logs generados en nuestra aplicación en Kibana, solamente nos faltaría crear los Index Pattern correspondientes a las dos tipologías de logs que estamos registrando; log-* y access-*.
No hay comentarios
Publicar un comentario