From 0b1b35084df74b8bf95751e45b490e8c84a86110 Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Fri, 10 Jun 2022 16:08:44 +0200 Subject: [PATCH] Backport of #143 to 4.2 branch Signed-off-by: Thomas Segismont --- .../micrometer/impl/AbstractMetrics.java | 18 +++-- .../micrometer/impl/VertxClientMetrics.java | 8 +- .../impl/VertxDatagramSocketMetrics.java | 9 ++- .../micrometer/impl/VertxEventBusMetrics.java | 8 +- .../impl/VertxHttpClientMetrics.java | 8 +- .../impl/VertxHttpServerMetrics.java | 8 +- .../impl/VertxMetricsFactoryImpl.java | 16 +++- .../micrometer/impl/VertxMetricsImpl.java | 44 ++++------- .../impl/VertxNetClientMetrics.java | 12 +-- .../impl/VertxNetServerMetrics.java | 12 +-- .../micrometer/impl/VertxPoolMetrics.java | 8 +- .../vertx/micrometer/impl/meters/Gauges.java | 76 ++++++++++++------- .../micrometer/impl/meters/GaugesTest.java | 36 +++++++-- 13 files changed, 165 insertions(+), 98 deletions(-) diff --git a/src/main/java/io/vertx/micrometer/impl/AbstractMetrics.java b/src/main/java/io/vertx/micrometer/impl/AbstractMetrics.java index 0e43dd82..b223ca34 100644 --- a/src/main/java/io/vertx/micrometer/impl/AbstractMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/AbstractMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 Red Hat, Inc. + * Copyright 2022 Red Hat, Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,6 +16,7 @@ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.micrometer.Label; import io.vertx.micrometer.MetricsDomain; @@ -24,6 +25,7 @@ import io.vertx.micrometer.impl.meters.Summaries; import io.vertx.micrometer.impl.meters.Timers; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.LongAdder; @@ -35,20 +37,24 @@ public abstract class AbstractMetrics implements MicrometerMetrics { protected final MeterRegistry registry; protected final String category; + protected final ConcurrentMap gaugesTable; - AbstractMetrics(MeterRegistry registry) { + AbstractMetrics(MeterRegistry registry, ConcurrentMap gaugesTable) { this.registry = registry; + this.gaugesTable = gaugesTable; this.category = null; } - AbstractMetrics(MeterRegistry registry, String category) { + AbstractMetrics(MeterRegistry registry, String category, ConcurrentMap gaugesTable) { this.registry = registry; this.category = category; + this.gaugesTable = gaugesTable; } - AbstractMetrics(MeterRegistry registry, MetricsDomain domain) { + AbstractMetrics(MeterRegistry registry, MetricsDomain domain, ConcurrentMap gaugesTable) { this.registry = registry; this.category = (domain == null) ? null : domain.toCategory(); + this.gaugesTable = gaugesTable; } /** @@ -69,11 +75,11 @@ Counters counters(String name, String description, Label... keys) { } Gauges longGauges(String name, String description, Label... keys) { - return new Gauges<>(baseName() + name, description, LongAdder::new, LongAdder::doubleValue, registry, keys); + return new Gauges<>(gaugesTable, baseName() + name, description, LongAdder::new, LongAdder::doubleValue, registry, keys); } Gauges> doubleGauges(String name, String description, Label... keys) { - return new Gauges<>(baseName() + name, description, () -> new AtomicReference<>(0d), AtomicReference::get, registry, keys); + return new Gauges<>(gaugesTable, baseName() + name, description, () -> new AtomicReference<>(0d), AtomicReference::get, registry, keys); } Summaries summaries(String name, String description, Label... keys) { diff --git a/src/main/java/io/vertx/micrometer/impl/VertxClientMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxClientMetrics.java index ec8a8c58..4cd6fed1 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxClientMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxClientMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,6 +16,7 @@ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.net.SocketAddress; import io.vertx.core.spi.metrics.ClientMetrics; @@ -25,6 +26,7 @@ import io.vertx.micrometer.impl.meters.Gauges; import io.vertx.micrometer.impl.meters.Timers; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.LongAdder; /** @@ -37,8 +39,8 @@ class VertxClientMetrics extends AbstractMetrics { private final Gauges processingPending; private final Counters resetCount; - VertxClientMetrics(MeterRegistry registry, String type, MetricsNaming names) { - super(registry, type); + VertxClientMetrics(MeterRegistry registry, String type, MetricsNaming names, ConcurrentMap gaugesTable) { + super(registry, type, gaugesTable); queueDelay = timers(names.getClientQueueTime(), "Time spent in queue before being processed", Label.REMOTE, Label.NAMESPACE); queueSize = longGauges(names.getClientQueuePending(), "Number of pending elements in queue", Label.REMOTE, Label.NAMESPACE); processingTime = timers(names.getClientProcessingTime(), "Processing time, from request start to response end", Label.REMOTE, Label.NAMESPACE); diff --git a/src/main/java/io/vertx/micrometer/impl/VertxDatagramSocketMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxDatagramSocketMetrics.java index 3cf05b8f..4faa6cef 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxDatagramSocketMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxDatagramSocketMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Red Hat, Inc. and/or its affiliates + * Copyright 2022 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ */ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.net.SocketAddress; import io.vertx.core.spi.metrics.DatagramSocketMetrics; @@ -25,6 +26,8 @@ import io.vertx.micrometer.impl.meters.Counters; import io.vertx.micrometer.impl.meters.Summaries; +import java.util.concurrent.ConcurrentMap; + /** * @author Joel Takvorian */ @@ -35,8 +38,8 @@ class VertxDatagramSocketMetrics extends AbstractMetrics implements DatagramSock private volatile String localAddress; - VertxDatagramSocketMetrics(MeterRegistry registry, MetricsNaming names) { - super(registry, MetricsDomain.DATAGRAM_SOCKET); + VertxDatagramSocketMetrics(MeterRegistry registry, MetricsNaming names, ConcurrentMap gaugesTable) { + super(registry, MetricsDomain.DATAGRAM_SOCKET, gaugesTable); bytesReceived = summaries(names.getDatagramBytesRead(), "Total number of datagram bytes received", Label.LOCAL); bytesSent = summaries(names.getDatagramBytesWritten(), "Total number of datagram bytes sent"); errorCount = counters(names.getDatagramErrorCount(), "Total number of datagram errors", Label.CLASS_NAME); diff --git a/src/main/java/io/vertx/micrometer/impl/VertxEventBusMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxEventBusMetrics.java index ef571aa4..31d1c246 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxEventBusMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxEventBusMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,6 +15,7 @@ */ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.eventbus.Message; import io.vertx.core.eventbus.ReplyFailure; @@ -26,6 +27,7 @@ import io.vertx.micrometer.impl.meters.Gauges; import io.vertx.micrometer.impl.meters.Summaries; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.LongAdder; /** @@ -46,8 +48,8 @@ class VertxEventBusMetrics extends AbstractMetrics implements EventBusMetrics gaugesTable) { + super(registry, MetricsDomain.EVENT_BUS, gaugesTable); handlers = longGauges(names.getEbHandlers(), "Number of event bus handlers in use", Label.EB_ADDRESS); pending = longGauges(names.getEbPending(), "Number of messages not processed yet", Label.EB_ADDRESS, Label.EB_SIDE); processed = counters(names.getEbProcessed(), "Number of processed messages", Label.EB_ADDRESS, Label.EB_SIDE); diff --git a/src/main/java/io/vertx/micrometer/impl/VertxHttpClientMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxHttpClientMetrics.java index 257a4358..928972ef 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxHttpClientMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxHttpClientMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,6 +16,7 @@ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.http.WebSocket; import io.vertx.core.net.SocketAddress; @@ -31,6 +32,7 @@ import io.vertx.micrometer.impl.meters.Summaries; import io.vertx.micrometer.impl.meters.Timers; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.LongAdder; /** @@ -47,8 +49,8 @@ class VertxHttpClientMetrics extends VertxNetClientMetrics { private final Summaries responseBytes; private final Gauges wsConnections; - VertxHttpClientMetrics(MeterRegistry registry, MetricsNaming names) { - super(registry, MetricsDomain.HTTP_CLIENT, names); + VertxHttpClientMetrics(MeterRegistry registry, MetricsNaming names, ConcurrentMap gaugesTable) { + super(registry, MetricsDomain.HTTP_CLIENT, names, gaugesTable); queueDelay = timers(names.getHttpQueueTime(), "Time spent in queue before being processed", Label.LOCAL, Label.REMOTE); queueSize = longGauges(names.getHttpQueuePending(), "Number of pending elements in queue", Label.LOCAL, Label.REMOTE); requests = longGauges(names.getHttpActiveRequests(), "Number of requests waiting for a response", Label.LOCAL, Label.REMOTE, Label.HTTP_PATH, Label.HTTP_METHOD); diff --git a/src/main/java/io/vertx/micrometer/impl/VertxHttpServerMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxHttpServerMetrics.java index b9a02385..5b2cb6af 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxHttpServerMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxHttpServerMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,6 +15,7 @@ */ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; import io.vertx.core.http.HttpMethod; @@ -34,6 +35,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.LongAdder; import java.util.function.Function; @@ -50,8 +52,8 @@ class VertxHttpServerMetrics extends VertxNetServerMetrics { private final Gauges wsConnections; private final Function> customTagsProvider; - VertxHttpServerMetrics(MeterRegistry registry, MetricsNaming names, Function> customTagsProvider) { - super(registry, MetricsDomain.HTTP_SERVER, names); + VertxHttpServerMetrics(MeterRegistry registry, MetricsNaming names, Function> customTagsProvider, ConcurrentMap gaugesTable) { + super(registry, MetricsDomain.HTTP_SERVER, names, gaugesTable); this.customTagsProvider = customTagsProvider; requests = longGauges(names.getHttpActiveRequests(), "Number of requests being processed", Label.LOCAL, Label.REMOTE, Label.HTTP_PATH, Label.HTTP_METHOD); requestCount = counters(names.getHttpRequestsCount(), "Number of processed requests", Label.LOCAL, Label.REMOTE, Label.HTTP_ROUTE, Label.HTTP_PATH, Label.HTTP_METHOD, Label.HTTP_CODE); diff --git a/src/main/java/io/vertx/micrometer/impl/VertxMetricsFactoryImpl.java b/src/main/java/io/vertx/micrometer/impl/VertxMetricsFactoryImpl.java index 28672c3a..58f55227 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxMetricsFactoryImpl.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxMetricsFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,6 +15,8 @@ */ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; @@ -29,11 +31,17 @@ import io.vertx.micrometer.backends.BackendRegistries; import io.vertx.micrometer.backends.BackendRegistry; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; + /** * @author Joel Takvorian */ public class VertxMetricsFactoryImpl implements VertxMetricsFactory { + private static final Map> tables = new WeakHashMap<>(1); + @Override public VertxMetrics metrics(VertxOptions vertxOptions) { MetricsOptions metricsOptions = vertxOptions.getMetricsOptions(); @@ -44,7 +52,11 @@ public VertxMetrics metrics(VertxOptions vertxOptions) { options = new MicrometerMetricsOptions(metricsOptions.toJson()); } BackendRegistry backendRegistry = BackendRegistries.setupBackend(options); - VertxMetricsImpl metrics = new VertxMetricsImpl(options, backendRegistry); + ConcurrentHashMap gaugesTable; + synchronized (tables) { + gaugesTable = tables.computeIfAbsent(backendRegistry.getMeterRegistry(), meterRegistry -> new ConcurrentHashMap<>()); + } + VertxMetricsImpl metrics = new VertxMetricsImpl(options, backendRegistry, gaugesTable); metrics.init(); if (options.isJvmMetricsEnabled()) { diff --git a/src/main/java/io/vertx/micrometer/impl/VertxMetricsImpl.java b/src/main/java/io/vertx/micrometer/impl/VertxMetricsImpl.java index c3c4264b..06542afb 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxMetricsImpl.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxMetricsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,6 +16,7 @@ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.datagram.DatagramSocketOptions; import io.vertx.core.http.HttpClientOptions; @@ -24,14 +25,7 @@ import io.vertx.core.net.NetClientOptions; import io.vertx.core.net.NetServerOptions; import io.vertx.core.net.SocketAddress; -import io.vertx.core.spi.metrics.ClientMetrics; -import io.vertx.core.spi.metrics.DatagramSocketMetrics; -import io.vertx.core.spi.metrics.EventBusMetrics; -import io.vertx.core.spi.metrics.HttpClientMetrics; -import io.vertx.core.spi.metrics.HttpServerMetrics; -import io.vertx.core.spi.metrics.PoolMetrics; -import io.vertx.core.spi.metrics.TCPMetrics; -import io.vertx.core.spi.metrics.VertxMetrics; +import io.vertx.core.spi.metrics.*; import io.vertx.micrometer.MetricsNaming; import io.vertx.micrometer.MicrometerMetricsOptions; import io.vertx.micrometer.backends.BackendRegistries; @@ -41,14 +35,9 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; -import static io.vertx.micrometer.MetricsDomain.DATAGRAM_SOCKET; -import static io.vertx.micrometer.MetricsDomain.EVENT_BUS; -import static io.vertx.micrometer.MetricsDomain.HTTP_CLIENT; -import static io.vertx.micrometer.MetricsDomain.HTTP_SERVER; -import static io.vertx.micrometer.MetricsDomain.NAMED_POOLS; -import static io.vertx.micrometer.MetricsDomain.NET_CLIENT; -import static io.vertx.micrometer.MetricsDomain.NET_SERVER; +import static io.vertx.micrometer.MetricsDomain.*; /** * Metrics SPI implementation for Micrometer. @@ -69,11 +58,8 @@ public class VertxMetricsImpl extends AbstractMetrics implements VertxMetrics { private final Map mapClientMetrics = new ConcurrentHashMap<>(); private final Set disabledCaterogies = new HashSet<>(); - /** - * @param options Vertx Prometheus options - */ - public VertxMetricsImpl(MicrometerMetricsOptions options, BackendRegistry backendRegistry) { - super(backendRegistry.getMeterRegistry()); + public VertxMetricsImpl(MicrometerMetricsOptions options, BackendRegistry backendRegistry, ConcurrentMap gaugesTable) { + super(backendRegistry.getMeterRegistry(), gaugesTable); this.backendRegistry = backendRegistry; registryName = options.getRegistryName(); MeterRegistry registry = backendRegistry.getMeterRegistry(); @@ -83,19 +69,19 @@ public VertxMetricsImpl(MicrometerMetricsOptions options, BackendRegistry backen names = options.getMetricsNaming(); eventBusMetrics = options.isMetricsCategoryDisabled(EVENT_BUS) ? null - : new VertxEventBusMetrics(registry, names); + : new VertxEventBusMetrics(registry, names, gaugesTable); datagramSocketMetrics = options.isMetricsCategoryDisabled(DATAGRAM_SOCKET) ? null - : new VertxDatagramSocketMetrics(registry, names); + : new VertxDatagramSocketMetrics(registry, names, gaugesTable); netClientMetrics = options.isMetricsCategoryDisabled(NET_CLIENT) ? null - : new VertxNetClientMetrics(registry, names); + : new VertxNetClientMetrics(registry, names, gaugesTable); netServerMetrics = options.isMetricsCategoryDisabled(NET_SERVER) ? null - : new VertxNetServerMetrics(registry, names); + : new VertxNetServerMetrics(registry, names, gaugesTable); httpClientMetrics = options.isMetricsCategoryDisabled(HTTP_CLIENT) ? null - : new VertxHttpClientMetrics(registry, names); + : new VertxHttpClientMetrics(registry, names, gaugesTable); httpServerMetrics = options.isMetricsCategoryDisabled(HTTP_SERVER) ? null - : new VertxHttpServerMetrics(registry, names, options.getRequestsTagsProvider()); + : new VertxHttpServerMetrics(registry, names, options.getRequestsTagsProvider(), gaugesTable); poolMetrics = options.isMetricsCategoryDisabled(NAMED_POOLS) ? null - : new VertxPoolMetrics(registry, names); + : new VertxPoolMetrics(registry, names, gaugesTable); } void init() { @@ -163,7 +149,7 @@ public PoolMetrics createPoolMetrics(String poolType, String poolName, int ma if (disabledCaterogies.contains(type)) { return DummyVertxMetrics.DummyClientMetrics.INSTANCE; } - VertxClientMetrics clientMetrics = mapClientMetrics.computeIfAbsent(type, t -> new VertxClientMetrics(registry, type, names)); + VertxClientMetrics clientMetrics = mapClientMetrics.computeIfAbsent(type, t -> new VertxClientMetrics(registry, type, names, gaugesTable)); return clientMetrics.forInstance(remoteAddress, namespace); } diff --git a/src/main/java/io/vertx/micrometer/impl/VertxNetClientMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxNetClientMetrics.java index 7e9815a7..9517f370 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxNetClientMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxNetClientMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,6 +16,7 @@ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.net.SocketAddress; import io.vertx.core.spi.metrics.TCPMetrics; @@ -25,6 +26,7 @@ import io.vertx.micrometer.impl.meters.Counters; import io.vertx.micrometer.impl.meters.Gauges; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.LongAdder; /** @@ -36,12 +38,12 @@ class VertxNetClientMetrics extends AbstractMetrics { private final Counters bytesSent; private final Counters errorCount; - VertxNetClientMetrics(MeterRegistry registry, MetricsNaming names) { - this(registry, MetricsDomain.NET_CLIENT, names); + VertxNetClientMetrics(MeterRegistry registry, MetricsNaming names, ConcurrentMap gaugesTable) { + this(registry, MetricsDomain.NET_CLIENT, names, gaugesTable); } - VertxNetClientMetrics(MeterRegistry registry, MetricsDomain domain, MetricsNaming names) { - super(registry, domain); + VertxNetClientMetrics(MeterRegistry registry, MetricsDomain domain, MetricsNaming names, ConcurrentMap gaugesTable) { + super(registry, domain, gaugesTable); connections = longGauges(names.getNetActiveConnections(), "Number of connections to the remote host currently opened", Label.LOCAL, Label.REMOTE); bytesReceived = counters(names.getNetBytesRead(), "Number of bytes received from the remote host", Label.LOCAL, Label.REMOTE); bytesSent = counters(names.getNetBytesWritten(), "Number of bytes sent to the remote host", Label.LOCAL, Label.REMOTE); diff --git a/src/main/java/io/vertx/micrometer/impl/VertxNetServerMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxNetServerMetrics.java index 1263657c..a5a326af 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxNetServerMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxNetServerMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,6 +15,7 @@ */ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.net.SocketAddress; import io.vertx.core.spi.metrics.TCPMetrics; @@ -24,6 +25,7 @@ import io.vertx.micrometer.impl.meters.Counters; import io.vertx.micrometer.impl.meters.Gauges; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.LongAdder; /** @@ -35,12 +37,12 @@ class VertxNetServerMetrics extends AbstractMetrics { private final Counters bytesSent; private final Counters errorCount; - VertxNetServerMetrics(MeterRegistry registry, MetricsNaming names) { - this(registry, MetricsDomain.NET_SERVER, names); + VertxNetServerMetrics(MeterRegistry registry, MetricsNaming names, ConcurrentMap gaugesTable) { + this(registry, MetricsDomain.NET_SERVER, names, gaugesTable); } - VertxNetServerMetrics(MeterRegistry registry, MetricsDomain domain, MetricsNaming names) { - super(registry, domain); + VertxNetServerMetrics(MeterRegistry registry, MetricsDomain domain, MetricsNaming names, ConcurrentMap gaugesTable) { + super(registry, domain, gaugesTable); connections = longGauges(names.getNetActiveConnections(), "Number of opened connections to the server", Label.LOCAL, Label.REMOTE); bytesReceived = counters(names.getNetBytesRead(), "Number of bytes received by the server", Label.LOCAL, Label.REMOTE); bytesSent = counters(names.getNetBytesWritten(), "Number of bytes sent by the server", Label.LOCAL, Label.REMOTE); diff --git a/src/main/java/io/vertx/micrometer/impl/VertxPoolMetrics.java b/src/main/java/io/vertx/micrometer/impl/VertxPoolMetrics.java index 401db6f2..31966461 100644 --- a/src/main/java/io/vertx/micrometer/impl/VertxPoolMetrics.java +++ b/src/main/java/io/vertx/micrometer/impl/VertxPoolMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The original author or authors + * Copyright (c) 2011-2022 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,6 +16,7 @@ package io.vertx.micrometer.impl; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.vertx.core.spi.metrics.PoolMetrics; import io.vertx.micrometer.Label; @@ -25,6 +26,7 @@ import io.vertx.micrometer.impl.meters.Gauges; import io.vertx.micrometer.impl.meters.Timers; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.LongAdder; @@ -39,8 +41,8 @@ class VertxPoolMetrics extends AbstractMetrics { private final Gauges> usageRatio; private final Counters completed; - VertxPoolMetrics(MeterRegistry registry, MetricsNaming names) { - super(registry, MetricsDomain.NAMED_POOLS); + VertxPoolMetrics(MeterRegistry registry, MetricsNaming names, ConcurrentMap gaugesTable) { + super(registry, MetricsDomain.NAMED_POOLS, gaugesTable); queueDelay = timers(names.getPoolQueueTime(), "Time spent in queue before being processed", Label.POOL_TYPE, Label.POOL_NAME); queueSize = longGauges(names.getPoolQueuePending(), "Number of pending elements in queue", Label.POOL_TYPE, Label.POOL_NAME); usage = timers(names.getPoolUsage(), "Time using a resource", Label.POOL_TYPE, Label.POOL_NAME); diff --git a/src/main/java/io/vertx/micrometer/impl/meters/Gauges.java b/src/main/java/io/vertx/micrometer/impl/meters/Gauges.java index 987f8d01..675a1775 100644 --- a/src/main/java/io/vertx/micrometer/impl/meters/Gauges.java +++ b/src/main/java/io/vertx/micrometer/impl/meters/Gauges.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Red Hat, Inc. and/or its affiliates + * Copyright 2022 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,23 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.vertx.micrometer.impl.meters; -import io.micrometer.core.instrument.Gauge; -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.*; import io.vertx.micrometer.Label; import io.vertx.micrometer.impl.Labels; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.function.Supplier; import java.util.function.ToDoubleFunction; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; /** * @author Joel Takvorian @@ -42,14 +35,16 @@ public class Gauges { private final Supplier tSupplier; private final ToDoubleFunction dGetter; private final MeterRegistry registry; - private final Map gauges = new ConcurrentHashMap<>(); + private final ConcurrentMap gauges; - public Gauges(String name, + public Gauges(ConcurrentMap gauges, + String name, String description, Supplier tSupplier, ToDoubleFunction dGetter, MeterRegistry registry, Label... keys) { + this.gauges = gauges; this.name = name; this.description = description; this.tSupplier = tSupplier; @@ -62,21 +57,50 @@ public T get(String... values) { return get(null, values); } - public synchronized T get(Iterable customTags, String... values) { - List tags = customTags != null - ? Stream.concat(Labels.toTags(keys, values).stream(), StreamSupport.stream(customTags.spliterator(), false)).collect(Collectors.toList()) - : Labels.toTags(keys, values); - // This method is synchronized to make sure the "T" built via supplier will match the one passed to Gauge - // since it is stored as WeakReference in Micrometer DefaultGauge, it must not be lost. - T t = tSupplier.get(); - // Register this gauge if necessary - // Note: we need here to go through the process of Gauge creation, even if it already exists, - // in order to get the Gauge ID. This ID generation is not trivial since it may involves attached MetricFilters. - // Micrometer will not register the gauge twice if it was already created. - Gauge g = Gauge.builder(name, t, dGetter) + @SuppressWarnings("unchecked") + public T get(Iterable customTags, String... values) { + Tags tags = Tags.of(Labels.toTags(keys, values)).and(customTags); + T candidate = tSupplier.get(); + ToDoubleFunc candidateFunc = new ToDoubleFunc<>(dGetter); + Gauge gauge = Gauge.builder(name, candidate, candidateFunc) .description(description) .tags(tags) .register(registry); - return gauges.computeIfAbsent(g.getId(), v -> t); + Meter.Id gaugeId = gauge.getId(); + Object res; + for (; ; ) { + res = gauges.get(gaugeId); + if (res != null) { + break; + } + ensureGetterInvoked(gauge); + if (candidateFunc.invoked) { + gauges.put(gaugeId, candidate); + res = candidate; + break; + } + } + return (T) res; + } + + private void ensureGetterInvoked(Gauge gauge) { + gauge.value(); + } + + private static class ToDoubleFunc implements ToDoubleFunction { + final ToDoubleFunction delegate; + volatile boolean invoked; + + ToDoubleFunc(ToDoubleFunction delegate) { + this.delegate = delegate; + } + + @Override + public double applyAsDouble(R value) { + if (!invoked) { + invoked = true; + } + return delegate.applyAsDouble(value); + } } } diff --git a/src/test/java/io/vertx/micrometer/impl/meters/GaugesTest.java b/src/test/java/io/vertx/micrometer/impl/meters/GaugesTest.java index 1558d160..863c0c96 100644 --- a/src/test/java/io/vertx/micrometer/impl/meters/GaugesTest.java +++ b/src/test/java/io/vertx/micrometer/impl/meters/GaugesTest.java @@ -1,6 +1,24 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.vertx.micrometer.impl.meters; import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; @@ -14,6 +32,8 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.LongAdder; import static org.assertj.core.api.Assertions.assertThat; @@ -25,6 +45,8 @@ public class GaugesTest { private static final EnumSet