springboot使用log4j2&logback输出日志到ekl

织梦少年      2022-05-19     655

关键词:

文章目录

1、ELK 介绍

ELK 是 Elasticsearch , Logstash, Kibana 的缩写,Elasticsearch 是开源分布式搜索引擎,提供搜集、分析、存储数据等功能,Logstash 主要是用来日志的搜集、分析、过滤日志的工具,Kibana 为 Elasticsearch 提供分析和可视化的 Web 平台,可以在 Elasticsearch 的索引中查找,交互数据,并生成各种维度的表图。一句话:日志收集(Logstash),数据存储(Elasticsearch),日志可视化(Kibana),三者有机结合起来,非常方便集中式处理日志。

2、环境、软件准备

本次演示环境,我是在本机 MAC OS 上操作,以下是安装的软件及版本:

  • Java: 1.8.0_211
  • Elasticsearch: 7.1.0
  • Logstash: 7.1.0
  • Kibana: 7.1.0
  • Spring Boot: 2.1.4.RELEASE

注意:本次主要演示如何在 Spring-Boot 项目中配置 Log4j2 以及 Logback 输出日志到 ELK 中,并能够在 Kibana 中可以正确检索出来,Elasticsearch 及 Spring-Boot 项目底层需要 Java 环境,所以需要提前本地安装好 Java 环境,这里忽略 Java 安装过程。

3、ELK 环境搭建

我们可以去 官网 分别下载系统对应最新版 ElasticsearchLogstashKibana,截止目前已更新到 7.1.0 版本,可通过以下链接获取安装包并提供默认配置启动步骤。

这里我先按照默认配置启动 Elasticsearch 服务,启动完毕,本地可以通过 http://127.0.0.1:9200 地址访问服务是否启动正常。注意:先不启动 LogstashKibana,因为他们的配置需要更改,下边会讲到。

技术图片

4、Spring Boot 配置示例

使用 Idea 创建一个 Spring Boot 项目,我们先添加 Log4j2支持,演示如何使用 Log4j2 将日志直接输出到本地的 ELK 中,然后演示下通过 Logback 动态输出索引名称到日志中,方便分类检索日志。

4.1、Log4j2 方式配置

首先修改 pom.xml 增加 Log4j2 日志框架支持,注意 spring-boot-starter 默认使用 Logback 作为日志框架,所以需要先移除默认日志配置 spring-boot-starter-logging

pom.xml 增加如下配置:

	 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
	 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.4.2</version>
    </dependency>

注意:disruptor 是一个轻量的高性能并发框架,Log4j2 包含了基于 LMAX Disruptor(高性能线程间消息通信库)的下一代 Asynchronous Loggers。在多线程环境下 Asynchronous Loggers 的吞吐量是 Log4j1Logback 的 18 倍,而延迟时间也要低一个数量级。如果使用异步日志时,添加 disruptor 支持,会大大提高效率,当然不添加也是没有问题的。

增加 log4j2-spring.xml 配置输出到 ELK 中,大概配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF" monitorInterval="60">
    <Appenders>
        <!-- Console 日志,只输出 level 及以上级别的信息,并配置各级别日志输出颜色 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%highlight{%d{yyyy.MM.dd ‘at‘ HH:mm:ss z} %-5level %class{36} %M() @%L - %msg%n}{FATAL=Bright Red, ERROR=Bright Magenta, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White}"/>
        </Console>
		 <!-- socket 日志,输出日志到 Logstash 中做日志收集 -->
        <Socket name="Socket" host="127.0.0.1" port="4560" protocol="TCP">
            <JsonLayout properties="true" compact="true" eventEol="true" />
            <PatternLayout pattern="%d{yyyy.MM.dd ‘at‘ HH:mm:ss z} %-5level %class{36} %M() @%L - %msg%n"/>
        </Socket>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <appender-ref ref="Socket"/>
            <appender-ref ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

注意:这里配置 Socket 输出方式,输出日志到本地 Logstash 做日志收集,格式化处理后自动输出到本地 Elasticsearch 中存储,最后通过 Kibana 检索索引通过 Web 页面展示出来。需要指定 hostportprotocol,这里就配置成本地 Logstash 指定配置的端口和地址即可。

同时可以在 application.properties 中配置日志输出级别,注意这里可以不指定加载 log4j2-spring.xml 文件,Spring Boot 会默认加载该配置文件。

logging.level.root=info

最后,代码中在 Controller 写入一些特定日志和异常信息,方便在 Kibana 中查看验证。

@RestController
@RequestMapping("/test")
public class LogController {

    private Logger logger = LogManager.getLogger(LogController.class);
    
    @RequestMapping(value = "/log4j2", method = RequestMethod.GET)
    public String testLog(){
        try {
            logger.info("Hello 这是 info message. 信息");
            logger.error("Hello 这是 error message. 报警");
            logger.warn("Hello 这是 warn message. 警告");
            logger.debug("Hello 这是 debug message. 调试");
            logger.fatal("Hello 这是 fatal message. 严重");
            List<String> list = new ArrayList<>();
            System.out.println(list.get(2));
        } catch (Exception e) {
            logger.error("testLog", e);
        }
        return "";
    }
}

OK,Spring Boot 工程添加 Log4j2 支持配置完毕,接下来,我们需要配置 LogstashKibana,在 Logstash 安装目录下 config 目录,新建 test-log4j2.conf 配置文件,配置如下:

input {
  tcp {
    host => "127.0.0.1"
    port => "4560"
    mode => "server"
    type = json
  }
  stdin {}
}
filter {

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

注意:这里配置 tcp 的 host 和 port 要跟上边 log4j2-spring.xml 中配置一致,否则无法进行日志收集, output 下的 elasticsearch 的 host 配置要跟上边启动的本地 Elasticsearch 配置一致,index 指定为固定的 log4j2-yyyy.MM.dd 格式,方便在 Kibana 中检索索引使用。使用该配置文件启动 Logstash,命令如下:

$ cd <Logstash_path>/bin
$ ./logstash -f ../config/test-log4j2.conf

最后,启动 Kibana,可以使用默认配置,不过这里我稍微修改一些配置如下:

$ vim <Kibana_path>/config/kibana.conf

server.port: 5601
server.host: "127.0.0.1"
elasticsearch.hosts: ["http://127.0.0.1:9200"]
i18n.locale: "zh-CN"

同理,这里 elasticsearch.hosts 配置要跟上边一致,同时指定 Kibana 启动端口为 5601,并且修改显示默认英文为中文,方便查看,启动 Kibana 直到日志输出显示状态为 Green 即启动完毕。

一切都准备完毕,最后启动 Spring Boot 工程,并触发 /test/log4j2 接口,制造各类日志,在 Kibana Web 页面查看是否正确加载过来吧!

浏览器访问 http://127.0.0.1:4560 即可打开 Kibana 页面,首先我们查看下 Elasticsearch 索引管理里面,是否已存在上边配置的 log4j2-yyyy.MM.dd 格式索引。

技术图片

OK,显示已存在,那么接下来我们在 Kibana 索引模式下创建索引模式,输入 log4j2-* 即可正确匹配到 Elasticsearch 中的指定的索引,接着在时间筛选字段名称处选择 @timestamp,方便我们后边按照时间段筛选数据,创建过程如下:

技术图片
技术图片
技术图片

创建完毕,我们就可以在 Kibana 中筛选并显示日志了,比如我增加了 message 字段,过滤完后,就显示出来上边工程示例代码中的各种类型日志以及异常日志了,非常直观方便!

技术图片

4.2、Logback 方式配置

上边使用 Log4j2 日志框架可以正确输出日志到 ELK,但是有一个地方需要我们注意,就是启动 Logstash 时指定 Elasticsearch 的 index 索引为固定值(log4j2-*)了,如果有多个 project 同时往 ELK 中输出日志,那么使用同一个索引名称的话,会造成日志混乱,不方便区分排查各个项目的日志,所以,我们希望能够通过动态输出索引名称到 Elasticsearch 中,例如 Project A 输出到索引 projectA-* 下,Project B 输出到索引 projectB-* 下,这样就方便我们在 Kibana 下根据项目匹配对应的索引值了,当然使用 Spring Boot 默认日志框架 Logback 可以很轻松的办到。

那么改造项目来支持 Logback 日志框架,首先修改 pom.xml 配置文件如下:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
<!--        <exclusions>-->
<!--            <exclusion>-->
<!--                <groupId>org.springframework.boot</groupId>-->
<!--                <artifactId>spring-boot-starter-logging</artifactId>-->
<!--            </exclusion>-->
<!--        </exclusions>-->
    </dependency>


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

注意:这里将移除的 spring-boot-starter-logging 重新添加进来,同时依赖 logstash-logback-encoder 该插件,该插件起到 Socket 通过 TCP 方式向 Logstash 进行日志输送的作用。

接着增加 logback-spring.xml 配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <property name="LOG_HOME" value="logs/demo.log" />
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>127.0.0.1:4560</destination>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder" >
            <customFields>{"appname": "demo-elk"}</customFields>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="logstash" />
    </root>
</configuration>

注意:这里的 destination 依旧要配置对应上本地 Logstash 配置,着重说下 <customFields>{"appname": "demo-elk"}</customFields> 字段配置,该自定义字段配置, Logstash 收集日志时,每条日志记录均会带上该字段,而且在 Logstash 配置文件中可以通过变量的方式获取到字段,这样就能达到我们说的动态输出索引名称到 Elasticsearch 中的功能了。同样,application.properties 可以不指定加载 logback-spring.xml 文件,Spring Boot 会默认加载该配置文件。接下来,去 Logstash config 下增加 test-logback.conf 配置文件,配置如下:

input {
  tcp {
    host => "127.0.0.1"
    port => "4560"
    mode => "server"
    type => json
  }
  stdin {}
}
filter {

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

注意:这里的 %{[appname]} 就是获取上边的 <customFields> 字段中的 json 串 key 值,我们只传了一个 appname 值,当让还可以传递其他值,例如 IP、Hostname 等关键信息,方便在 Kibana 中检索索引时区分。重启一下 Logstash 指定该配置文件。

$ cd <Logstash_path>/bin
$ ./logstash -f ../config/test-logback.conf

ElasticsearchKibana 不需要重启,再次启动 Spring Boot 工程,去 Kibana 下查看 !查看下 Elasticsearch 索引管理里面,是否已存在上边配置的 demo-elk-yyyy.MM.dd 格式索引。

技术图片

What? 怎么没有获取到传递过去的 appname 值呢?原样配置到 Elasticsearch 索引中去了,但是我在后台 Logstash 控制台日志中可以明显看到,打印的每条 Json 串中是有该字段的呀!各种搜索,发现大家也是这么配置的呢!即使将 type => json 改为 codec => json 依旧不行!百思不得解的时候,查看了下 logstash-logback-encoder 文档说明 这里明确指出要使用 codec => json_lines 方式,好吧! test-logbash.conf 配置修改如下并重启 Logstash

input {
  tcp {
    host => "127.0.0.1"
    port => "4560"
    mode => "server"
    codec => json_lines
  }
  stdin {}
}
filter {

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

这下妥妥没有问题了,在去查看下 Elasticsearch 索引管理,这下就有了。

技术图片

那么接着建一个索引模式名称为 demo-elk-*,查看下日志记录,是否能够正常加载的项目日志,也是妥妥没有问题的。

技术图片
技术图片

springboot+log4j2日志框架配置(maven)

参考SpringBoot官方文档日志部分SpringBoot默认情况下,当使用"Starters"使用Logback输出日志,还包括适当的Logback路由,确保其他的日志框架(JavaUtilLogging,CommonsLogging,Log4j,SLF4J)都能正常使用SpingBoot文档的26.5CustomLogConfiguration章节,说明... 查看详情

如何在springboot中配置log4j写入文件?

这可能是一个配置?log4j只在我们运行项目时将日志写入文件:java-jarproject.jar&当我们在eclipse中运行项目时,log4j将日志写入文件并在控制台上打印答案也许你可以看看thisanswer,它似乎描述了同样的问题。通过使用不同的Spring... 查看详情

🔥springboot图文教程2—日志的使用「logback」「log4j」

...有的代码案例都敲一遍大哥大姐新年好,点赞转发不要少SpringBoot图文系列教程技术大纲简单说明,教程分为基础篇,进阶篇和高级篇基础篇,本章力求简单快速的掌握基本的SpringBoot使用,并应用到项目中进阶篇,学会 查看详情

springboot整合log4j(代码片段)

springboot整合log4j1、依赖添加 1.1、添加依赖 1.2、剔除依赖2、配置日志 2.1、日志打印记录 2.2、指定配置文件1、依赖添加 1.1、添加依赖 需要引入log4j的依赖支持,推荐自己确定使用的版本。<dependency><groupId>org.apa... 查看详情

lo4j的配置一(代码片段)

最近开始在研究log4j,可能因为是想要自己去搭建框架那。废话不多说,先上一个例子好了。第一步:当然是引入对象的jar包了地址:http://www.apache.org/dyn/closer.cgi/logging/log4j/1.2.17/log4j-1.2.17.tar.gz第二步:代码packagecom.sun.test;importorg... 查看详情

外部log4j.properties在不打印日志中-springboot2.2.1(代码片段)

[在2.2.1RELEASE中开发一个SpringBoot应用程序。除使用log4j.properties进行记录外,其他所有操作都正常。在apoplication.properies中,添加了logging.config,如下所示logging.config=$external.config/log4j.properties.Pom.xml文件,排除spring-boot-starter-l 查看详情

在 log4j2.xml 中使用 Spring Boot 应用程序属性

】在log4j2.xml中使用SpringBoot应用程序属性【英文标题】:UseSpringbootapplicationpropertiesinlog4j2.xml【发布时间】:2018-08-0302:40:38【问题描述】:我正在开发一个基于SpringBoot的Web应用程序,并希望使用log4j2作为记录器实现。log4j2-spring.xml... 查看详情

在 Spring Boot 中配置 log4j2.properties

】在SpringBoot中配置log4j2.properties【英文标题】:Configuringlog4j2.propertiesinSpringBoot【发布时间】:2018-06-1207:08:39【问题描述】:我是SpringBoot的新手。我有一个正在运行的SpringBoot项目。我想使用log4j2(由于项目限制,我必然会使用log... 查看详情

springboot日志1

SpringBoot在所有内部日志中使用CommonsLogging,但是默认配置也提供了对常用日志的支持,如:JavaUtilLogging,Log4J, Log4J2和Logback。每种Logger都可以通过配置使用控制台或者文件输出日志内容。 Logback是log4j框架的作者开发的新... 查看详情

springboot使用log4j

log4j、logback、Log4j2简介log4j是apache实现的一个开源日志组件logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现Log4j2是log4j1.x和logback的改进版,采用了一些新技术(无锁异步、... 查看详情

springboot配置log4j2.xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><version>RELEASE</version></dependency><!-- 查看详情

springboot2.x实践记:log4j2.xml(代码片段)

目录Maven添加log4j2.xml实战小结TL;DR我们都知道,SpringBoot的默认日志采用的是Logback。今天,我们通过配置log4j2.xm来使用Log4j2日志记录。Maven首先,排除SpringBoot默认的日志记录依赖logback,然后添加log4j2依赖。<depende... 查看详情

springboot2.x实践记:log4j2.xml(代码片段)

目录Maven添加log4j2.xml实战小结TL;DR我们都知道,SpringBoot的默认日志采用的是Logback。今天,我们通过配置log4j2.xm来使用Log4j2日志记录。Maven首先,排除SpringBoot默认的日志记录依赖logback,然后添加log4j2依赖。<depende... 查看详情

idea创建lo4j模板

  复制文字到文本框中: log4j.rootLogger=DEBUG,stdout log4j.logger.org.mybatis=DEBUG log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout l 查看详情

外置tomcat启动springboot应用,日志profile功能失效

参考技术A日志profile相关配置如下在主配置文件application.properties中声明profile为dev环境spring.profiles.active=dev在application-dev.properties文件中指定了日志配置文件为类路径下的log4j2-dev.xmllogging.config=classpath:log4j2-dev.xml但是项目启动的时... 查看详情

springboot项目集成logf4j详细流程记录

...实际使用样例三个方面来记录。第一步:我这里使用的是springboot,因为springboot自带log,咱们要使用log4j,先屏蔽了原来的log第二步:加入log4j的依赖,一个接口,一个实现两个包配置文件放置位置,项目Application所在module中的reso... 查看详情

将 log4j2.properties 配置到 Spring Boot 中的问题(使用 gradle)

】将log4j2.properties配置到SpringBoot中的问题(使用gradle)【英文标题】:Problemwithconfiguringlog4j2.propertiesintospringboot(usinggradle)【发布时间】:2019-10-2615:14:29【问题描述】:我在scr/main/resources中添加了一个log4j2.properties文件,但它没有... 查看详情

springboot之日志记录

SpringBoot之日志记录SpringBoot支持集成Java世界主流的日志库。如果对于Java日志库不熟悉,可以参考:细说Java主流日志工具库关键词:log4j,log4j2,logback,slf4j日志格式控制台输出彩色打印文件输出日志级别日志组日志配置文件SpringBoot... 查看详情