Spring Boot e Filebeat localmente sem registro e sms

Neste tutorial, veremos como conectar e configurar um sistema de registro em um projeto Spring Boot e enviar registros para ELK usando Filebeat . Este guia se destina a desenvolvedores iniciantes.



Registro e por que é necessário



Quando comecei a trabalhar como programador, um de meus colegas mais velhos gostava de repetir: "Se você não tem registros, então não tem nada . " De fato, quando nos deparamos com o primeiro bug em bancos de teste ou pior em um ambiente industrial, a primeira coisa de que precisamos são os logs de aplicativos e o fácil acesso a eles. Os próprios logs são os próprios desenvolvedores da aplicação, que devem garantir que o comportamento do sistema seja registrado de forma que a qualquer momento seja possível entender o que está acontecendo com o sistema e, o mais importante, o que há de errado com ele.



A próxima questão é a conveniência de acesso aos logs. Normalmente, durante o teste local, vemos o log no console do aplicativo e na bancada de teste - em arquivos de log especiais no servidor. É conveniente e seguro conectar-se ao suporte todas as vezes, pesquisar o diretório necessário e ler os arquivos de log a partir dele? A prática mostra que não, e este é o segundo problema que uma série de produtos são projetados para resolver, que fornecem acesso conveniente aos logs e busca por informações importantes neles. Hoje vamos falar muito brevemente sobre um dos grupos de tais produtos, a chamada pilha ELK (Elasticsearch - Logstash - Kibana ) e em mais detalhes sobre Filebeat - um produto de código aberto que fornece um mecanismo conveniente para entrega de logs para ELK .



Três linhas sobre ELK



  • Logstash - recebimento, modificação de registros
  • Elasticsearch - armazenamento e pesquisa
  • Kibana - display


O que o Filebeat tem a ver com isso?



O Filebeat fornecerá a entrega de dados para ELK e será implantado próximo ao nosso aplicativo, geralmente é apenas mais conveniente do que configurar o Logstash para ler dados de arquivos de log ou outros canais.



Uma boa abordagem seria implantar um ELK comum para um grupo de microsserviços e, para cada microsserviço, implantar seu próprio Filebeat (especialmente porque não é mais fácil), que lerá os logs de microsserviço e os enviará para o ELK comum .



Tentaremos implementar essa solução posteriormente no ambiente local.





Prática



Java 8

ApacheMaven3.6

Spring Boot 2.3.4.RELEASE

Docker



Spring Boot App



Spring Boot , . /



Spring Boot Spring Initalizr





<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>6.4</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>


  • spring-boot-starter-web — ..
  • logstash-logback-encoder
  • lombok — ,


pom.xml



Spring Boot :



@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}


:



@Slf4j
@Service
public class LogGenerator {

    public void generate(int count) {
        log.info("Start generating logs");
        LongStream.range(0, count)
                .forEach(i -> log.info("Log {}", i));
    }
}


0 count



, :



@Slf4j
@RestController
@RequiredArgsConstructor
public class LogController {
    private final LogGenerator generator;

    @GetMapping("/generate")
    public ResponseEntity test(@RequestParam(name = "count", defaultValue = "0") Integer count) {
        log.info("Test request received with count: {}", count);
        generator.generate(count);
        return ResponseEntity.ok("Success!");
    }
}


GET :

http://localhost:8080/generate?count=10



. resources logback-spring.xml



<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d [%thread] %-5level  %logger{35} - [%mdc] - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="filebeatAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>./log/application.log</file>
        <append>true</append>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>./log/application.%d.%i.log.gz</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
        </rollingPolicy>
    </appender>

    <root level="INFO">
        <appender-ref ref="consoleAppender" />
        <appender-ref ref="filebeatAppender" />
    </root>
</configuration>


:



  • consoleAppender
  • filebeatAppender — , LogstashEncoder logstash-logback-encoder

    JSON , Logstash. Logstash .


, ./log/application.log log . . maxFileSize



Filebeat .



:



@Slf4j
@Component
public class LogFilter extends OncePerRequestFilter {

    private static final String REQUEST_ID = "requestId";

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String requestId = request.getHeader(REQUEST_ID);
        if (requestId == null) {
            requestId = UUID.randomUUID().toString();
        }

        MDC.put(REQUEST_ID, requestId);

        try {
            log.info("Started process request with {} : {}", REQUEST_ID, requestId);
            filterChain.doFilter(request, response);
        } finally {
            MDC.clear();
        }
    }
}


, ( requestId), MDC (Mapped Diagnostic Context)



MDC.put(REQUEST_ID, requestId);


finally MDC



MDC.clear();


, , . Kibana .



, , :



mvn spring-boot:run


, application.log



curl "localhost:8080/generate?count=10"


Success!, application.log :



{
   "@timestamp":"2020-10-17T22:39:45.595+03:00",
   "@version":"1",
   "message":"Writing [\"Success!\"]",
   "logger_name":"org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor",
   "thread_name":"http-nio-8080-exec-3",
   "level":"INFO",
   "level_value":10000,
   "requestId":"77abe5ac-4458-4dc3-9f4e-a7320979e3ae"
}


Filebeat



Filebeat

7.9.2 macOS

.

Filebeat filebeat.xml



, inputs output:



  inputs:
  - enabled: true
    encoding: utf-8
    exclude_files: ['\.gz$']
    json:
      add_error_key: true
      keys_under_root: true
      overwrite_keys: true
    paths:
    - {     }/*.log
    scan_frequency: 10s
    type: log


, Filebeat . :



  • keys_under_rootjson json, Filebeat Logstash
  • overwrite_keys
  • add_error_keyFilebeat error.message error.type: json json .


output:
  logstash:
    hosts:
    - localhost:5044
    ssl:
      certificate_authorities:
      - {    }/logstash-beats.crt


, Filebeat . Logstash ( )

ssl.certificate_authorities Logstash ( ), .



Filebeat, , .. ELK .

ELK . , docker ELK sebp/elk logstash-beats.crt. certificate_authorities filebeat.xml



docker-compose :



version: '3.7'
services:
  elk:
    image: sebp/elk
    ports:
      - "5601:5601" #kibana
      - "9200:9200" #elastic
      - "5044:5044" #logstash


ELK Filebeat , macOS :



./filebeat -e run


? , LogstashEncoder JSON application.log, Filebeat , Logstash. Kibana.



Kibana :

http://localhost:5601/



Discover:





:





Kibana index ELK . ! Filebeat , . :



curl "localhost:8080/generate?count=100"


:





:





. requestId MDC :





Agora, na guia Descobrir de nosso índice, você pode configurar a exibição de campos e ver se todos os logs em uma solicitação são combinados pelo mesmo requestId . Você pode expandir o campo JSON e ver o texto completo da mensagem recebida do Filebeat :






All Articles