前言

当应用被拆分为N多个微服务时,当系统遇到问题,能够准确的查看日志就成了一个非常现实的问题。 原因是以容器方式运行的服务可能分布在不同的服务器上,至少十几个的微服务,甚至更多。同时由于也不太可能给到研发人员所有的相关服务器权限, 因此,需要一个集中的日志查看分析的系统,这个系统就是EFK(ElasticSearch、FileBeat和Kibana的组合)。 因此将日志格式化为json格式,方便导入到EFK进行日志集中处理就是第一步。

对于 springboot 应用来说,绝大多数都是使用默认的 logback 日志实现。 因此本文以springboot应用maven工程,使用logback配置日志输出为例。

添加maven 依赖

在项目的 pom.xml 增加如下依赖:

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

修改logback-spring.xml 配置

修改 src/resources/logback-spring.xmlsrc/resources/logback.xml 文件,使用json格式化的appender

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

<configuration debug="false">
    <contextName>logback</contextName>
    <property name="appName" value="test-app"/>
    <!-- 控制台输出 -->  
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">  
     <filter class="ch.qos.logback.classic.filter.LevelFilter">  
            <level>DEBUG</level>  
            <onMatch>DENY</onMatch>  
            <onMismatch>ACCEPT</onMismatch>  
        </filter>  
<!--        <encoder>-->
<!--            <pattern>${CONSOLE_LOG_PATTERN}</pattern>-->
<!--        </encoder>-->
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>GMT+8</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "app": "${appName}",
                        "level": "%level",
                        "class": "%logger{40}",
                        "message": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>
    <root level="INFO">  
      <appender-ref ref="CONSOLE" />
    </root>
</configuration>    

这样控制台的日志输出就转变成为了如下的格式:

{"@timestamp":"2022-06-15T16:27:23.151+08:00","app":"test-app","level":"INFO","class":"o.s.web.servlet.DispatcherServlet","message":"Completed initialization in 24 ms"}

将控制台日志重定向成日志文件后就可以导入EFK系统了。

对于logback-spring.xml文件中的

<property name="appName" value="test-app"/>

可以替换成

<springProperty scope="context" name="appName" source="spring.application.name" />

这样会直接使用springboot配置的应用名称,避免了硬编码。