diff --git a/build.gradle.kts b/build.gradle.kts index 5a75b9d..067035c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ repositories { // maven { url = uri("https://repo.spring.io/milestone") } // D4J snapshots } -val prometheusVersion = "0.16.0" +val prometheusVersion = "1.1.0" val dsProxyVersion = "1.9" val jdaVersion = "5.0.0-beta.18" val troveVersion = "3.0.3" @@ -45,7 +45,7 @@ val mockitoVersion = "5.8.0" val assertJVersion = "3.24.2" dependencies { - api("io.prometheus:simpleclient:$prometheusVersion") + api("io.prometheus:prometheus-metrics-core:$prometheusVersion") compileOnly("net.ttddyy:datasource-proxy:$dsProxyVersion") diff --git a/src/main/java/space/npstr/prometheus_extensions/DiscordMetrics.java b/src/main/java/space/npstr/prometheus_extensions/DiscordMetrics.java index dd0229d..b7add98 100644 --- a/src/main/java/space/npstr/prometheus_extensions/DiscordMetrics.java +++ b/src/main/java/space/npstr/prometheus_extensions/DiscordMetrics.java @@ -24,11 +24,11 @@ package space.npstr.prometheus_extensions; -import io.prometheus.client.CollectorRegistry; -import io.prometheus.client.Counter; -import io.prometheus.client.Gauge; -import io.prometheus.client.Histogram; -import io.prometheus.client.Summary; +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.core.metrics.Gauge; +import io.prometheus.metrics.core.metrics.Histogram; +import io.prometheus.metrics.core.metrics.Summary; +import io.prometheus.metrics.model.registry.PrometheusRegistry; public class DiscordMetrics { @@ -47,65 +47,65 @@ public class DiscordMetrics { private final Histogram discordRestRequestResponseTime; private final Counter discordRestHardFailures; - public DiscordMetrics(final CollectorRegistry registry) { - this.voiceChannelsConnected = Gauge.build() + public DiscordMetrics(final PrometheusRegistry registry) { + this.voiceChannelsConnected = Gauge.builder() .name("discord_voicechannels_connected_current") .help("How many voice channel is the bot connected to") .register(registry); - this.discordEntities = Gauge.build() + this.discordEntities = Gauge.builder() .name("discord_entities_current") .help("How many entities are present") .labelNames("type") .register(registry); - this.unavailableGuilds = Gauge.build() + this.unavailableGuilds = Gauge.builder() .name("discord_unavailable_guilds_current") .help("How many guilds are unavailable") .labelNames("shard") .register(registry); - this.sessionStartLimitTotal = Gauge.build() + this.sessionStartLimitTotal = Gauge.builder() .name("discord_session_start_limit_total") .help("Maximum session start limit") .register(registry); - this.sessionStartLimitRemaining = Gauge.build() + this.sessionStartLimitRemaining = Gauge.builder() .name("discord_session_start_limit_remaining") .help("Remaining session starts") .register(registry); - this.recommendedShardCount = Gauge.build() + this.recommendedShardCount = Gauge.builder() .name("discord_recommended_shard_count") .help("Recommended shard count") .register(registry); - this.events = Counter.build() + this.events = Counter.builder() .name("discord_events_received_total") .help("All received events by class") .labelNames("class") .register(registry); - this.closeCodes = Counter.build() + this.closeCodes = Counter.builder() .name("discord_websocket_close_codes_total") .help("Close codes of the main websocket connections") .labelNames("code") .register(registry); - this.discordRestRequests = Summary.build() + this.discordRestRequests = Summary.builder() .name("discord_rest_request_seconds") .help("Total Discord REST requests sent and their received responses") .labelNames("method", "uri", "status", "error") .register(registry); - this.discordRestRequestResponseTime = Histogram.build() + this.discordRestRequestResponseTime = Histogram.builder() .name("discord_rest_request_response_time_seconds") - .exponentialBuckets(0.05, 1.2, 20) + .classicExponentialUpperBounds(0.05, 1.2, 20) // TODO use new native histograms when support becomes stable .help("Discord REST request response time") .register(registry); - this.discordRestHardFailures = Counter.build() + this.discordRestHardFailures = Counter.builder() .name("discord_rest_request_hard_failures_total") .help("Total Discord REST requests that experienced hard failures (not client response exceptions)") .labelNames("method", "uri") diff --git a/src/main/java/space/npstr/prometheus_extensions/OkHttpEventCounter.java b/src/main/java/space/npstr/prometheus_extensions/OkHttpEventCounter.java index 89b17bc..b262252 100644 --- a/src/main/java/space/npstr/prometheus_extensions/OkHttpEventCounter.java +++ b/src/main/java/space/npstr/prometheus_extensions/OkHttpEventCounter.java @@ -24,7 +24,7 @@ package space.npstr.prometheus_extensions; -import io.prometheus.client.Counter; +import io.prometheus.metrics.core.metrics.Counter; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -41,7 +41,7 @@ public class OkHttpEventCounter extends EventListener { - private static final Counter httpEventCounter = Counter.build() + private static final Counter httpEventCounter = Counter.builder() .name("okhttp_events_total") .help("Total okhttp events") .labelNames("instance", "event") @@ -58,102 +58,102 @@ public OkHttpEventCounter(final String instanceLabel) { @Override public void callStart(final @NonNull Call call) { - httpEventCounter.labels(this.instanceLabel, "callStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "callStart").inc(); } @Override public void dnsStart(@NonNull final Call call, @NonNull final String domainName) { - httpEventCounter.labels(this.instanceLabel, "dnsStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "dnsStart").inc(); } @Override public void dnsEnd(@NonNull final Call call, @NonNull final String domainName, @NonNull final List inetAddressList) { - httpEventCounter.labels(this.instanceLabel, "dnsEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "dnsEnd").inc(); } @Override public void connectStart(@NonNull final Call call, @NonNull final InetSocketAddress inetSocketAddress, @NonNull final Proxy proxy) { - httpEventCounter.labels(this.instanceLabel, "connectStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "connectStart").inc(); } @Override public void secureConnectStart(@NonNull final Call call) { - httpEventCounter.labels(this.instanceLabel, "secureConnectStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "secureConnectStart").inc(); } @Override public void secureConnectEnd(@NonNull final Call call, final Handshake handshake) { - httpEventCounter.labels(this.instanceLabel, "secureConnectEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "secureConnectEnd").inc(); } @Override public void connectEnd(@NonNull final Call call, @NonNull final InetSocketAddress inetSocketAddress, @NonNull final Proxy proxy, final Protocol protocol) { - httpEventCounter.labels(this.instanceLabel, "connectEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "connectEnd").inc(); } @Override public void connectFailed(@NonNull final Call call, @NonNull final InetSocketAddress inetSocketAddress, @NonNull final Proxy proxy, final Protocol protocol, @NonNull final IOException ioe) { - httpEventCounter.labels(this.instanceLabel, "connectFailed").inc(); + httpEventCounter.labelValues(this.instanceLabel, "connectFailed").inc(); } @Override public void connectionAcquired(@NonNull final Call call, @NonNull final Connection connection) { - httpEventCounter.labels(this.instanceLabel, "connectionAcquired").inc(); + httpEventCounter.labelValues(this.instanceLabel, "connectionAcquired").inc(); } @Override public void connectionReleased(@NonNull final Call call, @NonNull final Connection connection) { - httpEventCounter.labels(this.instanceLabel, "connectionReleased").inc(); + httpEventCounter.labelValues(this.instanceLabel, "connectionReleased").inc(); } @Override public void requestHeadersStart(@NonNull final Call call) { - httpEventCounter.labels(this.instanceLabel, "requestHeadersStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "requestHeadersStart").inc(); } @Override public void requestHeadersEnd(@NonNull final Call call, @NonNull final Request request) { - httpEventCounter.labels(this.instanceLabel, "requestHeadersEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "requestHeadersEnd").inc(); } @Override public void requestBodyStart(@NonNull final Call call) { - httpEventCounter.labels(this.instanceLabel, "requestBodyStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "requestBodyStart").inc(); } @Override public void requestBodyEnd(@NonNull final Call call, final long byteCount) { - httpEventCounter.labels(this.instanceLabel, "requestBodyEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "requestBodyEnd").inc(); } @Override public void responseHeadersStart(@NonNull final Call call) { - httpEventCounter.labels(this.instanceLabel, "responseHeadersStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "responseHeadersStart").inc(); } @Override public void responseHeadersEnd(@NonNull final Call call, @NonNull final Response response) { - httpEventCounter.labels(this.instanceLabel, "responseHeadersEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "responseHeadersEnd").inc(); } @Override public void responseBodyStart(@NonNull final Call call) { - httpEventCounter.labels(this.instanceLabel, "responseBodyStart").inc(); + httpEventCounter.labelValues(this.instanceLabel, "responseBodyStart").inc(); } @Override public void responseBodyEnd(@NonNull final Call call, final long byteCount) { - httpEventCounter.labels(this.instanceLabel, "responseBodyEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "responseBodyEnd").inc(); } @Override public void callEnd(@NonNull final Call call) { - httpEventCounter.labels(this.instanceLabel, "callEnd").inc(); + httpEventCounter.labelValues(this.instanceLabel, "callEnd").inc(); } @Override public void callFailed(@NonNull final Call call, @NonNull final IOException ioe) { - httpEventCounter.labels(this.instanceLabel, "callFailed").inc(); + httpEventCounter.labelValues(this.instanceLabel, "callFailed").inc(); } } diff --git a/src/main/java/space/npstr/prometheus_extensions/QueryCountCollector.java b/src/main/java/space/npstr/prometheus_extensions/QueryCountCollector.java index 18fb664..8791e17 100644 --- a/src/main/java/space/npstr/prometheus_extensions/QueryCountCollector.java +++ b/src/main/java/space/npstr/prometheus_extensions/QueryCountCollector.java @@ -24,102 +24,110 @@ package space.npstr.prometheus_extensions; -import io.prometheus.client.Collector; -import io.prometheus.client.CounterMetricFamily; -import java.util.ArrayList; -import java.util.List; +import io.prometheus.metrics.core.metrics.CounterWithCallback; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Unit; +import java.util.function.Function; import net.ttddyy.dsproxy.QueryCount; import net.ttddyy.dsproxy.listener.SingleQueryCountHolder; -public class QueryCountCollector extends Collector { +public class QueryCountCollector { + + private static final double MILLIS_PER_SECOND = 1000.0; private final SingleQueryCountHolder queryCountHolder; - public QueryCountCollector(SingleQueryCountHolder queryCountHolder) { + public QueryCountCollector(SingleQueryCountHolder queryCountHolder, PrometheusRegistry registry) { this.queryCountHolder = queryCountHolder; + String[] labelNames = {"datasource"}; + + CounterWithCallback.builder() + .name("jdbc_query_select_total") + .help("Total select queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getSelect)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_query_insert_total") + .help("Total insert queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getInsert)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_query_update_total") + .help("Total update queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getUpdate)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_query_delete_total") + .help("Total delete queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getDelete)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_query_other_total") + .help("Total other queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getOther)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_query_total") + .help("Total queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getTotal)) + .register(registry); + + CounterWithCallback.builder() + .name("jdbc_statement_total") + .help("Total statements") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getStatement)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_prepared_total") + .help("Total prepared statements") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getPrepared)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_callable_total") + .help("Total callable statements") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getCallable)) + .register(registry); + + CounterWithCallback.builder() + .name("jdbc_success_total") + .help("Total successful queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getSuccess)) + .register(registry); + CounterWithCallback.builder() + .name("jdbc_failure_total") + .help("Total failed queries") + .labelNames(labelNames) + .callback(callback -> collect(callback, QueryCount::getFailure)) + .register(registry); + + CounterWithCallback.builder() + .name("jdbc_time_total") + .help("Total query execution time in seconds") + .unit(Unit.SECONDS) + .labelNames(labelNames) + .callback(callback -> collect(callback, qc -> qc.getTime() / MILLIS_PER_SECOND)) + .register(registry); } - @Override - public List collect() { - - List mfs = new ArrayList<>(); - List labelNames = List.of("datasource"); - - CounterMetricFamily select = new CounterMetricFamily("jdbc_query_select_total", - "Total select queries", labelNames - ); - mfs.add(select); - CounterMetricFamily insert = new CounterMetricFamily("jdbc_query_insert_total", - "Total insert queries", labelNames - ); - mfs.add(insert); - CounterMetricFamily update = new CounterMetricFamily("jdbc_query_update_total", - "Total update queries", labelNames - ); - mfs.add(update); - CounterMetricFamily delete = new CounterMetricFamily("jdbc_query_delete_total", - "Total delete queries", labelNames - ); - mfs.add(delete); - CounterMetricFamily other = new CounterMetricFamily("jdbc_query_other_total", - "Total other queries", labelNames - ); - mfs.add(other); - CounterMetricFamily total = new CounterMetricFamily("jdbc_query_total", - "Total queries", labelNames - ); - mfs.add(total); - - CounterMetricFamily statement = new CounterMetricFamily("jdbc_statement_total", - "Total statements", labelNames - ); - mfs.add(statement); - CounterMetricFamily prepared = new CounterMetricFamily("jdbc_prepared_total", - "Total prepared statements", labelNames - ); - mfs.add(prepared); - CounterMetricFamily callable = new CounterMetricFamily("jdbc_callable_total", - "Total callable statements", labelNames - ); - mfs.add(callable); - - CounterMetricFamily success = new CounterMetricFamily("jdbc_success_total", - "Total successful queries", labelNames - ); - mfs.add(success); - CounterMetricFamily failure = new CounterMetricFamily("jdbc_failure_total", - "Total failed queries", labelNames - ); - mfs.add(failure); - - CounterMetricFamily time = new CounterMetricFamily("jdbc_time_total", - "Total query execution time in seconds", labelNames - ); - mfs.add(time); - + private void collect(CounterWithCallback.Callback callback, Function counter) { for (var entry : this.queryCountHolder.getQueryCountMap().entrySet()) { String datasourceName = entry.getKey(); QueryCount queryCount = entry.getValue(); - List labels = List.of(datasourceName); - - select.addMetric(labels, queryCount.getSelect()); - insert.addMetric(labels, queryCount.getInsert()); - update.addMetric(labels, queryCount.getUpdate()); - delete.addMetric(labels, queryCount.getDelete()); - other.addMetric(labels, queryCount.getOther()); - total.addMetric(labels, queryCount.getTotal()); - statement.addMetric(labels, queryCount.getStatement()); - prepared.addMetric(labels, queryCount.getPrepared()); - callable.addMetric(labels, queryCount.getCallable()); + double value = counter.apply(queryCount).doubleValue(); - success.addMetric(labels, queryCount.getSuccess()); - failure.addMetric(labels, queryCount.getFailure()); - - time.addMetric(labels, queryCount.getTime() / MILLISECONDS_PER_SECOND); + callback.call(value, datasourceName); } - - return mfs; } } diff --git a/src/main/java/space/npstr/prometheus_extensions/ThreadPoolCollector.java b/src/main/java/space/npstr/prometheus_extensions/ThreadPoolCollector.java index 3081f91..301c6d0 100644 --- a/src/main/java/space/npstr/prometheus_extensions/ThreadPoolCollector.java +++ b/src/main/java/space/npstr/prometheus_extensions/ThreadPoolCollector.java @@ -24,18 +24,16 @@ package space.npstr.prometheus_extensions; -import io.prometheus.client.Collector; -import io.prometheus.client.CounterMetricFamily; -import io.prometheus.client.GaugeMetricFamily; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import io.prometheus.metrics.core.metrics.CounterWithCallback; +import io.prometheus.metrics.core.metrics.GaugeWithCallback; +import io.prometheus.metrics.model.registry.PrometheusRegistry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ThreadPoolExecutor; +import java.util.function.BiConsumer; +import java.util.function.Function; -public class ThreadPoolCollector extends Collector { +public class ThreadPoolCollector { protected final ConcurrentMap pools = new ConcurrentHashMap<>(); @@ -71,38 +69,39 @@ public void clear() { this.pools.clear(); } + public ThreadPoolCollector(PrometheusRegistry registry) { + String[] labelNames = {"name"}; + + GaugeWithCallback.builder() + .name("threadpool_active_threads_current") + .help("Amount of active threads in a thread pool") + .labelNames(labelNames) + .callback(callback -> collect(callback::call, ThreadPoolExecutor::getActiveCount)) + .register(registry); + + GaugeWithCallback.builder() + .name("threadpool_queue_size_current") + .help("Size of queue of a thread pool (including scheduled tasks)") + .labelNames(labelNames) + .callback(callback -> collect(callback::call, pool -> pool.getQueue().size())) + .register(registry); + + CounterWithCallback.builder() + .name("threadpool_completed_tasks_total") + .help("Total completed tasks by a thread pool") + .labelNames(labelNames) + .callback(callback -> collect(callback::call, ThreadPoolExecutor::getCompletedTaskCount)) + .register(registry); + } - @Override - public List collect() { - - List mfs = new ArrayList<>(); - List labelNames = Collections.singletonList("name"); - - GaugeMetricFamily activeThreads = new GaugeMetricFamily("threadpool_active_threads_current", - "Amount of active threads in a thread pool", labelNames - ); - mfs.add(activeThreads); - - GaugeMetricFamily queueSize = new GaugeMetricFamily("threadpool_queue_size_current", - "Size of queue of a thread pool (including scheduled tasks)", labelNames - ); - mfs.add(queueSize); - - CounterMetricFamily completedTasks = new CounterMetricFamily("threadpool_completed_tasks_total", - "Total completed tasks by a thread pool", labelNames - ); - mfs.add(completedTasks); - - for (Map.Entry entry : this.pools.entrySet()) { + private void collect(BiConsumer callback, Function counter) { + for (var entry : this.pools.entrySet()) { String poolName = entry.getKey(); + String[] labels = {poolName}; ThreadPoolExecutor pool = entry.getValue(); - List labels = Collections.singletonList(poolName); + double value = counter.apply(pool).doubleValue(); - activeThreads.addMetric(labels, pool.getActiveCount()); - queueSize.addMetric(labels, pool.getQueue().size()); - completedTasks.addMetric(labels, pool.getCompletedTaskCount()); //guaranteed to always increase, ergo good fit for a counter + callback.accept(value, labels); } - - return mfs; } } diff --git a/src/main/java/space/npstr/prometheus_extensions/d4j/D4JMetrics.java b/src/main/java/space/npstr/prometheus_extensions/d4j/D4JMetrics.java index 530aae0..dbbcbb8 100644 --- a/src/main/java/space/npstr/prometheus_extensions/d4j/D4JMetrics.java +++ b/src/main/java/space/npstr/prometheus_extensions/d4j/D4JMetrics.java @@ -111,7 +111,7 @@ private void instrumentUnavailableGuilds(Duration interval) { for (Map.Entry> entry : unavailableGuilds.entrySet()) { int shardId = entry.getKey(); Set guildIds = entry.getValue(); - this.discordMetrics.getUnavailableGuilds().labels(Integer.toString(shardId)).set(guildIds.size()); + this.discordMetrics.getUnavailableGuilds().labelValues(Integer.toString(shardId)).set(guildIds.size()); } }) .doOnError(t -> log.warn("Failed to instrument unavailable guilds", t)) @@ -172,7 +172,7 @@ private void instrumentEntity(Duration interval, CountTotalAction action, String } private void doInstrument(long count, String label) { - this.discordMetrics.getDiscordEntities().labels(label).set(count); + this.discordMetrics.getDiscordEntities().labelValues(label).set(count); } private Mono logEntityCountError(Throwable throwable, String label) { @@ -193,7 +193,7 @@ private long countShards() { private void instrumentEvents() { this.gatewayDiscordClient.getEventDispatcher() .on(Event.class) - .doOnNext(event -> this.discordMetrics.getEvents().labels(event.getClass().getSimpleName()).inc()) + .doOnNext(event -> this.discordMetrics.getEvents().labelValues(event.getClass().getSimpleName()).inc()) .doOnError(t -> log.warn("Failed to track event", t)) .retry() .subscribe(); @@ -210,7 +210,7 @@ private void instrumentCloseCodes() { private void instrumentCloseCode(final DisconnectEvent event) { int code = event.getStatus().getCode(); - this.discordMetrics.getCloseCodes().labels(Integer.toString(code)).inc(); + this.discordMetrics.getCloseCodes().labelValues(Integer.toString(code)).inc(); log.info("Shard {} websocket closed with {} {}", formatShard(event.getShardInfo()), code, event.getStatus().getReason().orElse("No reason"), diff --git a/src/main/java/space/npstr/prometheus_extensions/d4j/InstrumentedRouter.java b/src/main/java/space/npstr/prometheus_extensions/d4j/InstrumentedRouter.java index 8caefee..c0eb595 100644 --- a/src/main/java/space/npstr/prometheus_extensions/d4j/InstrumentedRouter.java +++ b/src/main/java/space/npstr/prometheus_extensions/d4j/InstrumentedRouter.java @@ -35,7 +35,6 @@ import discord4j.rest.request.RouterOptions; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; -import io.prometheus.client.Collector; import java.time.Duration; import java.time.Instant; import java.util.Map; @@ -52,6 +51,7 @@ public class InstrumentedRouter implements Router { private static final Logger log = LoggerFactory.getLogger(InstrumentedRouter.class); + private static final double MILLIS_PER_SECOND = 1000.0; private final DiscordMetrics discordMetrics; private final Router delegate; @@ -81,11 +81,11 @@ private void instrumentNext(ClientResponse response, DiscordWebRequest request) ContextView contextView = response.getHttpResponse().currentContextView(); Instant requestStarted = Instant.ofEpochMilli(contextView.get(DiscordWebClient.KEY_REQUEST_TIMESTAMP)); long responseTimeMillis = Duration.between(requestStarted, Instant.now()).toMillis(); - double responseTimeSeconds = responseTimeMillis / Collector.MILLISECONDS_PER_SECOND; + double responseTimeSeconds = responseTimeMillis / MILLIS_PER_SECOND; log.trace("{} {} {}ms {}", method, uriTemplate, responseTimeMillis, status.code()); this.discordMetrics.getDiscordRestRequests() - .labels(method.name(), uriTemplate, Integer.toString(status.code()), "") + .labelValues(method.name(), uriTemplate, Integer.toString(status.code()), "") .observe(responseTimeSeconds); this.discordMetrics.getDiscordRestRequestResponseTime() .observe(responseTimeSeconds); @@ -104,11 +104,11 @@ private void instrumentError(Throwable throwable, DiscordWebRequest request) { ContextView contextView = error.getResponse().currentContextView(); Instant requestStarted = Instant.ofEpochMilli(contextView.get(DiscordWebClient.KEY_REQUEST_TIMESTAMP)); long responseTimeMillis = Duration.between(requestStarted, Instant.now()).toMillis(); - double responseTimeSeconds = responseTimeMillis / Collector.MILLISECONDS_PER_SECOND; + double responseTimeSeconds = responseTimeMillis / MILLIS_PER_SECOND; log.trace("{} {} {}ms {} {} {}", method, uriTemplate, responseTimeMillis, status.code(), errorCode, errorMessage); this.discordMetrics.getDiscordRestRequests() - .labels(method.name(), uriTemplate, Integer.toString(status.code()), Integer.toString(errorCode)) + .labelValues(method.name(), uriTemplate, Integer.toString(status.code()), Integer.toString(errorCode)) .observe(responseTimeSeconds); this.discordMetrics.getDiscordRestRequestResponseTime() .observe(responseTimeSeconds); @@ -120,7 +120,7 @@ private void instrumentError(Throwable throwable, DiscordWebRequest request) { } else { log.warn("Failed request to {} {}", method, uriTemplate, throwable); this.discordMetrics.getDiscordRestHardFailures() - .labels(method.name(), uriTemplate) + .labelValues(method.name(), uriTemplate) .inc(); } } diff --git a/src/main/java/space/npstr/prometheus_extensions/jda/JdaMetrics.java b/src/main/java/space/npstr/prometheus_extensions/jda/JdaMetrics.java index b80ee5f..3bab252 100644 --- a/src/main/java/space/npstr/prometheus_extensions/jda/JdaMetrics.java +++ b/src/main/java/space/npstr/prometheus_extensions/jda/JdaMetrics.java @@ -24,8 +24,9 @@ package space.npstr.prometheus_extensions.jda; -import io.prometheus.client.CollectorRegistry; -import io.prometheus.client.Gauge; +import io.prometheus.metrics.core.metrics.Gauge; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; import java.time.Duration; import java.util.Objects; import java.util.concurrent.ScheduledExecutorService; @@ -56,8 +57,8 @@ public class JdaMetrics { private final Gauge distinctUsers; - public JdaMetrics(final ShardManager shardManager, final ScheduledExecutorService scheduler) { - this(shardManager, scheduler, CollectorRegistry.defaultRegistry); + public JdaMetrics(ShardManager shardManager, ScheduledExecutorService scheduler) { + this(shardManager, scheduler, PrometheusRegistry.defaultRegistry); } /** @@ -66,8 +67,8 @@ public JdaMetrics(final ShardManager shardManager, final ScheduledExecutorServic * those calculations shall be run on the passed in executor */ public JdaMetrics( - final ShardManager shardManager, final ScheduledExecutorService scheduler, - final CollectorRegistry registry + ShardManager shardManager, ScheduledExecutorService scheduler, + PrometheusRegistry registry ) { this.shardManager = shardManager; this.metricsScheduler = new MetricsScheduler(scheduler, shardManager); @@ -76,7 +77,7 @@ public JdaMetrics( final var metricsEventListener = new PrometheusMetricsEventListener(registry, discordMetrics); this.shardManager.addEventListener(metricsEventListener); - this.distinctUsers = Gauge.build() + this.distinctUsers = Gauge.builder() .name("jda_distinct_users_current") .help("Total distinct users") .register(registry); @@ -86,7 +87,12 @@ public JdaMetrics( } public int getDistinctUsers() { - return ((Double) this.distinctUsers.get()).intValue(); + GaugeSnapshot.GaugeDataPointSnapshot datapoint = this.distinctUsers.collect().getDataPoints().stream() + .findFirst().orElse(null); + if (datapoint == null) { + return 0; + } + return (int) datapoint.getValue(); } private void registerMetricsJobs() { @@ -142,35 +148,35 @@ private void countConnectedVoiceChannels() { } private void countEntities() { - this.discordMetrics.getDiscordEntities().labels("Category") + this.discordMetrics.getDiscordEntities().labelValues("Category") .set(countShardEntities(JDA::getCategoryCache)); - this.discordMetrics.getDiscordEntities().labels("Guild") + this.discordMetrics.getDiscordEntities().labelValues("Guild") .set(countShardEntities(JDA::getGuildCache)); - this.discordMetrics.getDiscordEntities().labels("PrivateChannel") + this.discordMetrics.getDiscordEntities().labelValues("PrivateChannel") .set(countShardEntities(JDA::getPrivateChannelCache)); - this.discordMetrics.getDiscordEntities().labels("TextChannel") + this.discordMetrics.getDiscordEntities().labelValues("TextChannel") .set(countShardEntities(JDA::getTextChannelCache)); - this.discordMetrics.getDiscordEntities().labels("User") + this.discordMetrics.getDiscordEntities().labelValues("User") .set(countShardEntities(JDA::getUserCache)); - this.discordMetrics.getDiscordEntities().labels("VoiceChannel") + this.discordMetrics.getDiscordEntities().labelValues("VoiceChannel") .set(countShardEntities(JDA::getVoiceChannelCache)); - this.discordMetrics.getDiscordEntities().labels("Emote") + this.discordMetrics.getDiscordEntities().labelValues("Emote") .set(countGuildEntities(Guild::getEmojiCache)); - this.discordMetrics.getDiscordEntities().labels("Role") + this.discordMetrics.getDiscordEntities().labelValues("Role") .set(countGuildEntities(Guild::getRoleCache)); countUnavailableGuilds(this.discordMetrics.getUnavailableGuilds()); } - private long countShardEntities(final Function> toCacheView) { + private long countShardEntities(Function> toCacheView) { return this.shardManager.getShards().stream() .map(toCacheView) .mapToLong(CacheView::size) .sum(); } - private long countGuildEntities(final Function> toCacheView) { + private long countGuildEntities(Function> toCacheView) { return this.shardManager.getShards().stream() .map(JDA::getGuildCache) .flatMap(CacheView::stream) @@ -183,7 +189,7 @@ private void countUnavailableGuilds(Gauge unavailableGuilds) { for (JDA jda : this.shardManager.getShards()) { int shardId = jda.getShardInfo().getShardId(); int size = jda.getUnavailableGuilds().size(); - unavailableGuilds.labels(Integer.toString(shardId)).set(size); + unavailableGuilds.labelValues(Integer.toString(shardId)).set(size); } } } diff --git a/src/main/java/space/npstr/prometheus_extensions/jda/PrometheusMetricsEventListener.java b/src/main/java/space/npstr/prometheus_extensions/jda/PrometheusMetricsEventListener.java index cc2871f..17161ee 100644 --- a/src/main/java/space/npstr/prometheus_extensions/jda/PrometheusMetricsEventListener.java +++ b/src/main/java/space/npstr/prometheus_extensions/jda/PrometheusMetricsEventListener.java @@ -24,8 +24,8 @@ package space.npstr.prometheus_extensions.jda; -import io.prometheus.client.CollectorRegistry; -import io.prometheus.client.Counter; +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.model.registry.PrometheusRegistry; import java.util.Optional; import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.http.HttpRequestEvent; @@ -50,9 +50,9 @@ class PrometheusMetricsEventListener extends ListenerAdapter { private final DiscordMetrics discordMetrics; private final Counter httpRequests; - PrometheusMetricsEventListener(final CollectorRegistry registry, DiscordMetrics discordMetrics) { + PrometheusMetricsEventListener(PrometheusRegistry registry, DiscordMetrics discordMetrics) { this.discordMetrics = discordMetrics; - this.httpRequests = Counter.build() + this.httpRequests = Counter.builder() .name("jda_restactions_total") .help("JDA restactions and their HTTP responses") .labelNames("status", "route") @@ -60,8 +60,8 @@ class PrometheusMetricsEventListener extends ListenerAdapter { } @Override - public void onGenericEvent(final GenericEvent event) { - this.discordMetrics.getEvents().labels(event.getClass().getSimpleName()).inc(); + public void onGenericEvent(GenericEvent event) { + this.discordMetrics.getEvents().labelValues(event.getClass().getSimpleName()).inc(); } @Override @@ -78,7 +78,7 @@ public void onSessionDisconnect(SessionDisconnectEvent event) { .findAny() .orElse("null"); - this.discordMetrics.getCloseCodes().labels(code).inc(); + this.discordMetrics.getCloseCodes().labelValues(code).inc(); } @Override @@ -93,7 +93,7 @@ public void onHttpRequest(final HttpRequestEvent event) { final String routeName = this.routeNamer.lookUpRouteName(route); - this.httpRequests.labels(code, routeName).inc(); + this.httpRequests.labelValues(code, routeName).inc(); }