Skip to content

Commit 183ce92

Browse files
committed
add a hidden /tasks actuator endpoint (for async)
1 parent b7e1025 commit 183ce92

3 files changed

Lines changed: 39 additions & 4 deletions

File tree

src/main/kotlin/ch/derlin/bbdata/AsyncConfig.kt

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package ch.derlin.bbdata
22

3+
import io.swagger.v3.oas.annotations.Hidden
4+
import io.swagger.v3.oas.annotations.Operation
35
import org.slf4j.Logger
46
import org.slf4j.LoggerFactory
57
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
68
import org.springframework.beans.factory.annotation.Value
9+
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation
10+
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint
711
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
812
import org.springframework.boot.task.TaskExecutorCustomizer
913
import org.springframework.context.annotation.Configuration
14+
import org.springframework.core.task.TaskExecutor
1015
import org.springframework.scheduling.annotation.AsyncConfigurer
1116
import org.springframework.scheduling.annotation.EnableAsync
1217
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
@@ -45,7 +50,7 @@ class AsyncExecutorCustomizer : TaskExecutorCustomizer {
4550
}
4651
}
4752

48-
@ConditionalOnProperty("async.enabled", havingValue = "true", matchIfMissing = true)
53+
@ConditionalOnProperty(AsyncProperties.ENABLED, havingValue = "true", matchIfMissing = true)
4954
@EnableAsync
5055
@Configuration
5156
class AsyncConfig : AsyncConfigurer {
@@ -66,4 +71,29 @@ class AsyncExceptionHandler : AsyncUncaughtExceptionHandler {
6671
val niceParams = params.take(2).joinToString(",") { it.toString() }
6772
logger.error("in ${method.name} with ${params.size} params: $niceParams ...", throwable)
6873
}
74+
}
75+
76+
@Component
77+
@ConditionalOnProperty(AsyncProperties.ENABLED, havingValue = "true", matchIfMissing = true)
78+
@WebEndpoint(id = "tasks")
79+
class AsyncMonitor(private val taskExecutor: TaskExecutor? = null) {
80+
/** add an optional tasks actuator to monitor async executor (hidden) */
81+
82+
@ReadOperation
83+
@Operation(description = "Actuator web endpoint 'tasks', monitor async tasks execution")
84+
@Hidden
85+
fun executorInfo(): Map<String, Any> {
86+
// use linkedMap to preserve insertion order in output
87+
val executorInfo = linkedMapOf<String, Any>()
88+
val tasksInfo = linkedMapOf<String, Any>()
89+
if (taskExecutor is ThreadPoolTaskExecutor)
90+
taskExecutor.threadPoolExecutor.let {
91+
executorInfo["pool-size"] = it.corePoolSize
92+
executorInfo["active-count"] = it.activeCount
93+
executorInfo["queue-size"] = it.queue.size
94+
tasksInfo["task-count"] = it.taskCount
95+
tasksInfo["completed-task-count"] = it.completedTaskCount
96+
}
97+
return linkedMapOf("executor" to executorInfo, "tasks" to tasksInfo)
98+
}
6999
}

src/main/kotlin/ch/derlin/bbdata/CustomProperties.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class ScanExcludeProperties {
3535
class AsyncProperties {
3636
/** Whether or not to turn async on: see AsyncConfig */
3737
var enabled: Boolean = true
38+
39+
companion object {
40+
const val ENABLED = "async.enabled"
41+
}
3842
}
3943

4044
@Configuration

src/main/resources/application.properties

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,22 @@ spring.task.execution.pool.allow-core-thread-timeout=false
8787
## Input/Output
8888
# make json the default
8989
spring.data.rest.defaultMediaType=application/json
90-
# pretty print output
90+
# pretty print output + keep map order
9191
spring.jackson.serialization.indent-output=true
92+
spring.jackson.serialization.order-map-entries-by-keys=true
9293
# dates (declared here only for swagger)
9394
spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss
9495
# Pageable configuration
9596
spring.data.web.pageable.max-page-size=1000000
9697
spring.data.web.pageable.default-page-size=1000000
9798

9899
## Actuator (config)
99-
management.endpoints.web.exposure.include=info, health
100+
management.endpoints.web.exposure.include=info, health, metrics, tasks
100101
management.endpoint.health.show-components=always
101102
#management.server.port=8888
102103
management.endpoints.web.base-path=/
103104

104-
## Documentation
105+
## Documentation
105106
# Paths: UI at /docs/api, yaml at /docs/api/bbdata{.yaml}
106107
springdoc.swagger-ui.path=/docs/api
107108
springdoc.api-docs.path=/docs/api/bbdata

0 commit comments

Comments
 (0)