threadman 0.1.0
Header-only C++23 managed threads, dynamic pools, futures, and executors
Loading...
Searching...
No Matches
metrics.hpp
Go to the documentation of this file.
1#pragma once
2
22
23#include <prom/prom.hpp>
24
25#include <memory>
26
28
30inline std::shared_ptr<prom::Scope>& scope() {
31 static std::shared_ptr<prom::Scope> sc =
32 prom::scope("threadman", prom::ScopeConfig{.prefix = "tm_"});
33 return sc;
34}
35
36// ---------------------------------------------------------------------------
37// pool — `thread_pool.hpp`; series selected by the `pool` label (pool name).
38// ---------------------------------------------------------------------------
39
41inline prom::Counter& pool_tasks_submitted() {
42 static prom::Counter m =
43 scope()->counter({.name = "pool_tasks_submitted_total",
44 .help = "Tasks submitted to a thread pool (all submit variants)."});
45 return m;
46}
47
49inline prom::Counter& pool_tasks_completed() {
50 static prom::Counter m =
51 scope()->counter({.name = "pool_tasks_completed_total",
52 .help = "Tasks that ran to completion on a pool worker."});
53 return m;
54}
55
57inline prom::Counter& pool_tasks_failed() {
58 static prom::Counter m = scope()->counter(
59 {.name = "pool_tasks_failed_total", .help = "Tasks whose body threw an exception."});
60 return m;
61}
62
64inline prom::Counter& pool_tasks_cancelled() {
65 static prom::Counter m =
66 scope()->counter({.name = "pool_tasks_cancelled_total",
67 .help = "Tasks cancelled before running (drained by shutdown_now)."});
68 return m;
69}
70
72inline prom::Counter& pool_queue_rejected() {
73 static prom::Counter m =
74 scope()->counter({.name = "pool_queue_rejected_total",
75 .help = "Submissions rejected because a bounded queue was full."});
76 return m;
77}
78
80inline prom::Counter& pool_submit_rejected() {
81 static prom::Counter m = scope()->counter(
82 {.name = "pool_submit_rejected_total",
83 .help = "Submissions rejected because the pool was shutting down or terminated."});
84 return m;
85}
86
88inline prom::Counter& pool_scale_ups() {
89 static prom::Counter m = scope()->counter(
90 {.name = "pool_scale_ups_total", .help = "Non-core workers spawned by a scale-up."});
91 return m;
92}
93
95inline prom::Counter& pool_scale_downs() {
96 static prom::Counter m = scope()->counter(
97 {.name = "pool_scale_downs_total", .help = "Non-core workers retired after idling out."});
98 return m;
99}
100
102inline prom::Gauge& pool_queue_depth() {
103 static prom::Gauge m = scope()->gauge(
104 {.name = "pool_queue_depth", .help = "Tasks currently waiting in a pool's queue."});
105 return m;
106}
107
109inline prom::Gauge& pool_workers() {
110 static prom::Gauge m =
111 scope()->gauge({.name = "pool_workers", .help = "Live workers in a pool."});
112 return m;
113}
114
116inline prom::Gauge& pool_workers_active() {
117 static prom::Gauge m = scope()->gauge(
118 {.name = "pool_workers_active", .help = "Workers currently executing a task."});
119 return m;
120}
121
123inline prom::Gauge& pool_workers_idle() {
124 static prom::Gauge m = scope()->gauge(
125 {.name = "pool_workers_idle", .help = "Workers currently idle on the queue."});
126 return m;
127}
128
130inline prom::Histogram& pool_task_execution_seconds() {
131 static prom::Histogram m = scope()->histogram(
132 {.name = "pool_task_execution_seconds",
133 .help = "Wall-clock seconds a task body spent executing.",
134 .buckets = {0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0}});
135 return m;
136}
137
139inline prom::Histogram& pool_task_queue_wait_seconds() {
140 static prom::Histogram m = scope()->histogram(
141 {.name = "pool_task_queue_wait_seconds",
142 .help = "Seconds a task waited in the queue before a worker picked it up.",
143 .buckets = {0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0}});
144 return m;
145}
146
147// ---------------------------------------------------------------------------
148// thread — `thread.hpp`; no label.
149// ---------------------------------------------------------------------------
150
152inline prom::Counter& threads_created() {
153 static prom::Counter m = scope()->counter(
154 {.name = "threads_created_total", .help = "ManagedThread bodies that started running."});
155 return m;
156}
157
159inline prom::Counter& threads_completed() {
160 static prom::Counter m =
161 scope()->counter({.name = "threads_completed_total",
162 .help = "ManagedThread bodies that returned normally."});
163 return m;
164}
165
167inline prom::Counter& threads_failed() {
168 static prom::Counter m = scope()->counter(
169 {.name = "threads_failed_total", .help = "ManagedThread bodies that exited by throwing."});
170 return m;
171}
172
174inline prom::Gauge& threads_live() {
175 static prom::Gauge m =
176 scope()->gauge({.name = "threads_live", .help = "ManagedThread bodies currently running."});
177 return m;
178}
179
180// ---------------------------------------------------------------------------
181// manager — `manager.hpp`; no label.
182// ---------------------------------------------------------------------------
183
185inline prom::Counter& manager_threads_registered() {
186 static prom::Counter m =
187 scope()->counter({.name = "manager_threads_registered_total",
188 .help = "Thread control blocks registered with the manager."});
189 return m;
190}
191
193inline prom::Counter& manager_summaries_published() {
194 static prom::Counter m =
195 scope()->counter({.name = "manager_summaries_published_total",
196 .help = "Periodic ManagerSummary payloads published to listeners."});
197 return m;
198}
199
201inline prom::Gauge& manager_pools_live() {
202 static prom::Gauge m = scope()->gauge(
203 {.name = "manager_pools_live", .help = "Pools currently registered with the manager."});
204 return m;
205}
206
207// ---------------------------------------------------------------------------
208// task / stuck — `manager.hpp`; `tasks_stuck_detected_total` labelled `pool_id`.
209// ---------------------------------------------------------------------------
210
212inline prom::Counter& tasks_stuck_detected() {
213 static prom::Counter m = scope()->counter(
214 {.name = "tasks_stuck_detected_total",
215 .help = "Distinct tasks newly detected as stuck (running past the threshold)."});
216 return m;
217}
218
220inline prom::Gauge& tasks_stuck_current() {
221 static prom::Gauge m = scope()->gauge(
222 {.name = "tasks_stuck_current", .help = "Tasks currently flagged as stuck."});
223 return m;
224}
225
226// ---------------------------------------------------------------------------
227// future — `future.hpp`; no label.
228// ---------------------------------------------------------------------------
229
231inline prom::Counter& futures_created() {
232 static prom::Counter m = scope()->counter(
233 {.name = "futures_created_total", .help = "Promise/Future pairs created."});
234 return m;
235}
236
238inline prom::Counter& futures_satisfied_value() {
239 static prom::Counter m = scope()->counter(
240 {.name = "futures_satisfied_value_total", .help = "Futures satisfied with a value."});
241 return m;
242}
243
245inline prom::Counter& futures_satisfied_exception() {
246 static prom::Counter m = scope()->counter({.name = "futures_satisfied_exception_total",
247 .help = "Futures satisfied with an exception."});
248 return m;
249}
250
252inline prom::Counter& future_continuations_registered() {
253 static prom::Counter m = scope()->counter(
254 {.name = "future_continuations_registered_total",
255 .help = "Continuations registered against a future (.then / .on_error)."});
256 return m;
257}
258
260inline prom::Counter& future_continuations_dispatched() {
261 static prom::Counter m =
262 scope()->counter({.name = "future_continuations_dispatched_total",
263 .help = "Continuations dispatched through an executor."});
264 return m;
265}
266
278inline void warm_up() {
279 scope();
280 // Force each metric's lazy bind now (a discarded empty-label child binds the
281 // parent family without recording any value), so the first runtime `inc` /
282 // `observe` / `set` — some of which sit on latency-sensitive paths such as
283 // promise satisfaction — takes the fast path instead of paying a first-use
284 // bind. Counter::labels is [[nodiscard]]; cast away.
285 const prom::Labels none{};
286 auto bind_counter = [&](const prom::Counter& c) { (void)c.labels(none); };
287 auto bind_gauge = [&](const prom::Gauge& g) { (void)g.labels(none); };
288 auto bind_histogram = [&](const prom::Histogram& h) { (void)h.labels(none); };
289
290 bind_counter(pool_tasks_submitted());
291 bind_counter(pool_tasks_completed());
292 bind_counter(pool_tasks_failed());
293 bind_counter(pool_tasks_cancelled());
294 bind_counter(pool_queue_rejected());
295 bind_counter(pool_submit_rejected());
296 bind_counter(pool_scale_ups());
297 bind_counter(pool_scale_downs());
298 bind_gauge(pool_queue_depth());
299 bind_gauge(pool_workers());
300 bind_gauge(pool_workers_active());
301 bind_gauge(pool_workers_idle());
302 bind_histogram(pool_task_execution_seconds());
303 bind_histogram(pool_task_queue_wait_seconds());
304 bind_counter(threads_created());
305 bind_counter(threads_completed());
306 bind_counter(threads_failed());
307 bind_gauge(threads_live());
308 bind_counter(manager_threads_registered());
309 bind_counter(manager_summaries_published());
310 bind_gauge(manager_pools_live());
311 bind_counter(tasks_stuck_detected());
312 bind_gauge(tasks_stuck_current());
313 bind_counter(futures_created());
314 bind_counter(futures_satisfied_value());
315 bind_counter(futures_satisfied_exception());
316 bind_counter(future_continuations_registered());
317 bind_counter(future_continuations_dispatched());
318}
319
320} // namespace threadman::metrics
Definition metrics.hpp:27
prom::Counter & future_continuations_registered()
.then/.on_error continuations registered against a future.
Definition metrics.hpp:252
void warm_up()
Eagerly construct the scope and every metric handle (and, transitively, prom's process-wide adapter c...
Definition metrics.hpp:278
prom::Counter & threads_failed()
ManagedThread bodies that exited by throwing.
Definition metrics.hpp:167
prom::Gauge & threads_live()
ManagedThread bodies currently running (inc on enter, dec on exit).
Definition metrics.hpp:174
prom::Counter & tasks_stuck_detected()
Distinct tasks newly detected as stuck (running past the threshold).
Definition metrics.hpp:212
prom::Counter & pool_scale_downs()
Non-core workers retired after idling out.
Definition metrics.hpp:95
prom::Counter & manager_threads_registered()
Thread control blocks registered with the manager.
Definition metrics.hpp:185
prom::Counter & pool_tasks_cancelled()
Tasks cancelled before running (drained by shutdown_now).
Definition metrics.hpp:64
prom::Gauge & tasks_stuck_current()
Tasks currently flagged as stuck (set from the housekeeper tick).
Definition metrics.hpp:220
prom::Counter & pool_scale_ups()
Non-core workers spawned by a scale-up decision.
Definition metrics.hpp:88
prom::Counter & manager_summaries_published()
Periodic ManagerSummary payloads published to listeners.
Definition metrics.hpp:193
prom::Counter & pool_tasks_submitted()
Tasks submitted to a thread pool (all submit variants).
Definition metrics.hpp:41
prom::Histogram & pool_task_execution_seconds()
Wall-clock seconds a task body spent executing.
Definition metrics.hpp:130
prom::Counter & pool_submit_rejected()
Submissions rejected because the pool was shutting down or terminated.
Definition metrics.hpp:80
prom::Counter & threads_completed()
ManagedThread bodies that returned normally.
Definition metrics.hpp:159
prom::Counter & threads_created()
ManagedThread bodies that entered (started running).
Definition metrics.hpp:152
prom::Gauge & pool_queue_depth()
Tasks currently waiting in a pool's queue (set from the summary tick).
Definition metrics.hpp:102
std::shared_ptr< prom::Scope > & scope()
The shared threadman scope; applies the tm_ prefix to every metric.
Definition metrics.hpp:30
prom::Gauge & pool_workers()
Live workers in a pool (set from the summary tick).
Definition metrics.hpp:109
prom::Gauge & pool_workers_active()
Workers currently executing a task (set from the summary tick).
Definition metrics.hpp:116
prom::Gauge & pool_workers_idle()
Workers currently idle on the queue (set from the summary tick).
Definition metrics.hpp:123
prom::Gauge & manager_pools_live()
Pools currently registered with the manager (set from the summary tick).
Definition metrics.hpp:201
prom::Counter & futures_satisfied_value()
Futures satisfied with a value.
Definition metrics.hpp:238
prom::Counter & pool_tasks_completed()
Tasks that ran to completion on a pool worker.
Definition metrics.hpp:49
prom::Histogram & pool_task_queue_wait_seconds()
Seconds a task waited in the queue before a worker picked it up.
Definition metrics.hpp:139
prom::Counter & future_continuations_dispatched()
Continuations dispatched through an executor.
Definition metrics.hpp:260
prom::Counter & futures_satisfied_exception()
Futures satisfied with an exception.
Definition metrics.hpp:245
prom::Counter & pool_tasks_failed()
Tasks whose body threw an exception.
Definition metrics.hpp:57
prom::Counter & futures_created()
Promise/Future pairs created.
Definition metrics.hpp:231
prom::Counter & pool_queue_rejected()
Submissions rejected because a bounded queue was full.
Definition metrics.hpp:72