应用 ELK 收集各模块日志处理流程

日志处理流程

1589975604187

Java 项目改造

一、log4j2.xml 项目改造

<appenders>
    <!-- kafka的appender配置 -->
    <Kafka name="KafkaAppender" topic="logger-channel">
        <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
        <PatternLayout charset="UTF-8" pattern="webphishing|%d|%level|%logger{15} - %m" />
        <Property name="bootstrap.servers">localhost:9092</Property>
    </Kafka>
</appenders>

<loggers>
    <logger name="org.apache.kafka" level="INFO"></logger>

    <appender-ref ref="KafkaAppender" />
</loggers>
  • localhost:9092 需要替换为 kafka 地址即可。
  • logger-channel 为 kafka 中的 topic 名称。

二、Springboot 项目改造

引入 maven 包:

<dependency>
	<groupId>com.github.danielwegener</groupId>
	<artifactId>logback-kafka-appender</artifactId>
	<version>0.2.0-RC2</version>
</dependency>

配置 logback-spring.xml

<!-- 模块名称配置,对应 application.properties 中的 spring.application.name -->
<springProperty scope="context" name="module" source="spring.application.name"  defaultValue="undefinded"/>
<!-- Kafka 配置,对应 application.properties 中的 spring.kafka.bootstrap-servers -->
<springProperty scope="context" name="bootstrapServers" source="spring.kafka.bootstrap-servers" defaultValue="localhost:9092"/>


   <!-- kafka的appender配置 -->
   <appender name="KafkaAppender" class="com.github.danielwegener.logback.kafka.KafkaAppender">
       <encoder>
           <pattern>${module}|%d|%level|%logger{15} - %msg</pattern>
           <charset>UTF-8</charset>
       </encoder>
       <topic>logger-channel</topic>
       <keyingStrategy class="com.github.danielwegener.logback.kafka.keying.NoKeyKeyingStrategy"/>
       <deliveryStrategy class="com.github.danielwegener.logback.kafka.delivery.AsynchronousDeliveryStrategy"/>

       <producerConfig>bootstrap.servers=${bootstrapServers}</producerConfig>

   </appender>
   
   <appender-ref ref="KafkaAppender" />

对应 application.properties 配置参考

spring.application.name=uploades
spring.kafka.bootstrap-servers=127.0.0.1:9092

开源 Git:

https://github.com/danielwegener/logback-kafka-appender

问题处理

出现异常:

09:39:22,934 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@11:100 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
09:39:22,940 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@18:143 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
09:39:22,941 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@27:114 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
09:39:22,941 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@28:113 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
09:39:22,941 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@29:124 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]

原因:如果项目中配置的日志文件的名称是 logback.xml 的话,logback 会先与 Spring 之前加载日志配置,这时日志文件中的 springProfile 的配置是无效的。按照官方文档的说法将 logback.xml 改为 logback-spring.xml 就可以了。

为什么 Spring Boot 推荐使用 logback-spring.xml 来替代 logback.xml 来配置 logback 日志的问题分析

最根本的原因:

image-20210924151936675

即,logback.xml 加载早于 application.properties,所以如果你在 logback.xml 使用了变量时,而恰好这个变量是写在 application.properties 时,那么就会获取不到,只要改成 logback-spring.xml 就可以解决。

LogStash 配置

配置 config/core.conf

input {
  kafka {
    id => "my_plugin_id"
    bootstrap_servers => "127.0.0.1:9092"
    topics => ["logger-channel"]
    auto_offset_reset => "latest"
    codec => plain {
        charset => "UTF-8"
    }
  }
}
filter {

   grok {
      patterns_dir => ["./patterns"]
            match => { "message" => "%{USERNAME:module}\|%{LOGBACKTIME:timestamp}\|%{LOGLEVEL:level}\|%{JAVACLASS:class} - %{JAVALOGMESSAGE:logmessage}" }
    }

}
output {
  stdout { codec => rubydebug }
  elasticsearch {
    hosts => ["127.0.0.1:9200"]
    index => "logstash-%{+YYYY.MM}"
  }
}

其中:

  • index => "logstash-%{+YYYY.MM}" 为 elasticsearch 的索引名称,在此表示按月建立索引。

配置 patterns/file

LOGBACKTIME 20%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{HOUR}:?%{MINUTE}(?::?%{SECOND})

时区配置

LogStash 的 docker 容器时间不正确可以通过以下方式进行配置:

docker run -it -d -p 5044:5044 -p 5045:5045 
        -v /usr/local/docker/logstash/config/:/usr/share/logstash/config/  
        -v /usr/local/docker/logstash/pipeline/:/usr/share/logstash/pipeline/  
        -v /usr/local/docker/logstash/jars/:/usr/share/logstash/logstash-core/lib/jars/  
        -e TZ="Asia/Shanghai"   # 重点:设置时区
        -v /etc/localtime:/etc/localtime:ro  # 重点:宿主机的时钟要正确
        --name=logstash   logstash:7.16.1

解析效果

1589975976799

方式优劣

优势

  • 模块改动最小,只需要改动日志配置。
  • 不需要其他应用程序进行 Kafka 解析。

缺点

  • 需要引入 Logstash 组件。
  • 日志格式需要统一固定。