当前位置: 首页 > news >正文

Elasticsearch:Java ECS 日志记录 - log4j2

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

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

git clone https://github.com/liu-xiao-guo/elasticsearch-java-ecs

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

我们可以在 https://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

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

		<dependency><groupId>co.elastic.logging</groupId><artifactId>log4j2-ecs-layout</artifactId><version>${ecs-logging-java.version}</version></dependency>

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

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

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency>

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

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

		<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>

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

添加 log4j2.xml 文件

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

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG"><Appenders><Console name="LogToConsole" target="SYSTEM_OUT"><EcsLayout serviceName="my-app" serviceVersion="my-app-version" serviceEnvironment="my-app-environment" serviceNodeName="my-app-cluster-node"/></Console><File name="LogToFile" fileName="logs/app.log"><EcsLayout serviceName="my-app" serviceVersion="my-app-version" serviceEnvironment="my-app-environment" serviceNodeName="my-app-cluster-node"/></File></Appenders><Loggers><Root level="info"><AppenderRef ref="LogToFile"/><AppenderRef ref="LogToConsole"/></Root></Loggers>
</Configuration>

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

修改 application.properties 文件

我们修改 application.properties 文件为:

spring.application.name=elasticsearch-java-ecs
spring.main.allow-circular-references=true

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

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

ElasticController.java

package com.liuxg.elasticsearch_java_ecs;import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.StringMapMessage;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;@RestController
class ElasticController {private static final Logger LOG = LogManager.getLogger(ElasticController.class);@AutowiredRestTemplate restTemplete;@BeanRestTemplate restTemplate() {return new RestTemplate();}@RequestMapping(value = "/")public String home() {String homeMessage = "Welcome to Elastic ECS logging demo";LOG.info(homeMessage);return homeMessage;}@RequestMapping(value = "/elk")public String helloWorld() {String response = "Welcome to JAVA " + new Date();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"));return response;}@RequestMapping(value = "/exception")public String exception() {String response = "";try {throw new Exception("Opps Exception raised....");} catch (Exception e) {e.printStackTrace();LOG.error(e);StringWriter sw = new StringWriter();PrintWriter pw = new PrintWriter(sw);e.printStackTrace(pw);String stackTrace = sw.toString();LOG.error("Exception - " + stackTrace);response = stackTrace;}return response;}
}

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

  1. LOG.info(homeMessage);
  2. 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"));
    
  3. LOG.error(e);

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

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

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

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

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

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

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

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

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

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

把日志写入到 Elasticsearch

我们配置 filebeat.yml 文件:

Filebeat 7.16+

filebeat.yaml

filebeat.inputs:
- type: filestream paths: /path/to/app.logparsers:- ndjson:overwrite_keys: true add_error_key: true expand_keys: true processors: - add_host_metadata: ~- add_cloud_metadata: ~- add_docker_metadata: ~- add_kubernetes_metadata: ~

Filebeat < 7.16

filebeat.yaml

filebeat.inputs:
- type: logpaths: /path/to/logs.jsonjson.keys_under_root: truejson.overwrite_keys: truejson.add_error_key: truejson.expand_keys: trueprocessors:
- add_host_metadata: ~
- add_cloud_metadata: ~
- add_docker_metadata: ~
- add_kubernetes_metadata: ~

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

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

  • Elastic:运用 Elastic Stack 分析 Spring Boot 微服务日志 (一)(二)

  • Elasticsearch:使用 Filebeat 从 Node.js Web 应用程序提取日志

  • Beats:使用 Filebeat 从 Python 应用程序中提取日志

http://www.lryc.cn/news/407189.html

相关文章:

  • MongoDB自学笔记(四)
  • 时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法(CPO)优化VMD二次分解
  • 新版海螺影视主题模板M3.1全解密版本多功能苹果CMSv10后台自适应主题
  • 汽车免拆诊断案例 | 2014 款上汽名爵 GT 车发动机无法起动
  • vue3前端开发-小兔鲜项目-登录功能的业务接口调用
  • 【Linux】vim编辑器使用详解
  • 手机怎么设置不同的ip地址
  • SpringBoot读取配置的6种方式
  • 1.1 openCv -- 介绍
  • 探索PostgreSQL的GUI工具:提升数据库管理效率
  • 【从零开始实现stm32无刷电机FOC】【实践】【5/7 stm32 adc外设的高级用法】
  • springcloud接入seata管理分布式事务
  • Android APP 音视频(02)MediaProjection录屏与MediaCodec编码
  • java中log4j.properties配置文件浅析
  • RV1126 Linux 系统,接外设,时好时坏(二)排查问题的常用命令
  • 鸿蒙北向开发 DevEco Studio 4.1 下载安装傻瓜式教程
  • pglogical扩展的基本用法介绍
  • 2024年虚拟主机转移教程
  • Python 函数对象和函数调用
  • sql注入的专项练习 sqlilabs(含代码审计)
  • 淄博网站建设贵不贵
  • 【学习笔记】无人机系统(UAS)的连接、识别和跟踪(十)-无人机A2X服务
  • 基于迁移学习的手势分类模型训练
  • 个性化音频生成GPT-SoVits部署使用和API调用
  • MFC列表框示例
  • Android TabLayout的简单用法
  • 基于vite + pnpm monorepo 实现一个UI组件库
  • FDM3D打印系列——Luck13关节可动模型打印和各种材料的尝试
  • windows10 获取磁盘类型
  • 数据库之运算符