Boot 自带哪些指标?uri 标签会不会因为路径变量爆炸?自己注册的 Gauge 为什么会变成 NaN?标签基数大了会怎样?Prometheus 里的名字为什么和代码里不一样?这篇在 Spring Boot 4.0.8 上逐个实测。
刚启动、还没有任何请求:/actuator/metrics 共 53 个指标名;按第一段分组:application×2, disk×2, executor×7, http×1, jvm×23, logback×1, process×6, queue×1, system×3, tomcat×6, weak×1 发过 2 个请求之后:54 个;多出来的:['http.server.requests'] jvm.memory*:4 个,例如 ['jvm.memory.committed', 'jvm.memory.max', 'jvm.memory.usage.after.gc', 'jvm.memory.used'] jvm.gc*:6 个,例如 ['jvm.gc.live.data.size', 'jvm.gc.max.data.size', 'jvm.gc.memory.allocated', 'jvm.gc.memory.promoted'] jvm.threads*:5 个,例如 ['jvm.threads.daemon', 'jvm.threads.live', 'jvm.threads.peak', 'jvm.threads.started'] process*:6 个,例如 ['process.cpu.time', 'process.cpu.usage', 'process.files.max', 'process.files.open'] system*:3 个,例如 ['system.cpu.count', 'system.cpu.usage', 'system.load.average.1m'] tomcat*:6 个,例如 ['tomcat.sessions.active.current', 'tomcat.sessions.active.max', 'tomcat.sessions.alive.max', 'tomcat.sessions.created'] executor*:7 个,例如 ['executor.active', 'executor.completed', 'executor.pool.core', 'executor.pool.max'] disk*:2 个,例如 ['disk.free', 'disk.total'] logback*:1 个,例如 ['logback.events'] application*:2 个,例如 ['application.ready.time', 'application.started.time'] http*:2 个,例如 ['http.server.requests', 'http.server.requests.active']
JVM、进程、系统、Tomcat、线程池、日志、启动耗时;http.server.requests 在第一个请求之后才出现。
总次数(COUNT)= 86;统计量 ['COUNT', 'TOTAL_TIME', 'MAX'];baseUnit=seconds
标签 exception:2 个取值 ['IllegalStateException', 'none']
标签 method:1 个取值 ['GET']
标签 error:2 个取值 ['IllegalStateException', 'none']
标签 uri:13 个取值 ['/queue', '/many', '/weak', '/user/{id}', '/fast', '/work', '/**', '/actuator/metrics/{requiredMetricName}', '/order', '/size', '/actuator/metrics', '/boom']
标签 outcome:3 个取值 ['CLIENT_ERROR', 'SUCCESS', 'SERVER_ERROR']
标签 status:3 个取值 ['404', '500', '200']
tag=uri:/user/{id} → COUNT 31
tag=status:404 → COUNT 30
tag=outcome:SERVER_ERROR → COUNT 5
tag=uri:/** → COUNT 30
tag=uri:/nope/1 →
tag=status:500 的 exception 标签取值:[['IllegalStateException']]uri 用路由模板,404 落在 /**;exception、outcome、status 都是低基数标签。
orders.created:baseUnit=None,[('COUNT', 3.0)],标签 [('type', ['a', 'b'])]
work.duration:baseUnit=seconds,[('COUNT', 3.0), ('TOTAL_TIME', 0.073), ('MAX', 0.035)],标签 []
payload.size:baseUnit=bytes,[('COUNT', 3.0), ('TOTAL', 600.0)],标签 []
orders.created?tag=type:a → COUNT 2
Gauge queue.size(Gauge.builder 引用字段 queue):7;g(/queue?n=3) 之后 → 3
Gauge weak.demo(reg.gauge("weak.demo", Tags.empty(), new AtomicInteger(42)),没有任何地方持有这个对象):注册后立刻读 = 42.0;紧接着两次 System.gc() 之后读 = NaN;后来通过 /actuator/metrics/weak.demo 读 = NaNCounter、Timer、DistributionSummary、Gauge 的用法;Gauge 弱引用被观察对象。
创建 100000 个同名不同 id 标签的 Counter(many.ids):Meter 总数 105 → 100108,用时 220 ms,GC 之后堆占用 17 MB → 70 MB 创建 100000 个同名不同 id 标签的 Counter(capped.ids):Meter 总数 100109 → 100209,用时 38 ms,GC 之后堆占用 70 MB → 70 MB
10 万个不同标签的 Counter 多占约 53 MB;MeterFilter 能把标签截在上限。
抓取前(Meter 数较少):/actuator/prometheus 共 258 行,17 KB,用时 13 ms
创建了 100000 个 many.ids 之后:100381 行,3137 KB,用时 232 ms
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{area="heap",id="G1 Eden Space"} 1.6777216E7 | jvm_memory_used_bytes{area="heap",id="G1 Old Gen"} 1.5126088E7 | jvm_memory_used_bytes{area="heap",id="G1 Survivor Space"} 3513792.0
# TYPE http_server_requests_seconds summary | # TYPE http_server_requests_seconds_max gauge
http_server_requests_seconds_count{error="none",exception="none",method="GET",outcome="SUCCESS",status="200",uri="/user/{id}"} 31
# TYPE orders_total counter | orders_total{type="a"} 2.0 | orders_total{type="b"} 1.0
# TYPE work_duration_seconds summary | # TYPE work_duration_seconds_max gauge
work_duration_seconds_count 3 | work_duration_seconds_sum 0.072557124 | work_duration_seconds_max 0.035021791
payload_size_bytes_count 3 | payload_size_bytes_sum 600.0 | payload_size_bytes_max 300.0
queue_size 3.0每次抓取输出全部 Meter;名字会被转换,orders.created 变成 orders_total。