# zero-observer **Repository Path**: kuafucv/zero-observer ## Basic Information - **Project Name**: zero-observer - **Description**: 一个开箱即用的一站式 Java 应用日志观测工具,无需各种复杂繁琐的配置,使用门槛低。 - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 37 - **Forks**: 5 - **Created**: 2025-06-27 - **Last Updated**: 2025-09-19 ## Categories & Tags **Categories**: logging **Tags**: 日志监控, 日志采集, 日志可视化 ## README # zero-observer ## 一、项目初衷 Java 应用开发的同学都知道,项目上线后,日志的可视化查询与 JVM 的可视化监控是一件非常重要的事。 市面上成熟方案一般是采用 ELK/EFK 实现日志可视化,采用 Actuator + Prometheus + Grafana 实现 JVM 监控。 这两套都是非常优秀的解决方案,不过对于很多开发者来说,这中间存在大量的繁琐的配置过程。 而对于大多数中小型企业来说,很多都是一个简单的单体项目,并不想要多余的运维和部署成本! 为此我们希望通过一些低门槛的方式,实现日志的自动采集与日志可视化查询。 ## 二、软件介绍 我们的目标:`zero-observer + zero-log = actuator + prometheus + grafana + elk / efk` ### 1. 主要功能 - **应用日志查询:** 提供控制台面板与列表两种方式查询应用日志; - **慢接口监控:** 监控 Java 服务中请求超过阈值的接口,支持通用配置与自定义配置; - **JVM 监控:** 监控 JVM 进程中的各种指标,包括堆内存、非堆内存、Eden、Survivor、OldGen、Metaspace、线程、GC、物理内存、CPU 等。 ### 2. 后续规划 - **JVM 监控自动告警:** 实现 JVM 指标超过阈值时自动告警,并记录对应信息,发送消息通知; - **慢接口监控自动告警:** 实现当请求接口触发接口响应时间阈值时自动告警,并记录对应信息,发送消息通知; - **消息通知:** 实现应用系统消息通知,并对接钉钉、飞书、企微等平台; - **线程堆栈信息实时下载:** 当CPU使用超过阈值时,实现自动保存当前 JVM 线程堆栈快照信息; - **堆内存实时下载:** 当频繁GC或堆内存使用超过阈值,实现自动 dump 堆内存; - **服务器性能监控:** 实现对服务器各项指标的性能监控,通过低门槛的方式,实现一站式接入。 - ...... > 版本在积极更新中,如果你有什么建议或者BUG,可以添加作者进行反馈,或者在项目仓库下提交 ISSUE,我们会积极跟进 😁😁😁 ### 3. 系统架构 ![img.png](images/img.png) 本项目主要分为客户端和服务端两个部分。 ### 4. Java 日志采集客户端【zero-log】 > 采集客户端旨在提供低门槛、少配置、轻量级、无侵入的方式实现日志、JVM 指标的自动采集与发送。 zero-log 基于 logback 实现将代码中通过 log.error、log.warn、log.info、log.trace 等方式输出的日志与 JVM 运行时的各项指标**_自动采集并发送到远程服务器上_**。 原系统代码无需任何改动,只需要引入 zero-log 的依赖,同时在 logback-spring.xml 中添加 HttpBatchAppender,配置采集数据接收的接口即可实现自动采集与传输。 ### 5. 服务端【zero-observer】 收集客户端采集插件采集的客户端数据,包括应用日志、JVM 指标等,并提供开箱即用的可视化检索功能,极大降低了 Java 应用日志与 JVM 指标监控可视化检索的门槛。 > 请注意: > 服务端从 1.0.0 之后,服务访问路径变更为 http://ip:port/zero-observer/ ### 5. 版本升级指南 请异步至 >>> [版本升级记录](VERSIONS.md) <<< ### 6. 功能介绍 #### 仪表盘 ![img_1.png](images/img_6.png) #### 应用日志 ![img_2.png](images/img_1.png) ##### 应用控制台日志 ![img_3.png](images/img_3.png) ##### 应用慢接口日志 ![img_3.png](images/img_2.png) ##### 应用日志查询 ![img_4.png](images/img_4.png) ##### 应用日志详情 ![img_5.png](images/img_5.png) #### JVM 监控 ![img.png](images/img_jvm.png) ![img.png](images/img_jvm2.png) ![img.png](images/img_jvm3.png) ## 三、服务端安装 > zero-observer 数据存储使用的是 mysql 与 elasticsearch,mysql 存储的是系统数据,elasticsearch 存储的是日志数据。 > 所以需要自行安装 mysql 与 elasticsearch。 ### 1. Mysql 初始化脚本 创建数据库:zero_observer,执行 docs/0-all 目录下的脚本 [create_table.sql](docs/0-all/create_table.sql) > 如果是升级,请异步至 >>> [版本升级记录](VERSIONS.md) <<< ### 2. Docker 部署 ```shell # 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/kuafucv/zero-observer:1.1.0 # 启动容器 docker run -itd -p 8080:8080 --name zero-observer \ -e TZ=Asia/Shanghai -e ES_IP=127.0.0.1 \ -e ES_PORT=9200 \ -e ES_USERNAME=es \ -e ES_PASSWORD=es \ -e MYSQL_IP=127.0.0.1 \ -e MYSQL_PORT=3306 \ -e MYSQL_USERNAME=root \ -e MYSQL_PASSWORD=123456 \ registry.cn-hangzhou.aliyuncs.com/kuafucv/zero-observer:1.1.0 ``` > 参数解析: > - TZ:时区,默认 Asia/Shanghai > - ES_IP:elasticsearch 的 ip > - ES_PORT:elasticsearch restapi 的端口 > - ES_USERNAME:elasticsearch 用户名,无则不填即可 > - ES_PASSWORD:elasticsearch 密码,无则不填即可 > - MYSQL_IP:mysql 的ip > - MYSQL_PORT:mysql 端口 > - MYSQL_USERNAME 用户名 > - MYSQL_PASSWORD 密码 启动成功后,浏览器访问:http://127.0.0.1:8080/zero-observer/ 默认用户密码:admin/123456 ### 3. Jar 包部署 - 下载对应操作系统与cpu架构下的 zero-observer.jar、application.yml 与 start 启动器 - 自行修改 application.yml 中 es、mysql 的相关配置 - Linux 启动 ```shell ./start java -jar zero-observer.jar ``` - windows 启动 ``` start.exe java -jar zero-observer.jar ``` 启动成功后,浏览器访问:http://127.0.0.1:9999/zero-observer/ 默认用户密码:admin/123456 > 默认 server.port=9999,有需要请自行更改 > > 本项目采用 jdk1.8 编译开发,如果使用的时候 jdk 11 以上的 版本,需要在启动参数中额外加两个参数 > - --add-opens java.base/java.net=ALL-UNNAMED > - --add-exports java.base/jdk.internal.loader=ALL-UNNAMED > > ./start java --add-opens java.base/java.net=ALL-UNNAMED --add-exports java.base/jdk.internal.loader=ALL-UNNAMED -jar zero-observer.jar ### 4. 访问入口说明 0.0.3 版本以前,访问路径是 http://ip:port 直接访问的。 有小伙伴反馈自己公司的项目环境只能暴露一个端口出去,所以需要有 context-path 做代理配置。 故而从 0.0.4 版本及以后,访问路径统一改为 http://ip:port/zero-observer/,有需要的小伙伴通过 zero-observer 进行代理配置。 如果有同学还是想要通过 http://ip:port 或者域名直接访问,不想后面再跟上 context-path 的,也可以通过 Nginx 进行一层代理。 ## 四、Java 应用日志快速接入 ### 1. 引入 maven 依赖 #### SpringBoot 工程 ```xml io.github.kuafucv zero-log-spring-boot-starter 1.1.0 ``` #### 非 SpringBoot 工程 ```xml io.github.kuafucv zero-log-core 1.1.0 ``` ### 2. 配置 logback-spring.xml docs/logback-spring.xml 是完整 [logback-spring.xml](docs/logback-spring.xml) 配置案例。 ```xml ${FILE_LOG_PATTERN} ${FILE_LOG_CHARSET} http://ip:port/zero-observer/appLog/report http://ip:port/zero-observer/ ${app_name} ${env} ${port} true 3 1000 1000 8 1024 ``` > 注意: > - 这里仅仅展示 springboot 下的 logback-spring-xml 的配置,非 springboot 项目自行配置。 > - 主要是新增 io.github.kuafucv.zero.log.core.HttpBatchAppender 日志 Appender,该 Appender 中的 encoder 建议与原项目中输出到日志文件的 encoder 一致。 > - endpointUrl(过时) 为日志接收的远程日志中心接口,zero-log 会自动调用该接口,并发送日志数据 > - 推荐使用 serverUrl,该属性值为 http://ip:port/zero-observer/ ### 3. 全量配置列表 | 属性 | 属性解释 | 默认值 | |----------------------------------------------|-------------------|------| | zero.log.slow-request.enabled | 是否启用慢接口监控 | true | | zero.log.slow-request.default-time-threshold | 全局默认慢请求时间阈值,单位毫秒 | 1000 | | zero.log.jvm-monitor.enabled | 是否启用jvm监控 | true | | zero.log.jvm-monitor.frequency | 监控频率,单位秒 | 5 | ### 4. 日志观测 启动 Java 服务,等待日志自动上报至 zero-observer 即可。 ## 五、Java 慢接口监控 ### 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,则默认该接口不做慢接口监控,不会进行日志输出。 ## 六、 hostname 如何取值? - 同一应用可能存在多实例部署情况,仅仅是一个 env 配置是不够的。zero-log 额外采集了 hostname、ip、port,用户可以使用这三个参数来确定一个服务实例。 - IP 是获取当前服务器的ip,port 是通过配置传递的。主要是为了解决有些情况下,同一台服务器会部署两个不同的服务实例,此时需要使用端口参数才能确定是哪个实例,如果不需要,可以不填,默认值为 0。 ### hostname 取值逻辑 1. 先去系统环境变量 hostname,如果为空,则取 HOSTNAME。采用 k8s 部署的用户,为每个 pod 设置 hostname/HOSTNAME 环境变量。 2. 如果环境变量获取为空,则使用 ``` InetAddress.getLocalHost().getHostName(); ```获取 hostname。 ## 六、版本对比 | 功能 | 个人免费版 | 专业版 | |------------|-------|-----| | 应用日志采集 | ✅ | ✅ | | 应用日志检索 | ✅ | ✅ | | 慢接口监控 | ✅ | ✅ | | 登录认证 | ✅ | ✅ | | CPU 监控 | ❌ | ✅ | | 物理内存监控 | ❌ | ✅ | | 堆内存监控 | ❌ | ✅ | | 非堆内存监控 | ❌ | ✅ | | Eden区监控 | ❌ | ✅ | | Survivor区监控 | ❌ | ✅ | | OldGen区监控 | ❌ | ✅ | | Metaspace区监控 | ❌ | ✅ | | 线程监控 | ❌ | ✅ | | GC监控 |❌ | ✅ | | 未来规划 | ... | ... | ### 服务咨询 ***非专业版用户 远程协助50元每次、问题咨询15元每次。请自觉付费*** ### 专业版价格 | 授权 | 授权价 | 权益 | |------|--------|--------------------------------| | 按年授权 | 599 元 | 授权期内免费更新版本、首次远程协助免费、授权期内免问题咨询费 | | 终身授权 | 2000 元 | 永久免费更新版本、首年远程协助免费、永久免问题咨询费 | #### 授权流程: 1. 联系作者微信,支付授权费用,获取授权码; 2. 获取授权码后,请在 ***10 分钟内***,点击系统右上角「授权版本」,在弹出窗内导入授权码。 3. 如果超时未导入颁发的授权码,导致无法授权,概不负责! 4. 确需要重新获取授权码的,请联系作者微信,并支付 100 元,重新获取新授权码。仅限一次!!!如再次超时,请按现行授权价另行付费! > 随着漫长时间的推移,版本的迭代越来越多,功能越来越多,授权价会随着版本的发布酌情上升,但原先按年授权用户可以按照原先授权价续订。 ## 早期投资者 赞助超 300元的 前 100 名爱心赞助者,享有永久专业版、首次远程协助免费、永久免问题咨询费。 赞助后请联系作者微信,提供赞助记录,获取专业授权码。 ## 联系我们 #### 微信 ![img1.png](images/img00.png) #### QQ群 ![img9.png](images/img_9.png) 如有使用问题或者建议,欢迎联系我,备注[猿观测]。 ## 赞助支持 ![1191831750864963_.pic.jpg](images/1191831750864963_.pic.jpg) ![1191821750864960_.pic.jpg](images/1191821750864960_.pic.jpg) 你的赞助是我坚持的最佳动力❤️❤️❤️