Skip to content

Differences between monitoring ThreadPoolExecutor and ForkJoinPool #7089

@jonatan-ivanov

Description

@jonatan-ivanov

While I was reviewing #7083, I saw that if I use ExecutorServiceMetrics.monitor for a ThreadPoolExecutor (Executors.newFixedThreadPool) and a ForkJoinPool I get a few unexpected differences in the outputs.

executor.active and executor.queued have units (threads and tasks) for ThreadPoolExecutor while for ForkJoinPool they do not, this means that changing this:

- ExecutorServiceMetrics.monitor(registry, Executors.newFixedThreadPool(2), name, tags);
+ ExecutorServiceMetrics.monitor(registry, new ForkJoinPool(2), name, tags);

will result in different time series (executor_active_threads vs. executor_active) in the Prometheus output:

- executor_active_threads{name="test"} 0.0
+ executor_active{name="test"} 0.0
- executor_queued_tasks{name="test"} 0.0
+ executor_queued{name="test"} 0.0

(Fixing this is a breaking change.)

Click to reveal demo code
public class Demo {
    public static void main(String[] args) {
        generateAndPrintMetricsFor(Executors.newFixedThreadPool(2));
        generateAndPrintMetricsFor(new ForkJoinPool(2));
    }

    private static void generateAndPrintMetricsFor(ExecutorService executorServiceToMonitor) {
        PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
        ExecutorService executorService = ExecutorServiceMetrics.monitor(registry, executorServiceToMonitor, "test", Tags.empty());
        List<Future<?>> futures = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            futures.add(executorService.submit(Demo::sleep));
        }
        for (Future<?> future : futures) {
            try {
                future.get(1_000, TimeUnit.MILLISECONDS);
            }
            catch (Exception e) {
                System.out.println(e.getMessage());
            }
            finally {
                future.cancel(true);
            }
        }

        System.out.println("===== Metrics for " + executorService.getClass().getSimpleName());
        System.out.println(registry.scrape());
        executorService.shutdown();
    }

    private static void sleep() {
        try {
            Thread.sleep(100);
        }
        catch (InterruptedException e) {
            // noop
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementA general enhancementhelp wantedAn issue that a contributor can help us with

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions