./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
14 / 14
100.0%
Branches:
14 / 14
100.0%
Functions:
1 / 1
100.0%

include/DetourModKit/async_logger_config.hpp
Line Branch Exec Source
1 #ifndef DETOURMODKIT_ASYNC_LOGGER_CONFIG_HPP
2 #define DETOURMODKIT_ASYNC_LOGGER_CONFIG_HPP
3
4 /**
5 * @file async_logger_config.hpp
6 * @brief Async-logger configuration types and their defaults.
7 */
8
9 #include <chrono>
10 #include <cstddef>
11 #include <cstdint>
12 #include <string>
13 #include <string_view>
14
15 namespace DetourModKit
16 {
17 /// Default strftime-style timestamp format for the async sink.
18 inline constexpr std::string_view DEFAULT_ASYNC_TIMESTAMP_FORMAT{"%Y-%m-%d %H:%M:%S"};
19 /// Default capacity, in slots, of the bounded MPMC record queue.
20 inline constexpr std::size_t DEFAULT_QUEUE_CAPACITY = 8192;
21 /// Default number of records that the writer drains per write batch.
22 inline constexpr std::size_t DEFAULT_BATCH_SIZE = 64;
23 /// Default interval between periodic writer flushes.
24 inline constexpr auto DEFAULT_FLUSH_INTERVAL = std::chrono::milliseconds(100);
25 /// Default spin-backoff iteration count before a producer yields or parks.
26 inline constexpr std::size_t DEFAULT_SPIN_BACKOFF_ITERATIONS = 32;
27
28 /**
29 * @brief Defines the action of a producer when the bounded queue is full.
30 * @warning On a callback path, use only DropNewest. On that path, keep each record within
31 * @ref LOG_INLINE_MESSAGE_SIZE. Each other policy has the hazard that its enumerator states.
32 * @note The policies differ in acceptance and in producer cost at the overflow step. DropNewest alone never waits
33 * or locks there.
34 */
35 enum class OverflowPolicy : std::uint8_t
36 {
37 /// Drops the new record without a wait.
38 DropNewest,
39 /** @brief Evicts the oldest record with no queue wait. Eviction of a long record takes the string-pool lock. */
40 DropOldest,
41 /// Parks the producer until space frees or block_timeout_ms elapses.
42 Block,
43 /** @brief Writes the record on the producer thread under the sink lock and performs I/O. */
44 SyncFallback
45 };
46
47 /**
48 * @brief Configuration for the async logger.
49 * @details Each queue slot embeds a LOG_INLINE_MESSAGE_SIZE inline buffer, so the default queue uses a few MiB.
50 * A longer record uses a bounded overflow string pool, or the heap once the pool is full or the record
51 * exceeds the pool's record size. For a small memory budget, shrink queue_capacity.
52 */
53 struct AsyncLoggerConfig
54 {
55 std::size_t queue_capacity = DEFAULT_QUEUE_CAPACITY;
56 /// Number of records that the writer drains per write batch. The writer clamps it to @ref queue_capacity.
57 std::size_t batch_size = DEFAULT_BATCH_SIZE;
58 std::chrono::milliseconds flush_interval = DEFAULT_FLUSH_INTERVAL;
59 OverflowPolicy overflow_policy = OverflowPolicy::DropOldest;
60 std::size_t spin_backoff_iterations = DEFAULT_SPIN_BACKOFF_ITERATIONS;
61 std::chrono::milliseconds block_timeout_ms{16};
62 std::size_t block_max_spin_iterations{1000};
63 /**
64 * @brief strftime-style timestamp format of the async sink. Empty selects @ref DEFAULT_ASYNC_TIMESTAMP_FORMAT.
65 * @details The empty default does not allocate. Logger::enable_async_mode ignores this field.
66 */
67 std::string timestamp_format{};
68
69 /** @brief Returns true if queue_capacity is a power of two above 1 and each duration or count is positive. */
70 1874 [[nodiscard]] constexpr bool validate() const noexcept
71 {
72
4/4
✓ Branch 2 → 3 taken 1872 times.
✓ Branch 2 → 4 taken 2 times.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1871 times.
1874 if (queue_capacity < 2 || (queue_capacity & (queue_capacity - 1)) != 0)
73 3 return false;
74
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 1870 times.
1871 if (batch_size == 0)
75 1 return false;
76
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 1868 times.
1870 if (flush_interval.count() <= 0)
77 2 return false;
78
2/2
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 1867 times.
1868 if (spin_backoff_iterations == 0)
79 1 return false;
80
2/2
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 15 taken 1865 times.
1867 if (block_timeout_ms.count() <= 0)
81 2 return false;
82
2/2
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 17 taken 1864 times.
1865 if (block_max_spin_iterations == 0)
83 1 return false;
84 1864 return true;
85 }
86 };
87
88 static_assert(
89 DEFAULT_QUEUE_CAPACITY >= 2 && (DEFAULT_QUEUE_CAPACITY & (DEFAULT_QUEUE_CAPACITY - 1)) == 0,
90 "DEFAULT_QUEUE_CAPACITY must be a power of 2 and at least 2"
91 );
92
93 } // namespace DetourModKit
94
95 #endif // DETOURMODKIT_ASYNC_LOGGER_CONFIG_HPP
96