kagkarlsson / db-scheduler

Persistent cluster-friendly scheduler for Java
Apache License 2.0
1.25k stars 191 forks source link

Feature: ExecutorService metrics for spring-boot-starter #548

Open s-volkov-1 opened 3 weeks ago

s-volkov-1 commented 3 weeks ago

Prerequisites

Proposal

I am using db-scheduler-spring-boot-starter. It would be great if default ExecutorService (i.e. workers thread pool) could automatically be attached to micrometer metrics for executors.

Example metrics, which are automatically registered for two default spring's thread pools (for @Async and @Scheduled):

executor_active_threads{name="applicationTaskExecutor"} 1.0
executor_active_threads{name="taskScheduler"} 0.0
executor_pool_size_threads{name="applicationTaskExecutor"} 8.0
executor_pool_size_threads{name="taskScheduler"} 2.0

These executors are exposed as beans and connected to MeterRegistry in TaskExecutorMetricsAutoConfiguration.

So scheduler's ExecutorService could be added as well:

executor_active_threads{name="dbScheduler"} 3.0
executor_pool_size_threads{name="dbScheduler"} 10.0

Workaround

One could take spring's executor (e.g. applicationTaskExecutor) and use it as db-scheduler worker ExecutorService via DbSchedulerCustomizer.executorService()

Thoughts

It seems like ExecutorService was intentionally not exposed as a bean, which possibly prevents it from being registered by TaskExecutorMetricsAutoConfiguration.

Bonus idea: metric returning overdue task count by names

Motivation

With ExecutorService's metrics users could monitor scheduler's load

Context

Involved classes:

  1. SchedulerBuilder
  2. DbSchedulerCustomizer
  3. DbSchedulerMetricsAutoConfiguration
  4. TaskExecutorMetricsAutoConfiguration (spring boot)
s-volkov-1 commented 1 week ago

What I did as a workaround:

@Configuration(proxyBeanMethods = false)
class DbSchedulerConfig(
    private val applicationTaskExecutor: ThreadPoolTaskExecutor
) {
    @Bean
    fun dbSchedulerCustomizer(): DbSchedulerCustomizer = object : DbSchedulerCustomizer {
        // this is needed to register executor service metrics for db-scheduler
        override fun executorService(): Optional<ExecutorService> {
            return Optional.of(applicationTaskExecutor.threadPoolExecutor)
        }
    }
}

application.yml

spring:
  task:
    execution: # ! used as db-scheduler pool !
      pool:
        core-size: 9
        max-size: 9
        allow-core-thread-timeout: false
      thread-name-prefix: task-executor-
      shutdown:
        await-termination: true
        await-termination-period: PT4M # just in case, same as db-scheduler.shutdown-max-wait

db-scheduler:
  # removed thread number setting
  immediate-execution-enabled: true
  shutdown-max-wait: 240s # 4 minutes

And can see executor's load now: image