diff --git a/build.gradle b/build.gradle index b5b734bb5..71d6bf6c2 100644 --- a/build.gradle +++ b/build.gradle @@ -94,6 +94,7 @@ dependencies { implementation 'com.coveo:spillway:3.0.0' // monitoring + implementation 'io.micronaut.micrometer:micronaut-micrometer-core' implementation 'io.micronaut.micrometer:micronaut-micrometer-registry-prometheus' // Also required to enable endpoint implementation 'io.micronaut:micronaut-management' @@ -157,7 +158,7 @@ jib { run{ def envs = findProperty('micronautEnvs') - def args = ["-Dmicronaut.environments=$envs","-Djdk.tracePinnedThreads=short"] + def args = ["-Dmicronaut.environments=$envs","-Djdk.tracePinnedThreads=short", "--add-opens","java.base/java.lang=ALL-UNNAMED"] if( environment['JVM_OPTS'] ) args.add(environment['JVM_OPTS']) jvmArgs args systemProperties 'DOCKER_USER': project.findProperty('DOCKER_USER') ?: environment['DOCKER_USER'], diff --git a/gradle.properties b/gradle.properties index 9c2c3bcbb..a89e1b2a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,4 @@ # micronautVersion=4.7.1 -micronautEnvs=dev,h2,mail,aws-ses +micronautEnvs=dev,h2,mail,aws-ses,prometheus diff --git a/src/main/groovy/io/seqera/wave/metrics/ExecutorsMetricsBinder.groovy b/src/main/groovy/io/seqera/wave/metrics/ExecutorsMetricsBinder.groovy new file mode 100644 index 000000000..746c328ec --- /dev/null +++ b/src/main/groovy/io/seqera/wave/metrics/ExecutorsMetricsBinder.groovy @@ -0,0 +1,82 @@ +/* + * Wave, containers provisioning service + * Copyright (c) 2023-2024, Seqera Labs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.seqera.wave.metrics + +import java.lang.reflect.Field +import java.util.concurrent.ForkJoinPool + +import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j +import io.micrometer.core.instrument.MeterRegistry +import io.micronaut.context.annotation.Context +import jakarta.annotation.PostConstruct +import jakarta.inject.Inject +/** + * + * @author Paolo Di Tommaso + */ +@Slf4j +@Context +@CompileStatic +class ExecutorsMetricsBinder { + + @Inject + private MeterRegistry registry + + @PostConstruct + void register() { + log.info "+ Registering executor metrics binder" + registerCommonPoolMetrics(registry) + registerVirtualThreadPoolMetrics(registry) + } + + void registerCommonPoolMetrics(MeterRegistry meterRegistry) { + ForkJoinPool commonPool = ForkJoinPool.commonPool(); + + meterRegistry.gauge("common.pool.size", commonPool, ForkJoinPool::getPoolSize); + meterRegistry.gauge("common.active.thread.count", commonPool, ForkJoinPool::getActiveThreadCount); + meterRegistry.gauge("common.queued.submissions", commonPool, ForkJoinPool::getQueuedSubmissionCount); + meterRegistry.gauge("common.queued.tasks", commonPool, ForkJoinPool::getQueuedTaskCount); + meterRegistry.gauge("common.parallelism", commonPool, ForkJoinPool::getParallelism); + meterRegistry.gauge("common.steal.count", commonPool, ForkJoinPool::getStealCount); + } + + void registerVirtualThreadPoolMetrics(MeterRegistry meterRegistry) { + try { + // Create a virtual thread executor + Class VirtualThread = Class.forName("java.lang.VirtualThread"); + + // Use reflection to get the internal ForkJoinPool + Field poolField = VirtualThread.getDeclaredField("DEFAULT_SCHEDULER"); + poolField.setAccessible(true); + ForkJoinPool virtualThreadPool = (ForkJoinPool) poolField.get(null); + + // Register metrics for the virtual thread pool + meterRegistry.gauge("virtual.pool.size", virtualThreadPool, ForkJoinPool::getPoolSize); + meterRegistry.gauge("virtual.active.thread.count", virtualThreadPool, ForkJoinPool::getActiveThreadCount); + meterRegistry.gauge("virtual.queued.submissions", virtualThreadPool, ForkJoinPool::getQueuedSubmissionCount); + meterRegistry.gauge("virtual.queued.tasks", virtualThreadPool, ForkJoinPool::getQueuedTaskCount); + meterRegistry.gauge("virtual.parallelism", virtualThreadPool, ForkJoinPool::getParallelism); + meterRegistry.gauge("virtual.steal.count", virtualThreadPool, ForkJoinPool::getStealCount); + } + catch (Exception e) { + log.error "Unable to registry carrier threads pool metrics", e + } + } +}