Elasticsearch:Java ECS 日志记录 - log4j2

ECS 记录器是你最喜欢的日志库的格式化程序/编码器插件。它们可让你轻松将日志格式化为与 ECS 兼容的 JSON。ECS 兼容的 JSON 日志记录可以帮我们简化很多分析,可视化及解析的工作。在今天的文章里,我来详述如何在 Java 应用里生成 ECS 相兼容的日志。

如果大家对完整的项目感兴趣,你可以在地址下载示例代码。

bash 复制代码
git clone https://github.com/liu-xiao-guo/elasticsearch-java-ecs

步骤1:生成模板 Spring boot 应用

我们可以在 start.spring.io/ 生成一个模板的 Spring boot 应用:

我们下载所生成的代码,并解压缩到我们的电脑目录中。我们可以使用我们所喜欢的 IDE 来进行导入。

步骤 2:配置应用程序日志记录

如果你使用的是 Elastic APM Java 代理,将日志转换为与 ECS 兼容的 JSON 格式的最简单方法是通过 log_ecs_reformatting 配置选项。只需设置此选项,Java 代理就会自动导入正确的 ECS 日志库并配置你的日志框架以使用它来代替(覆盖/替换)或补充(遮蔽)你当前的配置。无需进行其他更改!请务必查看其他日志配置选项以充分发挥此选项的潜力。

否则,请按照以下步骤通过你的日志框架配置手动应用 ECS 格式。支持以下日志框架:

  • Logback(Spring Boot 的默认设置)
  • Log4j2
  • Log4j
  • java.util.logging (JUL)
  • JBoss 日志管理器

在今天的文章里,我们来展示如何使用 Log4j2 来进行生成 ECS 相兼容的日志。更多的资料可以在地址查看。

添加 dependency

所需的最低 log4j2 版本为 2.6。下载最新版本的 Elastic 日志记录:Maven Central v1.6.0

向你的应用程序添加依赖项:

xml 复制代码
 1.  		<dependency>
2.  			<groupId>co.elastic.logging</groupId>
3.  			<artifactId>log4j2-ecs-layout</artifactId>
4.  			<version>${ecs-logging-java.version}</version>
5.  		</dependency>

提示:如果你不使用依赖项管理工具(如 maven),则必须手动将 log4j2-ecs-layout 和 ecs-logging-core jar 添加到类路径。例如,添加到 $CATALINA_HOME/lib 目录。除此之外,没有必需的依赖项。

除此之外,我们还必须添加如下的 dependency:

xml 复制代码
 1.  		<dependency>
2.  			<groupId>org.springframework.boot</groupId>
3.  			<artifactId>spring-boot-starter-log4j2</artifactId>
4.  		</dependency>

这个是为了记录日志之用。

由于 Spring Boot 使用 logback 作为默认记录器,因此我们将其从 spring-boot-starter 依赖项中排除。我们需要做如下的修改:

xml 复制代码
 1.  		<dependency>
2.  			<groupId>org.springframework.boot</groupId>
3.  			<artifactId>spring-boot-starter-web</artifactId>
4.  			<exclusions>
5.  				<exclusion>
6.  					<groupId>org.springframework.boot</groupId>
7.  					<artifactId>spring-boot-starter-logging</artifactId>
8.  				</exclusion>
9.  			</exclusions>
10.  		</dependency>

在上面,为了能够使得它能在 Java 1.8 下进行编译,我必须把上面的 spring-boot-starter 修改为 spring-boot-starter-web,否则会有错误。

添加 log4j2.xml 文件

接下来,在 src/main/resources 中为 log4j2 记录器 log4j2.xml 添加一个 log4j2 配置。

xml 复制代码
1.  <?xml version="1.0" encoding="UTF-8"?>
2.  <Configuration status="DEBUG">
3.      <Appenders>
4.          <Console >
5.              <EcsLayout service/>
6.          </Console>
7.          <File >
8.              <EcsLayout service/>
9.          </File>
10.      </Appenders>
11.      <Loggers>
12.          <Root level="info">
13.              <AppenderRef ref="LogToFile"/>
14.              <AppenderRef ref="LogToConsole"/>
15.          </Root>
16.      </Loggers>
17.  </Configuration>

在上面,我们定义了日志的文件名 logs/app.log。里面参数的描述请参考链接

修改 application.properties 文件

我们修改 application.properties 文件为:

ini 复制代码
1.  spring.application.name=elasticsearch-java-ecs
2.  spring.main.allow-circular-references=true

在应用中使用 Log4j2 来记录日志

我们在 ElasticController class 中使用如下的方式来记录日志:

ElasticController.java

java 复制代码
1.  package com.liuxg.elasticsearch_java_ecs;

3.  import java.io.PrintWriter;
4.  import java.io.StringWriter;
5.  import java.util.Date;

7.  import org.apache.logging.log4j.LogManager;
8.  import org.apache.logging.log4j.Logger;
9.  import org.apache.logging.log4j.message.StringMapMessage;

11.  import org.springframework.beans.factory.annotation.Autowired;
12.  import org.springframework.context.annotation.Bean;
13.  import org.springframework.web.bind.annotation.RequestMapping;
14.  import org.springframework.web.bind.annotation.RestController;
15.  import org.springframework.web.client.RestTemplate;

17.  @RestController
18.  class ElasticController {
19.      private static final Logger LOG = LogManager.getLogger(ElasticController.class);

21.      @Autowired
22.      RestTemplate restTemplete;

24.      @Bean
25.      RestTemplate restTemplate() {
26.          return new RestTemplate();
27.      }

29.      @RequestMapping(value = "/")
30.      public String home() {
31.          String homeMessage = "Welcome to Elastic ECS logging demo";
32.          LOG.info(homeMessage);
33.          return homeMessage;
34.      }

36.      @RequestMapping(value = "/elk")
37.      public String helloWorld() {
38.          String response = "Welcome to JAVA " + new Date();

40.          LOG.info(new StringMapMessage()
41.                  .with("message", "API called")
42.                  .with("customer.id", "client-1")
43.                  .with("product.id", "25a76f91-41dd-49da-8020-3553c9100267")
44.                  .with("customer.action", "CREATE"));

46.          return response;
47.      }

49.      @RequestMapping(value = "/exception")
50.      public String exception() {
51.          String response = "";
52.          try {
53.              throw new Exception("Opps Exception raised....");
54.          } catch (Exception e) {
55.              e.printStackTrace();
56.              LOG.error(e);

58.              StringWriter sw = new StringWriter();
59.              PrintWriter pw = new PrintWriter(sw);
60.              e.printStackTrace(pw);
61.              String stackTrace = sw.toString();
62.              LOG.error("Exception - " + stackTrace);
63.              response = stackTrace;
64.          }

66.          return response;
67.      }
68.  }

如上所示,我们可以使用 Log.info() 来记录日志。在上面的代码中,我们使用了三种方式来记录日志:

ini 复制代码
 LOG.info(homeMessage);
csharp 复制代码
LOG.info(new StringMapMessage()
        .with("message", "API called")
        .with("customer.id", "client-1")
        .with("product.id", "25a76f91-41dd-49da-8020-3553c9100267")
        .with("customer.action", "CREATE"));
go 复制代码
 LOG.error(e);

我们为 Spring Boot 应用定义了三个接口。运行我们的 Spring Boot 应用:

它将在程序的更目录下的 logs 下生成一个叫做 app.log 的文件:

从上面的日志输出中,我们可以看出来日志是一个 ECS 相兼容的 JSON 日志文件。我们相下滚动直到文件的底部:

上面的最后一条日志就是我们刚生成的日志。

我们接着访问另外一个接口:

我们滚动到最后的一条日志:

上面显示的是我们的一条自定义的日志。

我们再接着访问一个 exception 接口:

同样的我们滚动到最后查看 app.log 日志的内容:

我们可以看到日志的内容。

把日志写入到 Elasticsearch

我们配置 filebeat.yml 文件:

Filebeat 7.16+

filebeat.yaml

yaml 复制代码
1.  filebeat.inputs:
2.  - type: filestream 
3.    paths: /path/to/app.log
4.    parsers:
5.      - ndjson:
6.        overwrite_keys: true 
7.        add_error_key: true 
8.        expand_keys: true 

10.  processors: 
11.    - add_host_metadata: ~
12.    - add_cloud_metadata: ~
13.    - add_docker_metadata: ~
14.    - add_kubernetes_metadata: ~

Filebeat < 7.16

filebeat.yaml

yaml 复制代码
1.  filebeat.inputs:
2.  - type: log
3.    paths: /path/to/logs.json
4.    json.keys_under_root: true
5.    json.overwrite_keys: true
6.    json.add_error_key: true
7.    json.expand_keys: true

9.  processors:
10.  - add_host_metadata: ~
11.  - add_cloud_metadata: ~
12.  - add_docker_metadata: ~
13.  - add_kubernetes_metadata: ~

针对 exception 这类的错误信息。我们可能需要进行特殊的处理。请参考文章 "Beats:使用 Filebeat 传送多行日志"。

更多关于如何写入 ECS 相兼容的 JSON 日志文件,请详细阅读文章:

相关推荐
Lill_bin9 小时前
深入理解ElasticSearch集群:架构、高可用性与数据一致性
大数据·分布式·elasticsearch·搜索引擎·zookeeper·架构·全文检索
RwTo11 小时前
Elasticsearch 聚合搜索
大数据·elasticsearch·搜索引擎·全文检索
求学小火龙12 小时前
ElasticSearch介绍+使用
java·大数据·elasticsearch
檀越剑指大厂12 小时前
【Elasticsearch系列六】系统命令API
大数据·elasticsearch·搜索引擎
bug菌¹18 小时前
滚雪球学SpringCloud[5.1讲]: Spring Cloud Config详解
spring·elasticsearch·spring cloud
Li小李同学Li18 小时前
git学习【持续更新中。。。】
git·学习·elasticsearch
nangonghen19 小时前
通过logstash同步elasticsearch数据
大数据·elasticsearch
檀越剑指大厂19 小时前
【Elasticsearch系列四】ELK Stack
大数据·elk·elasticsearch
2401_8401922720 小时前
ELFK日志分析平台,架构和通信
elk·elasticsearch·架构
cyt涛1 天前
搜索功能技术方案
mysql·elasticsearch·全文检索·canal·索引·数据同步·搜索