<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-micrometer-metrics</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-influx</artifactId>
<version>${micrometer.version}</version>
</dependency>
Vert.x Micrometer 指标
该项目是 Vert.x 指标服务提供接口 (SPI) 的一个实现。它使用 Micrometer 来管理指标并报告给多个后端。
特性
-
Vert.x 核心工具监控:TCP/HTTP 客户端和服务器、
DatagramSocket
、EventBus
和连接池 -
通过 Micrometer 定义的用户指标
-
报告到 Micrometer 支持的任何后端
-
为 InfluxDB、Prometheus 和 JMX 报告内置选项。
InfluxDB
快速入门
vertx-micrometer-metrics 和 micrometer-registry-influx 模块必须存在于 classpath 中。
Maven 用户应将其添加到其项目 POM 文件中
Gradle 用户,应将其添加到其构建文件中
compile 'io.vertx:vertx-micrometer-metrics:5.0.1'
compile 'io.micrometer:micrometer-registry-influx:${micrometer.version}'
配置示例
Vert.x 默认不启用 SPI 实现。您必须在 Vert.x 选项中启用指标收集。
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setInfluxDbOptions(new VertxInfluxDbOptions().setEnabled(true))
.setEnabled(true)));
使用特定 URI
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setInfluxDbOptions(new VertxInfluxDbOptions().setEnabled(true)
.setUri("http://influxdb.example.com:8888"))
.setEnabled(true)));
连接到 InfluxDB V2
连接到 InfluxDB V2 要求至少设置 org
属性。
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setInfluxDbOptions(new VertxInfluxDbOptions().setEnabled(true)
.setOrg("my-org"))
.setEnabled(true)));
使用特定的数据库名称或存储桶
配置特定数据库名称
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setInfluxDbOptions(new VertxInfluxDbOptions().setEnabled(true)
.setDb("sales-department"))
.setEnabled(true)));
对于 InfluxDB V2,您也可以使用 setBucket
。
带认证
可以使用用户名和密码配置认证
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setInfluxDbOptions(new VertxInfluxDbOptions().setEnabled(true)
.setUserName("username")
.setPassword("password"))
.setEnabled(true)));
或者可以使用令牌配置
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setInfluxDbOptions(new VertxInfluxDbOptions().setEnabled(true)
.setToken(authToken))
.setEnabled(true)));
Prometheus
快速入门
vertx-micrometer-metrics 和 micrometer-registry-prometheus 模块必须存在于 classpath 中。您可能还需要 vertx-web 来暴露指标。
Maven 用户应将其添加到其项目 POM 文件中
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-micrometer-metrics</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>${micrometer.version}</version>
</dependency>
Gradle 用户,应将其添加到其构建文件中
compile 'io.vertx:vertx-micrometer-metrics:5.0.1'
compile 'io.micrometer:micrometer-registry-prometheus:${micrometer.version}'
配置示例
Vert.x 默认不启用 SPI 实现。您必须在 Vert.x 选项中启用指标收集
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
.setEnabled(true)));
使用带有自定义端点的嵌入式 HTTP 服务器
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true)
.setStartEmbeddedServer(true)
.setEmbeddedServerOptions(new HttpServerOptions().setPort(8080))
.setEmbeddedServerEndpoint("/metrics/vertx"))
.setEnabled(true)));
如果未指定嵌入式服务器端点,则默认为 /metrics。
使用自定义 HTTP 服务器
PrometheusRequestHandler
在抓取和提供 Prometheus 指标方面提供了灵活性。
vertx.createHttpServer()
.requestHandler(PrometheusRequestHandler.create(prometheusMeterRegistry, "/metrics/prometheus"))
.listen(8888);
将指标绑定到现有的 Vert.x Web 路由器
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
.setEnabled(true)));
// Later on, creating a router
Router router = Router.router(vertx);
router.route("/metrics").handler(PrometheusScrapingHandler.create());
vertx.createHttpServer().requestHandler(router).listen(8080);
JMX
快速入门
vertx-micrometer-metrics 和 micrometer-registry-jmx 模块必须存在于 classpath 中。
Maven 用户应将其添加到其项目 POM 文件中
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-micrometer-metrics</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-jmx</artifactId>
<version>${micrometer.version}</version>
</dependency>
Gradle 用户,应将其添加到其构建文件中
compile 'io.vertx:vertx-micrometer-metrics:5.0.1'
compile 'io.micrometer:micrometer-registry-jmx:${micrometer.version}'
配置示例
Vert.x 默认不启用 SPI 实现。您必须在 Vert.x 选项中启用指标收集
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setJmxMetricsOptions(new VertxJmxMetricsOptions().setEnabled(true))
.setEnabled(true)));
带步长和域
在 Micrometer 中,step
指的是报告周期(以秒为单位)。domain
是注册 MBean 的 JMX 域。
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setJmxMetricsOptions(new VertxJmxMetricsOptions().setEnabled(true)
.setStep(5)
.setDomain("my.metrics.domain"))
.setEnabled(true)));
其他后端或组合
即使并非所有 Micrometer 支持的后端都在 Vert.x 选项中实现,仍然可以创建任何 Micrometer 注册表并将其传递给 Vert.x。
可用后端列表包括 Graphite、Ganglia、Atlas 等。它还启用了Micrometer 复合注册表,以便将相同的指标报告给多个后端。
在此示例中,指标同时报告给 JMX 和 Graphite
CompositeMeterRegistry myRegistry = new CompositeMeterRegistry();
myRegistry.add(new JmxMeterRegistry(s -> null, Clock.SYSTEM));
myRegistry.add(new GraphiteMeterRegistry(s -> null, Clock.SYSTEM));
Vertx vertx = Vertx.builder()
.with(new VertxOptions()
.setMetricsOptions(new MicrometerMetricsOptions()
.setEnabled(true)))
.withMetrics(new MicrometerMetricsFactory(myRegistry))
.build();
高级用法
有关选项的完整列表,请参阅 MicrometerMetricsOptions
。
Prometheus 中的平均值和分位数
默认情况下,当使用 Prometheus 注册表时,直方图类型的指标将不包含平均值或分位数统计信息。
平均值并非开箱即用,但它们通常通过 promql
在查询时计算。例如,过去 5 分钟内 HTTP 客户端响应时间的平均值
rate(vertx_http_client_response_time_seconds_sum[5m])
/
rate(vertx_http_client_response_time_seconds_count[5m])
要计算分位数,有两种可用选项。第一种是全局激活分位数统计信息,使其可用于 Prometheus 函数 histogram_quantile
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true)
.setPublishQuantiles(true))
.setEnabled(true)));
然后,例如 HTTP 客户端响应时间的 promql
查询,过去 5 分钟的第 99 个百分位数
histogram_quantile(0.99, sum(rate(vertx_http_client_response_time_seconds_bucket[5m])) by (le))
此选项的优点是可以在 promql
中利用,并在各个维度上进行聚合。缺点是它在底层为统计数据创建了大量时间序列。
第二种选择是创建有限的、不可跨维度聚合的统计数据。这需要直接访问 Micrometer / Prometheus 注册表
PrometheusMeterRegistry registry = (PrometheusMeterRegistry) BackendRegistries.getDefaultNow();
registry.config().meterFilter(
new MeterFilter() {
@Override
public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
return DistributionStatisticConfig.builder()
.percentiles(0.95, 0.99)
.build()
.merge(config);
}
});
另请参阅,更多关于直方图和百分位数
此外,您可以查看一些完整的示例。它们附带了一些设置 Prometheus 和在 Grafana 中查看仪表盘的说明。
用户自定义指标
可以访问 Micrometer 注册表,以便创建新指标或获取现有指标。默认情况下,将使用一个唯一的注册表,并在 JVM 的 Vert.x 实例之间共享。
MeterRegistry registry = BackendRegistries.getDefaultNow();
还可以为每个 Vert.x 实例设置单独的注册表,通过在指标选项中提供注册表名称。然后可以专门检索它
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setInfluxDbOptions(new VertxInfluxDbOptions().setEnabled(true)) // or VertxPrometheusOptions
.setRegistryName("my registry")
.setEnabled(true)));
// Later on:
MeterRegistry registry = BackendRegistries.getNow("my registry");
例如,这是一个自定义计时器,它将跟踪定期调用的代码片段的执行时间
MeterRegistry registry = BackendRegistries.getDefaultNow();
Timer timer = Timer
.builder("my.timer")
.description("a description of what this timer does")
.register(registry);
vertx.setPeriodic(1000, l -> {
timer.record(() -> {
// Running here some operation to monitor
});
});
有关更多示例、Micrometer 注册表文档以及如何创建指标的信息,请查阅Micrometer 文档。
重用现有注册表
可以重用现有的 Micrometer 注册表(或 Prometheus Java 客户端的 CollectorRegistry
),并使用 VertxBuilder
将其注入 Vert.x 实例。
PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
// You could also reuse an existing registry from the Prometheus Java client:
PrometheusRegistry prometheusClientRegistry = new PrometheusRegistry();
registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT, prometheusClientRegistry, Clock.SYSTEM);
// It's reused in MicrometerMetricsOptions.
// Prometheus options configured here, such as "setPublishQuantiles(true)", will affect the whole registry.
Vertx.builder()
.with(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true)
.setPublishQuantiles(true))
.setEnabled(true)))
.withMetrics(new MicrometerMetricsFactory(registry))
.build();
Netty 指标
Vert.x 依赖 Netty 作为网络层。
Vert.x Micrometer Metrics 可以配置为收集 Netty 指标
metricsOptions.setNettyMetricsEnabled(true);
收集的指标数据与 Vert.x 特定的字节缓冲区分配器和事件循环组相关。
其他插装
由于提供了对 Micrometer 注册表的直接访问,因此可以利用 Micrometer API
MeterRegistry registry = BackendRegistries.getDefaultNow();
DiskSpaceMetrics metrics = new DiskSpaceMetrics(new File("/opt/myapp/data"));
metrics.bindTo(registry);
指标名称
Vert.x 提供的每个指标都可以通过指标选项使用 MetricsNaming
和 setMetricsNaming
进行重命名。Vert.x 4 中更改了默认指标名称,以更好地与后端约定对齐,但仍可以检索 Vert.x 3.x 中使用的名称以实现兼容性
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
.setMetricsNaming(MetricsNaming.v3Names())
.setEnabled(true)));
标签和匹配器
Vert.x Micrometer Metrics 定义了一组标签(也称为标记或字段),用于为指标提供维度。例如,与事件总线消息相关的指标具有一个 address 标签,这允许查询特定事件总线地址的时间序列,或按地址比较时间序列,或执行查询 API 允许的任何类型的聚合。
在设置指标选项时,您可以指定要启用或禁用的标签
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
.setLabels(EnumSet.of(Label.REMOTE, Label.LOCAL, Label.HTTP_CODE, Label.HTTP_PATH))
.setEnabled(true)));
标签的完整列表在此处详细说明:Label
。
启用标签可能会导致值基数过高,这可能会对指标后端造成问题并影响性能。因此必须谨慎使用。通常,当可能的值集有界时,启用标签是没问题的。 |
因此,默认启用的标签仅限于已知有界值的标签。
除了启用/禁用之外,还可以进一步与标签交互。有两种方法:
使用匹配器
Match
对象可用于通过精确字符串或正则表达式(前者更高效)匹配来过滤或重命名某些标签值。
这是一个将 HTTP 服务器指标限制为仅包含标签 local=localhost:8080 的示例
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
.addLabelMatch(new Match()
// Restrict HTTP server metrics to those with label "local=localhost:8080" only
.setDomain(MetricsDomain.HTTP_SERVER)
.setLabel("local")
.setValue("localhost:8080"))
.setEnabled(true)));
当在 Match 中指定 alias 时,它将用于重命名值而不是过滤。
匹配器通过配置设置,因为它们是通过 MicrometerMetricsOptions
设置的,因此在通过配置控制标签时特别有用。
使用 Micrometer 的 MeterFilter
可以直接访问 Micrometer 的MeterFilter API 以定义标签规则。与匹配器相比,它在操作标签方面提供了更多功能,但无法从配置中定义。因此两者各有优势。
这是一个将 HTTP 请求的实际 path
标签替换为使用正则表达式的通用形式的示例
MeterRegistry registry = BackendRegistries.getDefaultNow();
Pattern pattern = Pattern.compile("/foo/bar/.*");
registry.config().meterFilter(
MeterFilter.replaceTagValues(Label.HTTP_PATH.toString(), actualPath -> {
Matcher m = pattern.matcher(actualPath);
if (m.matches()) {
return "/foo/bar/:id";
}
return actualPath;
}, ""));
匹配器在底层使用 MeterFilters。 |
自定义标签提供者
您可以定义一个函数,为 HTTP 服务器或客户端指标生成额外的标记(或标签)。此函数将 HttpRequest
对象作为参数,并返回 Tag
的 Iterable。
例如,以下是如何在服务器和客户端指标中将 x-user 头部映射到自定义标签 user 的方法
Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
.setServerRequestTagsProvider(req -> {
String user = req.headers().get("x-user");
return Collections.singletonList(Tag.of("user", user));
})
.setClientRequestTagsProvider(req -> {
String user = req.headers().get("x-user");
return Collections.singletonList(Tag.of("user", user));
})
.setEnabled(true)));
快照
可以从 Measured
对象创建一个 MetricsService
,以便获取其相关指标和测量的快照。快照以 JsonObject
的形式返回。
一个众所周知的 Measured 对象就是 Vertx
MetricsService metricsService = MetricsService.create(vertx);
JsonObject metrics = metricsService.getMetricsSnapshot();
System.out.println(metrics);
其他组件,例如 EventBus
或 HttpServer
都是可测量的
HttpServer server = vertx.createHttpServer();
MetricsService metricsService = MetricsService.create(server);
JsonObject metrics = metricsService.getMetricsSnapshot();
System.out.println(metrics);
最后,可以根据指标的基本名称过滤返回的指标
MetricsService metricsService = MetricsService.create(vertx);
// Client + server
JsonObject metrics = metricsService.getMetricsSnapshot("vertx.http");
System.out.println(metrics);
Vert.x 核心指标
本节列出了通过监控 Vert.x 核心工具生成的所有指标。
指标后端可能对指标命名有不同的约定或规则。下面描述的名称是 Vert.x 4 中使用的默认名称,使用下划线分隔。实际名称可能因指标后端而异。 |
TCP 客户端
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 计数器 | 从远程主机接收的字节数。 |
|
| 计数器 | 发送到远程主机的字节数。 |
|
| 度量器 | 当前打开到远程主机的连接数。 |
|
| 计数器 | 错误数。 |
HTTP 客户端
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 计数器 | 从远程主机接收的字节数。 |
|
| 计数器 | 发送到远程主机的字节数。 |
|
| 度量器 | 当前打开到远程主机的连接数。 |
|
| 计数器 | 错误数。 |
|
| 度量器 | 正在处理中、等待响应的请求数。 |
|
| 计数器 | 已发送请求数。 |
|
| 总结 | 请求的字节大小。 |
|
| 计时器 | 响应时间(秒)。 |
|
| 计数器 | 已接收响应数。 |
|
| 总结 | 响应的字节大小。 |
|
| 度量器 | 当前打开的 WebSocket 连接数。 |
TCP 服务器
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 计数器 | Net 服务器接收的字节数。 |
|
| 计数器 | Net 服务器发送的字节数。 |
|
| 度量器 | 与 Net 服务器建立的已打开连接数。 |
|
| 计数器 | 错误数。 |
HTTP 服务器
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 计数器 | HTTP 服务器接收的字节数。 |
|
| 计数器 | HTTP 服务器发送的字节数。 |
|
| 度量器 | 与 HTTP 服务器建立的已打开连接数。 |
|
| 计数器 | 错误数。 |
|
| 度量器 | 正在处理的请求数。 |
|
| 计数器 | 已处理请求数。 |
|
| 计数器 | 请求重置次数。 |
|
| 总结 | 请求的字节大小。 |
|
| 计时器 | 请求处理时间(秒)。 |
|
| 总结 | 响应的字节大小。 |
|
| 度量器 | 当前打开的 WebSocket 连接数。 |
数据报套接字
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 总结 | 在 |
| (无) | 总结 | 发送到远程主机的字节总数。 |
|
| 计数器 | 错误总数。 |
事件总线
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 总结 | 从事件总线集群对等方读取消息时接收的字节总数。 |
|
| 总结 | 向事件总线集群对等方发送消息时发送的字节总数。 |
|
| 度量器 | 正在使用的事件总线处理器数量。 |
|
| 度量器 | 尚未处理的消息数量。如果 |
|
| 计数器 | 已处理消息数。 |
|
| 计数器 | 已发布消息数(发布/订阅)。 |
|
| 计数器 | 已丢弃消息数(例如,处理程序未注册时仍待处理的消息,或溢出消息)。 |
|
| 计数器 | 已发送消息数(点对点)。 |
|
| 计数器 | 已接收消息数。 |
|
| 计数器 | 已传递到处理器的消息数。 |
|
| 计数器 | 消息回复失败数。 |
通用指标
连接池指标
Vert.x 客户端,除了核心 HTTP 客户端外,也可能暴露连接池指标。
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 计时器 | 在处理前在队列中花费的时间(秒)。 |
|
| 度量器 | 队列中待处理元素的数量。 |
|
| 计时器 | 使用资源的时间(即工作线程池的处理时间)。 |
|
| 度量器 | 已使用的资源数量。 |
|
| 计数器 | 已完成使用资源的元素数量(即工作线程池执行的任务总数)。 |
|
| 度量器 | 连接池使用率,仅在能够确定最大连接池大小时才存在。 |
客户端指标
Vert.x 客户端,除了核心 HTTP/Net 客户端外,也可能实现一套标准的客户端指标。
此类客户端指标以“客户端类型”标识符命名,在下表中显示为 $TYPE
。
namespace
标签的含义由客户端实现自行决定。
指标名称 | 标签 | 类型 | 描述 |
---|---|---|---|
|
| 度量器 | 队列中待处理元素的数量。 |
|
| 计时器 | 在处理前在队列中花费的时间(秒)。 |
|
| 度量器 | 正在处理的元素数量。 |
|
| 计时器 | 处理时间,从请求开始到响应结束(秒)。 |
|
| 计数器 | 重置总次数。 |
数据库客户端指标
-
Vert.x SQL 客户端
-
Vert.x Redis 客户端
-
…
连接池指标带有 pool_type
,例如 SQL 客户端使用 sql
类型
-
vertx.pool.queue.pending
和pool_type
=sql -
vertx.pool.queue.time
和pool_type
=sql -
vertx.pool.usage
和pool_type
=sql -
vertx.pool.ratio
pool_type
=sql -
vertx.pool.completed
pool_type
=sql -
vertx.pool.in.use
pool_type
=sql
客户端指标类型出现在指标名称中
-
vertx.sql.processing.pending
-
vertx.sql.processing.time
为了区分连接池,您可以在 PoolOptions
上设置连接池名称,并将其作为标签暴露
-
vertx.pool.queue.pending
和pool_type
=sql 以及pool_name
=the-pool-name -
vertx.pool.queue.time
和pool_type
=sql 以及pool_name
=the-pool-name -
vertx.pool.usage
和pool_type
=sql 以及pool_name
=the-pool-name -
vertx.pool.ratio
pool_type
=sql 以及pool_name
=the-pool-name -
vertx.pool.completed
pool_type
=sql 以及pool_name
=the-pool-name -
vertx.pool.in.use
pool_type
=sql 以及pool_name
=the-pool-name
同样,客户端指标使用命名空间来区分它们
-
vertx.sql.processing.pending
和client_namespace
=the-client-name
-
vertx.sql.processing.time
和client_namespace
=the-client-name
必须配置 Micrometer 来暴露这些标签
micrometerMetricsOptions.addLabels(Label.POOL_NAME);
micrometerMetricsOptions.addLabels(Label.NAMESPACE);
Vert.x SQL 客户端
Vert.x SQL 客户端使用 sql
类型。
使用 PoolOptions#setName(String)
来命名连接池
poolOptions.setName("the-pool-name");
同样,使用 SqlConnectOptions#setMetricsName(String)
来限定客户端指标的范围
connectOptions.setMetricsName("the-client-name");
Vert.x Redis 客户端
Vert.x Redis 客户端使用 redis
类型。
使用 RedisOptions#setPoolName(String)
来命名连接池
redisOptions.setPoolName("the-pool-name");
同样,使用 RedisOptions#setMetricsName(String)
来限定客户端指标的范围
redisOptions.setMetricsName("the-client-name");