# zero-log
**Repository Path**: jonerxq_admin/zero-log
## Basic Information
- **Project Name**: zero-log
- **Description**: zero-log 旨在提供低门槛、轻量级、无侵入式的方式实现日志的采集与发送。
- **Primary Language**: Java
- **License**: GPL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 9
- **Created**: 2025-07-30
- **Last Updated**: 2025-07-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# zero-log
## 一、背景
Java 应用开发时,服务器上的日志往往是以日志文件的形式存在。在日常维护时,通常需要将日志信息实现可视化查询。
ELK、EFK 等是优秀的日志可视化查询解决方案。不过对于部分开发者来说,日志的采集配置与日志可视化配置是一个比较繁琐的过程。
为此我们希望通过一些低门槛的方式,实现日志的自动采集与日志可视化查询。
zero-log 旨在提供低门槛、轻量级、无侵入式的方式实现日志的采集与发送。springboot 内置使用的是 logback,所以,zero-log 基于 logback 实现将代码中通过 log.error、log.warn、log.info、log.trace 等方式输出的日志**_自动采集并发送到远程服务器上_**。
原系统代码的日志输出方式无需任何改动,只需要引入 zero-log 的依赖,同时在 logback-spring.xml 中添加 HttpBatchAppender,配置日志数据接收的接口即可实现日志的自动采集与传输。
> 请注意:
>
> 本项目从 1.0.0 之后,工程目录进行结构调整,pom 的引入方式发生变化,同时新增慢接口日志!!!
## 二、软件介绍
### 1. 软件结构图

### 2. 版本升级指南
请异步至 >>> [版本升级记录](VERSIONS.md) <<<
## 三、功能介绍
1. 日志数据自动化采集,并通过 http 接口的方式方式定时发送到远程服务器;
2. 监控系统接口响应性能,输出慢接口日志;
## 四、快速接入
### 1. 引入 maven 依赖
#### SpringBoot 工程
```xml
io.github.kuafucv
zero-log-spring-boot-starter
1.0.0
```
#### 非 SpringBoot 工程
```xml
io.github.kuafucv
zero-log-core
1.0.0
```
### 2. 配置 logback-spring.xml
```xml
${FILE_LOG_PATTERN}
${FILE_LOG_CHARSET}
${endpointUrl}
true
${app_name}
${env}
${port}
3
1000
1000
8
1024
```
> 注意:
> 1. 这里仅仅展示 springboot 下的 logback-spring-xml 的配置,非 springboot 项目自行配置。主要是新增 io.github.kuafucv.zero.log.core.HttpBatchAppender 日志 Appender,该 Appender 中的 encoder 建议与原项目中输出到日志文件的 encoder 一致。
> 2. endpointUrl 为日志接收的远程日志中心接口,zero-log 会自动调用该接口,并发送日志数据,**_详情见下文_**。
## 五、慢接口监控
### 1 快速接入
#### SpringBoot 工程
springboot 工程引入`zero-log-spring-boot-starter`包,则自动开启慢接口监控。可以通过配置`zero.log.slow-request.enabled=false`进行关闭。
```yaml
zero:
log:
slow-request:
# 是否开启慢接口健康
enabled: true
# 默认时间阈值(毫秒)
default-time-threshold: 1000
```
#### 非 SpringBoot 工程
非 springboot 工程引入的是`zero-log-core`包,无法使用 starter 的自动装配,所以需要手动配置 `SlowRequestFilter`。
```java
@Bean
public FilterRegistrationBean slowRequestFilterFilterRegistrationBean() {
FilterRegistrationBean bean = new FilterRegistrationBean<>();
bean.setFilter(new SlowRequestFilter());
bean.setOrder(Integer.MIN_VALUE);
bean.setUrlPatterns(Collections.singletonList("/*"));
return bean;
}
```
> 其他更古老的项目,如使用 servlet 的 web.xml 配置的方式,请自行配置。
### 2 高阶配置
同一系统不同的接口,慢的时间阈值可能存在一定差别,zero-log 支持高阶的自定义配置,实现不同接口的不同阈值配置能力。
#### SpringBoot 工程
```java
@Component
public class SlowRequestThresholdFactoryImpl implements SlowRequestThresholdFactory {
@Override
public List build() {
List list = new ArrayList<>();
SlowRequestThreshold s0 = new SlowRequestThreshold();
s0.setUrlPattern("/**/user/**");
s0.setTimeThreshold(500);
list.add(s1);
SlowRequestThreshold s1 = new SlowRequestThreshold();
s1.setUrlPattern("/**");
s1.setTimeThreshold(2000);
list.add(s1);
return list;
}
}
```
#### 非 SpringBoot 工程
```java
public class SlowRequestThresholdFactoryImpl implements SlowRequestThresholdFactory {
@Override
public List build() {
List list = new ArrayList<>();
SlowRequestThreshold s0 = new SlowRequestThreshold();
s0.setUrlPattern("/**/user/**");
s0.setTimeThreshold(500);
list.add(s1);
SlowRequestThreshold s1 = new SlowRequestThreshold();
s1.setUrlPattern("/**");
s1.setTimeThreshold(2000);
list.add(s1);
return list;
}
}
@Bean
public SlowRequestThresholdFactory slowRequestThresholdFactory() {
return new SlowRequestThresholdFactoryImpl();
}
@Bean
public FilterRegistrationBean slowRequestFilterFilterRegistrationBean(SlowRequestThresholdFactory slowRequestThresholdFactory) {
FilterRegistrationBean bean = new FilterRegistrationBean<>();
bean.setFilter(new SlowRequestFilter(1000, slowRequestThresholdFactory));
bean.setOrder(Integer.MIN_VALUE);
bean.setUrlPatterns(Collections.singletonList("/*"));
return bean;
}
```
不论是否是 springboot 工程,本质都是通过实现 SlowRequestThresholdFactory 接口的 build 方法,返回 List 集合,实现自定义不同接口的不同阈值能力。
>注意事项:
>1. 接口匹配是通过 spring 的 AntPathMatcher 实现的,所以 SlowRequestThreshold.urlPattern 的值配置规则参考 spring AntPathMatcher 匹配规则。
>2. 接口匹配根据放回的 List 从上到下逐个匹配,匹配到了则不再继续匹配,所以 urlPattern 范围更大的配置需要发放在 List 集合的的后面。
>3. 如果匹配不到,则使用默认阈值。
>4. 默认阈值与 SlowRequestThreshold 里设置的阈值,如果 小于等于 0,则默认改接口不做慢接口监控,不会进行日志输出。
## 六、日志数据格式
### 1 日志格式
```json
{
"hostname":"hostname",
"ip":"ip",
"port": 0,
"patternLog": "通过 encode 转换后的日志格式,通常 encode 的 pattern 配置与 日志文件的 patter 一致",
"timestamp": "日志输出的时间戳,毫秒",
"level": "level",
"pid": "线程id",
"thread": "线程名称",
"logger": "logger",
"message": "message",
"mdc": {},
"exception": {
"className":"",
"message": "",
"stackTrace": []
}
}
```
### 2 慢接口日志
```json
{
"hostname":"hostname",
"ip":"ip",
"port": 0,
"patternLog": "通过 encode 转换后的日志格式,通常 encode 的 pattern 配置与 日志文件的 patter 一致",
"timestamp": "日志输出的时间戳,毫秒",
"level": "level",
"pid": "线程id",
"thread": "线程名称",
"logger": "logger",
"message": {
"uri":"/aaa/bbb/ccc",
"method":"GET",
"ip":"ip",
"status":"200(接口的HttpResponseStatus)",
"duration":"1319(耗时,单位毫秒)",
"userAgent":"UA值"
},
"mdc": {
"SLOW_REQUEST_WARN": "耗时(毫秒)"
},
"exception": {
"className":"",
"message": "",
"stackTrace": []
}
}
```
> 如果不是采用 [zero-observer](https://gitee.com/kuafucv/zero-observer) 做日志中心,而是自建日志中心的同学,可以根据 mdc 中是否包含 SLOW_REQUEST_WARN 属性进行分辨是否属于慢接口日志。
### 3. hostname 如何取值?
同一应用可能存在多实例部署情况,仅仅是一个 env 配置是不够的。zero-log 额外采集了 hostname、ip、port,用户可以使用这三个参数来确定一个服务实例。
IP 是获取当前服务器的ip,port 是通过配置传递的。主要是为了解决有些情况下,同一台服务器会部署两个不同的服务实例,此时需要使用端口参数才能确定是哪个实例,如果不需要,可以不填,默认值为 0。
hostname 取值逻辑:
1. 先去系统环境变量 hostname,如果为空,则取 HOSTNAME。采用 k8s 部署的用户,为每个 pod 设置 hostname/HOSTNAME 环境变量。
2. 如果环境变量获取为空,则使用 ``` InetAddress.getLocalHost().getHostName(); ```获取 hostname。
## 七、endpointUrl
endpointUrl 是远端接口日志信息的接口地址,http 协议,post 方法。
可以对接自研日志中心,也可以使用 [zero-observer](https://gitee.com/kuafucv/zero-observer) 进行对接,zero-observer 的日志接收地址为 ```http://ip:port/log/report```。
## 联系我

如有使用问题或者建议,欢迎联系我,备注[zero-log]。
## 赞助支持


你的赞助是我坚持的最佳动力❤️❤️❤️