9#if !THREADMAN_WITH_NLOHMANN_JSON
10#error "threadman/json.hpp requires THREADMAN_WITH_NLOHMANN_JSON to be enabled"
15#include <nlohmann/json.hpp>
48inline void to_json(nlohmann::json& j,
const ThreadSnapshot& s) {
52 {
"native_id", s.native_id},
54 {
"run_duration_ns", s.run_duration.count()},
56 {
"is_core", s.is_core},
58 if (s.pool_id.has_value()) {
59 j[
"pool_id"] = *s.pool_id;
62inline void from_json(
const nlohmann::json& j, ThreadSnapshot& s) {
63 j.at(
"id").get_to(s.id);
64 j.at(
"name").get_to(s.name);
65 j.at(
"native_id").get_to(s.native_id);
66 j.at(
"state").get_to(s.state);
68 j.at(
"run_duration_ns").get_to(ns);
69 s.run_duration = std::chrono::nanoseconds{ns};
70 j.at(
"failed").get_to(s.failed);
71 j.at(
"is_core").get_to(s.is_core);
72 if (j.contains(
"pool_id")) {
73 s.pool_id = j.at(
"pool_id").get<std::uint64_t>();
79inline void to_json(nlohmann::json& j,
const ThreadPoolStats& s) {
81 {
"pool_id", s.pool_id},
84 {
"workers", s.workers},
85 {
"core_workers", s.core_workers},
86 {
"max_workers", s.max_workers},
90 {
"completed", s.completed},
92 {
"avg_execution_duration_ns", s.avg_execution_duration.count()},
93 {
"scale_ups", s.scale_ups},
94 {
"scale_downs", s.scale_downs},
97inline void from_json(
const nlohmann::json& j, ThreadPoolStats& s) {
98 j.at(
"pool_id").get_to(s.pool_id);
99 j.at(
"name").get_to(s.name);
100 j.at(
"state").get_to(s.state);
101 j.at(
"workers").get_to(s.workers);
102 j.at(
"core_workers").get_to(s.core_workers);
103 j.at(
"max_workers").get_to(s.max_workers);
104 j.at(
"active").get_to(s.active);
105 j.at(
"idle").get_to(s.idle);
106 j.at(
"queued").get_to(s.queued);
107 j.at(
"completed").get_to(s.completed);
108 j.at(
"failed").get_to(s.failed);
110 j.at(
"avg_execution_duration_ns").get_to(ns);
111 s.avg_execution_duration = std::chrono::nanoseconds{ns};
112 j.at(
"scale_ups").get_to(s.scale_ups);
113 j.at(
"scale_downs").get_to(s.scale_downs);
118template <
class Clock>
119inline long long tp_to_ns(
const std::chrono::time_point<Clock>& tp) {
120 return std::chrono::duration_cast<std::chrono::nanoseconds>(tp.time_since_epoch()).count();
123template <
class Clock>
124inline std::chrono::time_point<Clock> ns_to_tp(
const long long ns) {
125 using TpDuration =
typename Clock::duration;
126 return std::chrono::time_point<Clock>{
127 std::chrono::duration_cast<TpDuration>(std::chrono::nanoseconds{ns})};
132inline void to_json(nlohmann::json& j,
const TaskSnapshot& s) {
135 {
"pool_id", s.pool_id},
137 {
"created_at_ns", detail::tp_to_ns(s.created_at)},
138 {
"failed", s.failed},
140 if (s.name.has_value()) {
143 if (s.started_at.has_value()) {
144 j[
"started_at_ns"] = detail::tp_to_ns(*s.started_at);
146 if (s.finished_at.has_value()) {
147 j[
"finished_at_ns"] = detail::tp_to_ns(*s.finished_at);
150inline void from_json(
const nlohmann::json& j, TaskSnapshot& s) {
151 j.at(
"id").get_to(s.id);
152 j.at(
"pool_id").get_to(s.pool_id);
153 j.at(
"state").get_to(s.state);
155 j.at(
"created_at_ns").get_to(ns);
156 s.created_at = detail::ns_to_tp<std::chrono::steady_clock>(ns);
157 j.at(
"failed").get_to(s.failed);
158 if (j.contains(
"name")) {
159 s.name = j.at(
"name").get<std::string>();
163 if (j.contains(
"started_at_ns")) {
165 detail::ns_to_tp<std::chrono::steady_clock>(j.at(
"started_at_ns").get<
long long>());
167 s.started_at.reset();
169 if (j.contains(
"finished_at_ns")) {
171 detail::ns_to_tp<std::chrono::steady_clock>(j.at(
"finished_at_ns").get<
long long>());
173 s.finished_at.reset();
177inline void to_json(nlohmann::json& j,
const FutureSnapshot& s) {
180 {
"has_exception", s.has_exception},
181 {
"continuation_count", s.continuation_count},
182 {
"shared", s.shared},
185inline void from_json(
const nlohmann::json& j, FutureSnapshot& s) {
186 j.at(
"ready").get_to(s.ready);
187 j.at(
"has_exception").get_to(s.has_exception);
188 j.at(
"continuation_count").get_to(s.continuation_count);
189 j.at(
"shared").get_to(s.shared);
192inline void to_json(nlohmann::json& j,
const ManagerSummary& s) {
194 {
"wall_clock_ns", detail::tp_to_ns(s.wall_clock)},
195 {
"live_threads", s.live_threads},
196 {
"total_pools", s.total_pools},
197 {
"total_live_workers", s.total_live_workers},
198 {
"total_queued", s.total_queued},
199 {
"total_completed", s.total_completed},
200 {
"total_failed", s.total_failed},
201 {
"per_pool_stats", s.per_pool_stats},
202 {
"stuck_tasks", s.stuck_tasks},
205inline void from_json(
const nlohmann::json& j, ManagerSummary& s) {
207 j.at(
"wall_clock_ns").get_to(ns);
208 s.wall_clock = detail::ns_to_tp<std::chrono::system_clock>(ns);
209 j.at(
"live_threads").get_to(s.live_threads);
210 j.at(
"total_pools").get_to(s.total_pools);
211 j.at(
"total_live_workers").get_to(s.total_live_workers);
212 j.at(
"total_queued").get_to(s.total_queued);
213 j.at(
"total_completed").get_to(s.total_completed);
214 j.at(
"total_failed").get_to(s.total_failed);
215 j.at(
"per_pool_stats").get_to(s.per_pool_stats);
216 j.at(
"stuck_tasks").get_to(s.stuck_tasks);
219inline void to_json(nlohmann::json& j,
const StuckTaskEvent& s) {
222 {
"running_for_ns", s.running_for.count()},
223 {
"pool_id", s.pool_id},
226inline void from_json(
const nlohmann::json& j, StuckTaskEvent& s) {
227 j.at(
"task").get_to(s.task);
229 j.at(
"running_for_ns").get_to(ns);
230 s.running_for = std::chrono::nanoseconds{ns};
231 j.at(
"pool_id").get_to(s.pool_id);
Central feature-gate header for ThreadMan's optional integrations and tunable defaults.
Definition exceptions.hpp:22
TaskState
Lifecycle state of a TaskHandle.
Definition stats.hpp:31
@ Completed
Body returned normally.
@ Running
Picked up by a worker; body executing.
@ Queued
Submitted, waiting for a worker.
@ Cancelled
Discarded before running (shutdown_now, etc.).
ThreadState
Lifecycle state of a ManagedThread / pool worker.
Definition stats.hpp:21
@ Completed
Body returned normally; thread joined or about to.
@ Retiring
Pool worker stop-requested; will exit on next loop check.
@ Running
User body is actively executing.
@ Starting
Constructed; user body not yet entered.
@ Failed
Body threw an exception; reason captured in ControlBlock.
@ Idle
Pool worker sleeping on the queue, no task.
NLOHMANN_JSON_SERIALIZE_ENUM(ThreadState, { {ThreadState::Starting, "starting"}, {ThreadState::Running, "running"}, {ThreadState::Idle, "idle"}, {ThreadState::Retiring, "retiring"}, {ThreadState::Completed, "completed"}, {ThreadState::Failed, "failed"}, }) NLOHMANN_JSON_SERIALIZE_ENUM(TaskState
PoolState
Lifecycle state of a ThreadPool.
Definition stats.hpp:40
@ ShuttingDown
shutdown() requested; draining queue, no new submits.
@ Running
Accepting submissions.
@ ShutdownNow
shutdown_now() requested; queue cancelled, workers stopping.
@ Terminated
All workers joined.
Plain value snapshots of the live state of the ThreadMan world — threads, pools, tasks,...