package io.vertx.ext.dropwizard.impl;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.SharedMetricRegistries;
import io.vertx.core.Handler;
import io.vertx.core.VertxOptions;
import io.vertx.core.datagram.DatagramSocketOptions;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.NetClientOptions;
import io.vertx.core.net.NetServerOptions;
import io.vertx.core.net.SocketAddress;
import io.vertx.core.spi.metrics.*;
import io.vertx.core.spi.metrics.ClientMetrics;
import io.vertx.ext.dropwizard.DropwizardMetricsOptions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
class VertxMetricsImpl extends AbstractMetrics implements VertxMetrics {
private final DropwizardMetricsOptions options;
private Handler<Void> doneHandler;
private final boolean shutdown;
private final Map<String, HttpClientReporter> clientReporters = new ConcurrentHashMap<>();
private final Map<String, DropwizardClientMetrics> clientMetrics = new HashMap<>();
VertxMetricsImpl(MetricRegistry registry, boolean shutdown, VertxOptions options, DropwizardMetricsOptions metricsOptions, String baseName) {
super(registry, baseName);
this.options = metricsOptions;
this.shutdown = shutdown;
gauge(options::getEventLoopPoolSize, "event-loop-size");
gauge(options::getWorkerPoolSize, "worker-pool-size");
}
DropwizardMetricsOptions getOptions() {
return options;
}
@Override
String projectName(String name) {
return name;
}
@Override
public EventBusMetrics createEventBusMetrics() {
return new EventBusMetricsImpl(this, nameOf("eventbus"), options);
}
@Override
public HttpServerMetrics<?, ?, ?> createHttpServerMetrics(HttpServerOptions options, SocketAddress localAddress) {
String baseName = MetricRegistry.name(nameOf("http.servers"), TCPMetricsImpl.addressName(localAddress));
return new HttpServerMetricsImpl(registry, baseName, this.options.getMonitoredHttpServerUris(), localAddress);
}
@Override
public synchronized ClientMetrics<?, ?, ?, ?> createClientMetrics(SocketAddress remoteAddress, String type, String namespace) {
String baseName;
if (namespace != null && namespace.length() > 0) {
baseName = MetricRegistry.name(nameOf(type, "clients", namespace, remoteAddress.toString()));
} else {
baseName = MetricRegistry.name(nameOf(type, "clients", remoteAddress.toString()));
}
return clientMetrics.compute(baseName, (key, prev) -> {
if (prev == null) {
return new DropwizardClientMetrics<>(this, registry, baseName, 1);
} else {
return prev.inc();
}
});
}
@Override
public HttpClientMetrics<?, ?, ?, ?> createHttpClientMetrics(HttpClientOptions options) {
String name = options.getMetricsName();
String baseName;
if (name != null && name.length() > 0) {
baseName = nameOf("http.clients", name);
} else {
baseName = nameOf("http.clients");
}
HttpClientReporter reporter = clientReporters.computeIfAbsent(baseName, n -> new HttpClientReporter(registry, baseName, null));
return new HttpClientMetricsImpl(this, reporter, options, this.options.getMonitoredHttpClientUris(), this.options.getMonitoredHttpClientEndpoint());
}
synchronized void closed(HttpClientMetricsImpl metrics) {
HttpClientReporter reporter = metrics.clientReporter;
if (reporter.decMaxPoolSize(metrics.maxPoolSize)) {
clientReporters.remove(reporter.baseName);
reporter.close();
}
}
synchronized void closed(DropwizardClientMetrics metrics) {
clientMetrics.compute(metrics.baseName, (key, prev) -> {
DropwizardClientMetrics instance = prev.dec();
if (instance.count == 0) {
instance.removeAll();
return null;
} else {
return instance;
}
});
}
@Override
public TCPMetrics<?> createNetServerMetrics(NetServerOptions options, SocketAddress localAddress) {
String baseName = MetricRegistry.name(nameOf("net.servers"), TCPMetricsImpl.addressName(localAddress));
return new TCPMetricsImpl(registry, baseName);
}
@Override
public TCPMetrics<?> createNetClientMetrics(NetClientOptions options) {
String baseName;
if (options.getMetricsName() != null) {
baseName = nameOf("net.clients", options.getMetricsName());
} else {
baseName = nameOf("net.clients");
}
return new TCPMetricsImpl(registry, baseName);
}
@Override
public DatagramSocketMetrics createDatagramSocketMetrics(DatagramSocketOptions options) {
return new DatagramSocketMetricsImpl(this, nameOf("datagram"));
}
@Override
public PoolMetrics<?> createPoolMetrics(String poolType, String poolName, int maxPoolSize) {
String baseName = nameOf("pools", poolType, poolName);
return new PoolMetricsImpl(registry, baseName, maxPoolSize);
}
@Override
public void close() {
if (shutdown) {
RegistryHelper.shutdown(registry);
if (options.getRegistryName() != null) {
SharedMetricRegistries.remove(options.getRegistryName());
}
}
List<HttpClientReporter> reporters;
synchronized (this) {
reporters = new ArrayList<>(clientReporters.values());
}
for (HttpClientReporter reporter : reporters) {
reporter.close();
}
if (doneHandler != null) {
doneHandler.handle(null);
}
}
@Override
public boolean isMetricsEnabled() {
return true;
}
void setDoneHandler(Handler<Void> handler) {
this.doneHandler = handler;
}
}