Spring Boot و Filebeat محليًا بدون تسجيل و SMS

في هذا البرنامج التعليمي ، سننظر في توصيل وتكوين نظام تسجيل في مشروع Spring Boot وإرسال السجلات إلى ELK باستخدام Filebeat . هذا الدليل مخصص للمطورين المبتدئين.



التسجيل ولماذا هو مطلوب



عندما بدأت العمل كمبرمج لأول مرة ، أحب أحد زملائي الكبار أن يكرر: "إذا لم يكن لديك سجلات ، فلن يكون لديك أي شيء" . في الواقع ، عند مواجهة الخطأ الأول على مقاعد الاختبار أو ما هو أسوأ في بيئة صناعية ، فإن أول شيء نحتاجه هو سجلات التطبيقات وسهولة الوصول إليها. مطورو التطبيق مسؤولون عن السجلات بأنفسهم ، والذين يجب عليهم التأكد من أن سلوك النظام قد تم تسجيله بطريقة تجعل من الممكن في أي وقت فهم ما يحدث مع النظام ، والأهم من ذلك ، ما هو الخطأ فيه.



السؤال التالي هو سهولة الوصول إلى السجلات. عادة ، أثناء الاختبار المحلي ، نرى السجل في وحدة تحكم التطبيق ، وعلى منصة الاختبار - في ملفات السجل الخاصة على الخادم. هل من الملائم والآمن الاتصال بالحامل في كل مرة والبحث عن الدليل المطلوب وقراءة ملفات السجل من هناك؟ تبين الممارسة أن لا ، وهذه هي المشكلة الثانية التي تم تصميم عدد من المنتجات لحلها والتي توفر وصولاً سهلاً إلى السجلات والبحث عن المعلومات المهمة فيها. سنتحدث اليوم بإيجاز شديد عن إحدى مجموعات هذه المنتجات ، ما يسمى ELK stack (Elasticsearch - Logstash - Kibana ) وبمزيد من التفاصيل حول Filebeat - منتج مفتوح المصدر يوفر آلية ملائمة لتسليم السجلات إلى ELK .



ثلاثة أسطر عن ELK



  • Logstash - تلقي وتعديل السجلات
  • Elasticsearch - التخزين والبحث
  • كيبانا - عرض


ما علاقة Filebeat به؟



سيوفر Filebeat تسليم البيانات إلى ELK وسيتم نشره بجوار تطبيقنا ، وغالبًا ما يكون أكثر ملاءمة من تكوين Logstash لقراءة البيانات من ملفات السجل أو القنوات الأخرى.



قد يكون الأسلوب الجيد هو نشر ELK مشترك لمجموعة من الخدمات المصغرة ، ولكل خدمة مصغرة ، نشر Filebeat الخاص بها (خاصة أنه ليس أسهل في أي مكان) ، والذي سيقرأ سجلات الخدمات المصغرة وإرسالها إلى ELK المشترك .



سنحاول تنفيذ هذا الحل لاحقًا في البيئة المحلية.





ممارسة



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 :





الآن ، في علامة التبويب Discover لفهرسنا ، يمكنك تكوين عرض الحقول ومعرفة أن جميع السجلات الموجودة في طلب واحد يتم دمجها بواسطة نفس معرف الطلب . يمكنك توسيع حقل JSON ومشاهدة النص الكامل للرسالة المستلمة من Filebeat :






All Articles