本文目录导读:

我将为你展示一个完整的Java实现Prometheus指标的案例,包括基础指标、自定义指标以及HTTP暴露端点。
项目依赖配置
Maven配置
<dependencies>
<!-- Prometheus Java Client -->
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.16.0</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_hotspot</artifactId>
<version>0.16.0</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_servlet</artifactId>
<version>0.16.0</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_common</artifactId>
<version>0.16.0</version>
</dependency>
<!-- Web服务器依赖 (可选,用于暴露端点) -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.48.v20220622</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.48.v20220622</version>
</dependency>
</dependencies>
核心指标实现
自定义指标类
package com.example.prometheus;
import io.prometheus.client.Counter;
import io.prometheus.client.Gauge;
import io.prometheus.client.Histogram;
import io.prometheus.client.Summary;
public class CustomMetrics {
// 计数器(Counter)- 只增不减
private static final Counter requestCount = Counter.build()
.name("http_requests_total")
.help("Total HTTP requests")
.labelNames("method", "endpoint")
.register();
// 仪表盘(Gauge)- 可增可减
private static final Gauge activeConnections = Gauge.build()
.name("active_connections")
.help("Active server connections")
.register();
// 直方图(Histogram)- 观察值分布
private static final Histogram requestDuration = Histogram.build()
.name("http_request_duration_seconds")
.help("HTTP request duration")
.labelNames("method")
.buckets(0.1, 0.5, 1.0, 2.5, 5.0, 10.0)
.register();
// Summary)- 分位数统计
private static final Summary responseSize = Summary.build()
.name("http_response_size_bytes")
.help("HTTP response size")
.labelNames("endpoint")
.quantile(0.5, 0.05) // 中位数
.quantile(0.9, 0.01) // 90分位
.quantile(0.99, 0.001) // 99分位
.register();
private CustomMetrics() {}
// 记录请求
public static void recordRequest(String method, String endpoint) {
requestCount.labels(method, endpoint).inc();
}
// 记录请求耗时(支持方法链)
public static io.prometheus.client.Histogram.Timer startRequestTimer(String method) {
return requestDuration.labels(method).startTimer();
}
// 增加活跃连接
public static void incrementActiveConnections() {
activeConnections.inc();
}
// 减少活跃连接
public static void decrementActiveConnections() {
activeConnections.dec();
}
// 记录响应大小
public static void recordResponseSize(String endpoint, double size) {
responseSize.labels(endpoint).observe(size);
}
}
HTTP端点暴露
Jetty服务器实现
package com.example.prometheus;
import io.prometheus.client.exporter.MetricsServlet;
import io.prometheus.client.hotspot.DefaultExports;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class MetricsServer {
private final int port;
private Server server;
public MetricsServer(int port) {
this.port = port;
}
public void start() throws Exception {
// 注册JVM指标(内存、GC等)
DefaultExports.initialize();
server = new Server(port);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
// 添加MetricsServlet用于暴露指标
ServletHolder metricsServlet = new ServletHolder(new MetricsServlet());
context.addServlet(metricsServlet, "/metrics");
server.setHandler(context);
server.start();
System.out.println("Metrics server started on port " + port);
}
public void stop() throws Exception {
if (server != null) {
server.stop();
}
}
}
业务代码集成示例
测试服务类
package com.example.prometheus;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
public class TestService {
private static final Random random = new Random();
private static final AtomicLong activeRequests = new AtomicLong(0);
public static void processRequest(String endpoint) {
String method = "GET"; // 简化示例
try {
// 增加活跃连接
CustomMetrics.incrementActiveConnections();
activeRequests.incrementAndGet();
// 开始计时
io.prometheus.client.Histogram.Timer timer =
CustomMetrics.startRequestTimer(method);
try {
// 模拟业务处理
Thread.sleep(random.nextInt(1000));
// 模拟业务结果
double responseSize = random.nextDouble() * 1024;
// 记录指标
CustomMetrics.recordRequest(method, endpoint);
CustomMetrics.recordResponseSize(endpoint, responseSize);
} finally {
// 停止计时
timer.observeDuration();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 减少活跃连接
CustomMetrics.decrementActiveConnections();
activeRequests.decrementAndGet();
}
}
public static double getActiveRequests() {
return activeRequests.get();
}
}
主程序入口
package com.example.prometheus;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainApplication {
public static void main(String[] args) {
try {
// 启动Metrics服务器
MetricsServer metricsServer = new MetricsServer(8080);
metricsServer.start();
// 模拟业务请求
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
String[] endpoints = {"/api/users", "/api/products", "/health"};
String endpoint = endpoints[random.nextInt(endpoints.length)];
TestService.processRequest(endpoint);
});
}
// 添加运行时指标
registerRuntimeMetrics();
// 保持程序运行
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
metricsServer.stop();
} catch (Exception e) {
e.printStackTrace();
}
}));
// 阻塞主线程
Thread.currentThread().join();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void registerRuntimeMetrics() {
// 自定义运行时指标
Gauge buildInfo = Gauge.build()
.name("application_build_info")
.help("Application build information")
.labelNames("version", "environment")
.register();
buildInfo.labels("1.0.0", "production").set(1);
// 自定义业务指标
Counter businessEvents = Counter.build()
.name("business_events_total")
.help("Business events counter")
.labelNames("event_type", "status")
.register();
// 模拟业务事件
for (int i = 0; i < 50; i++) {
businessEvents.labels("order_created", "success").inc();
if (i % 5 == 0) {
businessEvents.labels("order_created", "failed").inc();
}
}
}
}
Prometheus配置
prometheus.yml自定义配置
scrape_configs:
- job_name: 'java-app'
scrape_interval: 15s
static_configs:
- targets: ['localhost:8080']
metrics_path: /metrics
Grafana仪表盘配置
简单仪表盘JSON配置示例
{
"panels": [
{
"title": "HTTP请求量",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{method}} - {{endpoint}}"
}
]
},
{
"title": "请求耗时分布",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))",
"legendFormat": "p99"
}
]
},
{
"title": "活跃连接数",
"type": "graph",
"targets": [
{
"expr": "active_connections",
"legendFormat": "connections"
}
]
}
]
}
测试与验证
查询指标文件
# 查看所有指标 curl http://localhost:8080/metrics # 查看特定指标 curl http://localhost:8080/metrics | grep http_request # 使用PromQL查询 curl 'http://localhost:9090/api/v1/query?query=rate(http_requests_total[5m])'
预期输出示例
# TYPE http_requests_total counter
http_requests_total{endpoint="/api/products",method="GET"} 32.0
http_requests_total{endpoint="/api/users",method="GET"} 35.0
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{method="GET",le="0.1"} 10.0
http_request_duration_seconds_bucket{method="GET",le="0.5"} 45.0
http_request_duration_seconds_sum{method="GET"} 123.456
http_request_duration_seconds_count{method="GET"} 100.0
# TYPE active_connections gauge
active_connections 5.0
这个案例展示了完整Prometheus指标监控方案,包含了所有主要指标类型、自定义指标、运行时指标注册以及HTTP暴露端点,你可以根据实际需求进行调整和扩展。