Thread System 0.3.1
High-performance C++20 thread pool with work stealing and DAG scheduling
Loading...
Searching...
No Matches
execution_event.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
12#pragma once
13
14#include <chrono>
15#include <cstdint>
16#include <functional>
17#include <iomanip>
18#include <memory>
19#include <optional>
20#include <sstream>
21#include <string>
22#include <thread>
23
25{
35 enum class event_type
36 {
37 enqueued,
38 dequeued,
39 started,
40 completed,
41 failed,
42 cancelled,
43 retried
44 };
45
51 [[nodiscard]] inline auto event_type_to_string(event_type type) -> std::string
52 {
53 switch (type)
54 {
55 case event_type::enqueued: return "enqueued";
56 case event_type::dequeued: return "dequeued";
57 case event_type::started: return "started";
58 case event_type::completed: return "completed";
59 case event_type::failed: return "failed";
60 case event_type::cancelled: return "cancelled";
61 case event_type::retried: return "retried";
62 default: return "unknown";
63 }
64 }
65
98 {
104 std::uint64_t event_id{0};
105
109 std::uint64_t job_id{0};
110
114 std::string job_name;
115
120
124 std::chrono::steady_clock::time_point timestamp;
125
131 std::chrono::system_clock::time_point system_timestamp;
132
138 std::thread::id thread_id;
139
143 std::size_t worker_id{0};
144
145 // =========================================================================
146 // Timing Information
147 // =========================================================================
148
154 std::chrono::nanoseconds wait_time{0};
155
161 std::chrono::nanoseconds execution_time{0};
162
163 // =========================================================================
164 // Error Information
165 // =========================================================================
166
170 std::optional<int> error_code;
171
175 std::optional<std::string> error_message;
176
177 // =========================================================================
178 // Utility Methods
179 // =========================================================================
180
185 [[nodiscard]] auto format_timestamp() const -> std::string
186 {
187 auto time_t = std::chrono::system_clock::to_time_t(system_timestamp);
188 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
189 system_timestamp.time_since_epoch()) % 1000;
190
191 char buffer[32];
192 std::strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S",
193 std::gmtime(&time_t));
194
195 return std::string(buffer) + "." +
196 std::to_string(ms.count()) + "Z";
197 }
198
203 [[nodiscard]] auto wait_time_ms() const -> double
204 {
205 return std::chrono::duration<double, std::milli>(wait_time).count();
206 }
207
212 [[nodiscard]] auto execution_time_ms() const -> double
213 {
214 return std::chrono::duration<double, std::milli>(execution_time).count();
215 }
216
221 [[nodiscard]] auto is_terminal() const -> bool
222 {
223 return type == event_type::completed ||
226 }
227
232 [[nodiscard]] auto is_error() const -> bool
233 {
234 return type == event_type::failed ||
236 }
237
259 [[nodiscard]] auto to_json() const -> std::string
260 {
261 std::ostringstream oss;
262 oss << "{\n";
263 oss << " \"event_id\": " << event_id << ",\n";
264 oss << " \"job_id\": " << job_id << ",\n";
265 oss << " \"job_name\": \"" << job_name << "\",\n";
266 oss << " \"type\": \"" << event_type_to_string(type) << "\",\n";
267 oss << " \"timestamp\": \"" << format_timestamp() << "\",\n";
268
269 // Format thread_id as string
270 std::ostringstream tid_oss;
271 tid_oss << thread_id;
272 oss << " \"thread_id\": \"" << tid_oss.str() << "\",\n";
273
274 oss << " \"worker_id\": " << worker_id << ",\n";
275 oss << std::fixed << std::setprecision(3);
276 oss << " \"wait_time_ms\": " << wait_time_ms() << ",\n";
277 oss << " \"execution_time_ms\": " << execution_time_ms();
278
279 if (error_code.has_value())
280 {
281 oss << ",\n \"error_code\": " << error_code.value();
282 }
283 else
284 {
285 oss << ",\n \"error_code\": null";
286 }
287
288 if (error_message.has_value())
289 {
290 oss << ",\n \"error_message\": \"" << error_message.value() << "\"";
291 }
292 else
293 {
294 oss << ",\n \"error_message\": null";
295 }
296
297 oss << "\n}";
298 return oss.str();
299 }
300
311 [[nodiscard]] auto to_string() const -> std::string
312 {
313 std::ostringstream oss;
314
315 // First line: timestamp, event info, job info, type
316 oss << "[" << format_timestamp() << "] ";
317 oss << "Event#" << event_id << " ";
318 oss << "job:" << job_name << "#" << job_id << " ";
319 oss << "type:" << event_type_to_string(type) << "\n";
320
321 // Second line: worker, thread, timing
322 oss << " worker:" << worker_id << " ";
323 oss << "thread:" << thread_id << " ";
324 oss << std::fixed << std::setprecision(3);
325 oss << "wait:" << wait_time_ms() << "ms ";
326 oss << "exec:" << execution_time_ms() << "ms";
327
328 // Error info if present
329 if (error_code.has_value() || error_message.has_value())
330 {
331 oss << "\n error:";
332 if (error_code.has_value())
333 {
334 oss << " code=" << error_code.value();
335 }
336 if (error_message.has_value())
337 {
338 oss << " msg=\"" << error_message.value() << "\"";
339 }
340 }
341
342 return oss.str();
343 }
344 };
345
378 {
379 public:
383 virtual ~execution_event_listener() = default;
384
393 virtual void on_event(const job_execution_event& event) = 0;
394 };
395
396} // namespace kcenon::thread::diagnostics
Interface for receiving job execution events.
virtual void on_event(const job_execution_event &event)=0
Called when a job execution event occurs.
virtual ~execution_event_listener()=default
Virtual destructor.
event_type
Type of job execution event.
@ dequeued
Job was taken from queue by a worker.
@ failed
Job failed with an error.
@ retried
Job is being retried after failure.
@ completed
Job completed successfully.
@ enqueued
Job was added to the queue.
auto event_type_to_string(event_type type) -> std::string
Converts event_type to human-readable string.
error_code
Strongly typed error codes for thread system operations.
std::uint64_t job_id
Unique job identifier for DAG scheduler.
Definition dag_job.h:33
STL namespace.
Event data for job execution tracing.
std::string job_name
Human-readable name of the job.
std::chrono::nanoseconds wait_time
Time spent waiting in queue before dequeue.
std::optional< std::string > error_message
Error message if the job failed.
std::chrono::nanoseconds execution_time
Time spent executing the job.
std::uint64_t event_id
Unique identifier for this event.
event_type type
Type of event that occurred.
auto wait_time_ms() const -> double
Converts wait_time to milliseconds.
std::optional< int > error_code
Error code if the job failed.
auto is_error() const -> bool
Checks if this event indicates an error.
auto execution_time_ms() const -> double
Converts execution_time to milliseconds.
auto to_string() const -> std::string
Converts the event to a human-readable string.
std::size_t worker_id
Worker ID that processed this job.
auto is_terminal() const -> bool
Checks if this is a terminal event (job finished).
auto to_json() const -> std::string
Converts the event to a JSON string.
auto format_timestamp() const -> std::string
Formats the event timestamp as ISO 8601 string.
std::thread::id thread_id
ID of the thread that processed this event.
std::chrono::system_clock::time_point system_timestamp
System time when the event occurred.
std::chrono::steady_clock::time_point timestamp
Time when the event occurred.