
前言
Java 应用开发中,项目上线后的日志可视化查询、接口性能监控、慢请求分析、调用链监控及 JVM 可视化监控至关重要。市面上常见的方案如 ELK/EFK(日志)、Actuator + Prometheus + Grafana(JVM 与接口)、Skywalking/PingPoint/Zipkin(调用链)等,往往配置繁琐且学习门槛较高,部署与运维成本较大。
对于中小型企业或个人开发者,Zero-Observer 提供了一款免费的一站式 Java 应用全方位监控平台。它具备轻量级、低门槛、零侵入的特点,旨在以极简高效的方式,在一个平台上实现日志采集与可视化、接口性能监控、慢请求分析、调用链监控及 JVM 可视化监控。
软件介绍
zero-observer + zero-log = Java 应用一站式监控
系统架构

主要分为客户端和服务端两个部分。
采集客户端【zero-log】
旨在提供低门槛、少配置、轻量级、无侵入的方式实现应用日志、接口性能、调用链、JVM 指标的自动采集与上报。
- 基于 logback 实现自动采集代码中通过 log.error、log.warn、log.info、log.trace 方式输出的日志。
- 采集各个接口的性能数据。
- 采集方法调用链数据。
- 采集 JVM 运行时各项指标。
服务端【zero-observer】
收集客户端采集插件采集的客户端数据,并提供开箱即用的可视化与管理功能。
功能介绍
| 功能 | 实现情况 |
|---|---|
| 登录认证 | ✅ |
| 仪表盘统计 | ✅ |
| 应用日志采集 | ✅ |
| 应用控制台日志 | ✅ |
| 应用日志列表检索 | ✅ |
| 接口性能监控 | ✅ |
| 接口慢请求分析 | ✅ |
| CPU 监控 | ✅ |
| 物理内存监控 | ✅ |
| 堆内存监控 | ✅ |
| 非堆内存监控 | ✅ |
| Eden 区监控 | ✅ |
| Survivor 区监控 | ✅ |
| OldGen 区监控 | ✅ |
| Metaspace 区监控 | ✅ |
| 线程监控 | ✅ |
| GC 监控 | ✅ |
| 调用链监控 | ✅ |
仪表盘

应用日志

控制台日志

应用日志查询

应用日志详情

接口性能监控

慢请求分析

调用链监控

JVM 监控



服务端部署
zero-observer 数据存储使用 MySQL 与 Elasticsearch,MySQL 存储系统数据,Elasticsearch 存储日志数据。需自行安装 MySQL 与 Elasticsearch。
1. MySQL 初始化脚本
创建数据库:zero_observer,执行脚本。
CREATE TABLE `app_log_growth_trend` (
`id` bigint(20) NOT NULL,
`create_time` datetime NOT NULL,
`app` varchar(255) NOT NULL,
`env` varchar(50) NOT NULL,
`level` varchar(10) NOT NULL,
`statistic_time` datetime NOT NULL,
`log_count` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `app_log_total_growth_trend` (
`id` bigint(20) NOT NULL,
`create_time` datetime NOT NULL,
`statistic_time` datetime NOT NULL,
`log_count` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `app_log_level_statistic` (
`id` bigint(20) NOT NULL,
`create_time` datetime NOT NULL,
`app` varchar(255) NOT NULL,
`env` varchar(50) NOT NULL,
`level` varchar(10) NOT NULL,
`statistic_time` datetime NOT NULL,
`log_count` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`app_env_instance` (
`id` () ,
`create_time` datetime ,
`app` () ,
`env` () ,
`ip` () ,
`port` () ,
`hostname` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`app_log_statistic` (
`id` () ,
`create_time` datetime ,
`app_log_statistic_counter_id` () ,
`app` () ,
`env` () ,
`statistic_time` datetime ,
`log_count` () ,
`slow_request_count` () ,
`error_count` () ,
`warn_count` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`app_log_statistic_counter` (
`id` () ,
`create_time` datetime ,
`statistic_time` datetime ,
`statistic_status` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`system_config` (
`id` () COMMENT ,
`create_time` datetime COMMENT ,
`key_code` () COMMENT ,
`key_name` () COMMENT ,
`key_value` () COMMENT ,
`enabled` () COMMENT ,
(`id`) BTREE
) ENGINEInnoDB CHARSETutf8mb4;
`system_config` (`id`, `create_time`, `key_code`, `key_name`, `key_value`, `enabled`) (, , , , , );
`users` (
`id` () ,
`create_time` datetime ,
`account` () ,
`pwd` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`token_info` (
`id` () ,
`create_time` datetime ,
`subject` () ,
`token` () ,
`expire_time` datetime ,
`expire_timestamp` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`license` (
`id` () ,
`create_time` datetime ,
`content` text ,
`remark` text ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`request_monitor_statistic` (
`id` () ,
`create_time` datetime ,
`statistic_date` () ,
`app` () ,
`env` () ,
`uri` () ,
`executeCount` () ,
`rtAvg` ,
`rtMax` () ,
`rtMin` () ,
`slow_count` () ,
`slow_avg` ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`request_mapping` (
`id` () ,
`create_time` datetime ,
`app` () ,
`env` () ,
`ip` () ,
`port` () ,
`hostname` () ,
`uri` () ,
`` () ,
`handler_method` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
app_env_instance online ;
app_env_instance last_heartbeat DATETIME ;
request_monitor_statistic req_method () ;
`app_env` (
`id` () ,
`create_time` datetime ,
`app` () ,
`env` () ,
`gene` () ,
`signature` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
`sys_lock` (
`id` () ,
`create_time` datetime ,
`lock_name` () ,
`status` ,
`last_heartbeat` datetime ,
`holder` () ,
`holder_id` () ,
(`id`)
) ENGINEInnoDB CHARSETutf8mb4;
2. Docker 部署
拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/kuafucv/zero-observer:2.0.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:2.0.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
SpringBoot 应用接入
1. 引入 Maven 依赖
<dependency>
<groupId>io.github.kuafucv</groupId>
<artifactId>zero-log-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
2. 配置 application.yml
zero:
log:
server-url: http://127.0.0.1:8080/zero-observer
注意:serverUrl 为 zero-observer 服务访问地址,该属性值为 http://ip:port/zero-observer
3. 启动类添加注解
启动类添加 @EnableZeroLog 注解。
@SpringBootApplication
@EnableZeroLog
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4. 启动服务
启动 Java 服务,等待日志自动上报至 zero-observer,前往界面查看对应数据。



