Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
batch_writer.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
7#include <algorithm>
8
9namespace kcenon::logger {
10
12 const config& cfg)
13 : base_type(std::move(underlying_writer), cfg.max_batch_size, "batch")
14 , config_(cfg)
15 , last_flush_time_(std::chrono::steady_clock::now()) {
16
17 // Reserve space for batch to avoid reallocations
19}
20
22 shutting_down_ = true;
23
24 // Flush any remaining entries with proper error handling
25 if (!queue_.empty()) {
26 utils::safe_destructor_result_operation("final_batch_flush", [this]() {
27 return flush();
28 });
29 }
30}
31
33
34 if (shutting_down_) {
35 return make_logger_void_result(logger_error_code::queue_stopped, "Batch writer is shutting down");
36 }
37
38 bool should_flush = false;
39
40 {
41 std::lock_guard<std::mutex> lock(queue_mutex_);
42
43 // Add entry to batch using shared helper
44 queue_.push_back(copy_log_entry(entry));
46
47 // Check if we should flush
48 should_flush = should_flush_by_size();
49 if (should_flush) {
51 }
52 }
53
54 // Flush outside of lock to avoid blocking other writers
55 if (should_flush) {
56 return flush();
57 }
58
59 return common::ok();
60}
61
63 if (shutting_down_ && queue_.empty()) {
64 return common::ok();
65 }
66
67 std::lock_guard<std::mutex> lock(queue_mutex_);
68
69 if (!shutting_down_) {
71 }
72
73 return flush_batch_unsafe();
74}
75
77 if (queue_.empty()) {
78 return common::ok();
79 }
80
81 // Write all entries in the batch
82 common::VoidResult last_result = common::ok();
83
84 for (const auto& entry : queue_) {
85 auto result = wrapped().write(entry);
86
87 if (result.is_err()) {
88 last_result = result;
90 }
91 }
92
93 // Flush the underlying writer
94 auto flush_result = wrapped().flush();
95 if (flush_result.is_err() && last_result.is_ok()) {
96 last_result = flush_result;
97 }
98
99 // Update statistics
101
102 // Clear the batch
103 queue_.clear();
104 last_flush_time_ = std::chrono::steady_clock::now();
105
106 // Return the last error if any
107 return last_result;
108}
109
110std::string batch_writer::get_name() const {
111 return "batch_writer[" + wrapped().get_name() + "]";
112}
113
115 return !shutting_down_ && wrapped().is_healthy();
116}
117
119 std::lock_guard<std::mutex> lock(queue_mutex_);
120 return queue_.size();
121}
122
131
133 return queue_.size() >= config_.max_batch_size;
134}
135
137 auto now = std::chrono::steady_clock::now();
138 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
139 now - last_flush_time_
140 );
141 return elapsed >= config_.flush_interval;
142}
143
144// Factory function implementation
145std::unique_ptr<batch_writer> make_batch_writer(
146 log_writer_ptr writer,
147 size_t batch_size,
148 std::chrono::milliseconds flush_interval) {
149
151 cfg.max_batch_size = batch_size;
152 cfg.flush_interval = flush_interval;
153
154 return std::make_unique<batch_writer>(std::move(writer), cfg);
155}
156
157} // namespace kcenon::logger
Batch writer that accumulates log entries and writes them in batches.
~batch_writer() override
Destructor - ensures all pending entries are flushed.
void reset_stats()
Reset batch statistics.
common::VoidResult flush_batch_unsafe()
Flush batch without locking (caller must hold lock)
batch_writer(log_writer_ptr underlying_writer, const config &cfg=config{})
Construct a batch writer.
bool is_healthy() const override
Check if writer is healthy.
std::chrono::steady_clock::time_point last_flush_time_
common::VoidResult flush() override
Flush the batch to the underlying writer.
std::string get_name() const override
Get writer name.
bool should_flush_by_size() const
Check if batch should be flushed based on size.
size_t get_current_batch_size() const
Get current batch size.
common::VoidResult write(const log_entry &entry) override
Write a log entry to the batch.
bool should_flush_by_time() const
Check if batch should be flushed based on time.
log_writer_interface & wrapped() noexcept
Access the wrapped writer (non-const)
virtual std::string get_name() const =0
virtual bool is_healthy() const =0
Check if the writer is healthy.
virtual common::VoidResult flush()=0
Flush any buffered data.
virtual common::VoidResult write(const log_entry &entry)=0
Write a log entry.
Structured error context for debugging log system failures.
VoidResult ok()
void safe_destructor_result_operation(const std::string &operation_name, F &&operation) noexcept
Safe operation with result for destructors.
common::VoidResult make_logger_void_result(logger_error_code code, const std::string &message="")
std::unique_ptr< batch_writer > make_batch_writer(log_writer_ptr writer, size_t batch_size=100, std::chrono::milliseconds flush_interval=std::chrono::milliseconds{1000})
Factory function to create a batch writer.
log_entry copy_log_entry(const log_entry &entry)
Creates a copy of a log_entry for queue storage.
std::unique_ptr< log_writer_interface > log_writer_ptr
Type alias for writer unique pointer.
Configuration for batch writer.
std::chrono::milliseconds flush_interval
Represents a single log entry with all associated metadata.
Definition log_entry.h:155