Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
kcenon::logger::batch_writer Class Reference

Batch writer that accumulates log entries and writes them in batches. More...

#include <batch_writer.h>

Inheritance diagram for kcenon::logger::batch_writer:
Inheritance graph
Collaboration diagram for kcenon::logger::batch_writer:
Collaboration graph

Classes

struct  batch_stats
 Get batch statistics. More...
 
struct  config
 Configuration for batch writer. More...
 

Public Member Functions

 batch_writer (log_writer_ptr underlying_writer, const config &cfg=config{})
 Construct a batch writer.
 
 ~batch_writer () override
 Destructor - ensures all pending entries are flushed.
 
common::VoidResult write (const log_entry &entry) override
 Write a log entry to the batch.
 
common::VoidResult flush () override
 Flush the batch to the underlying writer.
 
std::string get_name () const override
 Get writer name.
 
bool is_healthy () const override
 Check if writer is healthy.
 
size_t get_current_batch_size () const
 Get current batch size.
 
const batch_statsget_stats () const
 Get batch statistics.
 
void reset_stats ()
 Reset batch statistics.
 
- Public Member Functions inherited from kcenon::logger::queued_writer_base< std::vector< log_entry > >
 queued_writer_base (std::unique_ptr< log_writer_interface > wrapped_writer, std::size_t max_queue_size, std::string_view decorator_name)
 Constructor for queued writer base.
 
 ~queued_writer_base () override=default
 Virtual destructor.
 
bool is_healthy () const override
 Check if the writer is healthy.
 
std::size_t get_queue_size () const
 Get the current queue size.
 
std::size_t get_max_queue_size () const
 Get maximum queue size.
 
- Public Member Functions inherited from kcenon::logger::decorator_writer_base
 decorator_writer_base (std::unique_ptr< log_writer_interface > wrapped, std::string_view decorator_name)
 Construct a decorator writer base.
 
 ~decorator_writer_base () override=default
 Virtual destructor for proper cleanup.
 
 decorator_writer_base (const decorator_writer_base &)=delete
 
decorator_writer_baseoperator= (const decorator_writer_base &)=delete
 
 decorator_writer_base (decorator_writer_base &&) noexcept=default
 
decorator_writer_baseoperator= (decorator_writer_base &&) noexcept=default
 
common::VoidResult flush () override
 Flush the wrapped writer.
 
std::string get_name () const override
 Get the name of this writer.
 
const log_writer_interfaceget_wrapped_writer () const noexcept
 Get the wrapped writer (const version)
 
- Public Member Functions inherited from kcenon::logger::log_writer_interface
virtual ~log_writer_interface ()=default
 
virtual common::VoidResult close ()
 Close the writer and release resources.
 
virtual auto is_open () const -> bool
 Check if writer is open and ready.
 

Private Types

using base_type = queued_writer_base<std::vector<log_entry>>
 

Private Member Functions

common::VoidResult flush_batch_unsafe ()
 Flush batch without locking (caller must hold lock)
 
bool should_flush_by_size () const
 Check if batch should be flushed based on size.
 
bool should_flush_by_time () const
 Check if batch should be flushed based on time.
 

Private Attributes

config config_
 
std::chrono::steady_clock::time_point last_flush_time_
 
batch_stats stats_
 

Additional Inherited Members

- Static Public Attributes inherited from kcenon::logger::decorator_writer_tag
static constexpr writer_category category = writer_category::decorator
 
- Static Public Attributes inherited from kcenon::logger::async_writer_tag
static constexpr writer_category category = writer_category::asynchronous
 
- Protected Member Functions inherited from kcenon::logger::queued_writer_base< std::vector< log_entry > >
common::VoidResult try_enqueue (const log_entry &entry)
 Try to enqueue an entry with overflow protection.
 
virtual common::VoidResult handle_overflow (const log_entry &)
 Handle queue overflow condition.
 
virtual void on_entry_enqueued ()
 Called after an entry is successfully enqueued.
 
- Protected Member Functions inherited from kcenon::logger::decorator_writer_base
log_writer_interfacewrapped () noexcept
 Access the wrapped writer (non-const)
 
const log_writer_interfacewrapped () const noexcept
 Access the wrapped writer (const)
 
const std::string & decorator_name () const noexcept
 Get the decorator name.
 
- Static Protected Member Functions inherited from kcenon::logger::queued_writer_base< std::vector< log_entry > >
static std::size_t get_container_size (const std::queue< T > &container)
 Get container size (specialization for std::queue)
 
static std::size_t get_container_size (const std::vector< T > &container)
 Get container size (specialization for std::vector)
 
static void enqueue_entry (std::queue< T > &container, const log_entry &entry)
 Enqueue entry (specialization for std::queue)
 
static void enqueue_entry (std::vector< T > &container, const log_entry &entry)
 Enqueue entry (specialization for std::vector)
 
- Protected Attributes inherited from kcenon::logger::queued_writer_base< std::vector< log_entry > >
std::size_t max_queue_size_
 
std::mutex queue_mutex_
 
std::vector< log_entryqueue_
 
std::atomic< bool > shutting_down_
 

Detailed Description

Batch writer that accumulates log entries and writes them in batches.

This writer wraps another writer and accumulates log entries up to a configurable batch size or timeout, then writes them all at once. This reduces the number of I/O operations and improves performance. It extends queued_writer_base to share common queue management logic with async_writer.

Features:

  • Configurable batch size
  • Automatic flush on timeout
  • Thread-safe batch accumulation
  • Preserves original timestamps

Category: Asynchronous (batched I/O), Decorator (wraps another writer)

Since
1.4.0 Added async_writer_tag and decorator_writer_tag for classification
4.0.0 Refactored to use queued_writer_base

Definition at line 43 of file batch_writer.h.

Member Typedef Documentation

◆ base_type

Definition at line 44 of file batch_writer.h.

Constructor & Destructor Documentation

◆ batch_writer()

kcenon::logger::batch_writer::batch_writer ( log_writer_ptr underlying_writer,
const config & cfg = config{} )
explicit

Construct a batch writer.

Parameters
underlying_writerThe actual writer to batch writes for
cfgBatch configuration

Definition at line 11 of file batch_writer.cpp.

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}
std::chrono::steady_clock::time_point last_flush_time_
queued_writer_base< std::vector< log_entry > > base_type

References config_, kcenon::logger::batch_writer::config::max_batch_size, and kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_.

◆ ~batch_writer()

kcenon::logger::batch_writer::~batch_writer ( )
override

Destructor - ensures all pending entries are flushed.

Definition at line 21 of file batch_writer.cpp.

21 {
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}
common::VoidResult flush() override
Flush the batch to the underlying writer.
void safe_destructor_result_operation(const std::string &operation_name, F &&operation) noexcept
Safe operation with result for destructors.

References flush(), kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_, kcenon::logger::utils::safe_destructor_result_operation(), and kcenon::logger::queued_writer_base< std::vector< log_entry > >::shutting_down_.

Here is the call graph for this function:

Member Function Documentation

◆ flush()

common::VoidResult kcenon::logger::batch_writer::flush ( )
overridevirtual

Flush the batch to the underlying writer.

Returns
common::VoidResult indicating success or error

Implements kcenon::logger::log_writer_interface.

Definition at line 62 of file batch_writer.cpp.

62 {
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}
common::VoidResult flush_batch_unsafe()
Flush batch without locking (caller must hold lock)
VoidResult ok()

References flush_batch_unsafe(), kcenon::logger::batch_writer::batch_stats::manual_flushes, kcenon::common::ok(), kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_, kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_mutex_, kcenon::logger::queued_writer_base< std::vector< log_entry > >::shutting_down_, and stats_.

Referenced by write(), and ~batch_writer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ flush_batch_unsafe()

common::VoidResult kcenon::logger::batch_writer::flush_batch_unsafe ( )
private

Flush batch without locking (caller must hold lock)

Returns
common::VoidResult indicating success or error

Definition at line 76 of file batch_writer.cpp.

76 {
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}
log_writer_interface & wrapped() noexcept
Access the wrapped writer (non-const)
virtual common::VoidResult flush()=0
Flush any buffered data.
virtual common::VoidResult write(const log_entry &entry)=0
Write a log entry.

References kcenon::logger::batch_writer::batch_stats::dropped_entries, kcenon::logger::log_writer_interface::flush(), last_flush_time_, kcenon::common::ok(), kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_, stats_, kcenon::logger::batch_writer::batch_stats::total_batches, kcenon::logger::decorator_writer_base::wrapped(), and kcenon::logger::log_writer_interface::write().

Referenced by flush().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_current_batch_size()

size_t kcenon::logger::batch_writer::get_current_batch_size ( ) const

Get current batch size.

Returns
Number of entries currently in the batch

Definition at line 118 of file batch_writer.cpp.

118 {
119 std::lock_guard<std::mutex> lock(queue_mutex_);
120 return queue_.size();
121}

References kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_, and kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_mutex_.

◆ get_name()

std::string kcenon::logger::batch_writer::get_name ( ) const
overridevirtual

Get writer name.

Returns
Name of the batch writer

Implements kcenon::logger::log_writer_interface.

Definition at line 110 of file batch_writer.cpp.

110 {
111 return "batch_writer[" + wrapped().get_name() + "]";
112}
virtual std::string get_name() const =0

References kcenon::logger::log_writer_interface::get_name(), and kcenon::logger::decorator_writer_base::wrapped().

Here is the call graph for this function:

◆ get_stats()

const batch_stats & kcenon::logger::batch_writer::get_stats ( ) const
inline

Get batch statistics.

Returns
Current batch statistics

Definition at line 127 of file batch_writer.h.

127{ return stats_; }

◆ is_healthy()

bool kcenon::logger::batch_writer::is_healthy ( ) const
overridevirtual

Check if writer is healthy.

Returns
true if both batch writer and underlying writer are healthy

Implements kcenon::logger::log_writer_interface.

Definition at line 114 of file batch_writer.cpp.

114 {
115 return !shutting_down_ && wrapped().is_healthy();
116}
virtual bool is_healthy() const =0
Check if the writer is healthy.

References kcenon::logger::log_writer_interface::is_healthy(), kcenon::logger::queued_writer_base< std::vector< log_entry > >::shutting_down_, and kcenon::logger::decorator_writer_base::wrapped().

Here is the call graph for this function:

◆ reset_stats()

◆ should_flush_by_size()

bool kcenon::logger::batch_writer::should_flush_by_size ( ) const
private

Check if batch should be flushed based on size.

Returns
true if batch is full

Definition at line 132 of file batch_writer.cpp.

132 {
133 return queue_.size() >= config_.max_batch_size;
134}

References config_, kcenon::logger::batch_writer::config::max_batch_size, and kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_.

Referenced by write().

Here is the caller graph for this function:

◆ should_flush_by_time()

bool kcenon::logger::batch_writer::should_flush_by_time ( ) const
private

Check if batch should be flushed based on time.

Returns
true if timeout has elapsed

Definition at line 136 of file batch_writer.cpp.

136 {
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}
std::chrono::milliseconds flush_interval

References config_, kcenon::logger::batch_writer::config::flush_interval, and last_flush_time_.

◆ write()

common::VoidResult kcenon::logger::batch_writer::write ( const log_entry & entry)
overridevirtual

Write a log entry to the batch.

Parameters
entryThe log entry to write
Returns
common::VoidResult indicating success or error
Since
3.5.0 Changed to use log_entry directly

Implements kcenon::logger::decorator_writer_base.

Definition at line 32 of file batch_writer.cpp.

32 {
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}
bool should_flush_by_size() const
Check if batch should be flushed based on size.
common::VoidResult make_logger_void_result(logger_error_code code, const std::string &message="")
log_entry copy_log_entry(const log_entry &entry)
Creates a copy of a log_entry for queue storage.

References kcenon::logger::copy_log_entry(), flush(), kcenon::logger::batch_writer::batch_stats::flush_on_size, kcenon::logger::make_logger_void_result(), kcenon::common::ok(), kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_, kcenon::logger::queued_writer_base< std::vector< log_entry > >::queue_mutex_, kcenon::logger::queue_stopped, should_flush_by_size(), kcenon::logger::queued_writer_base< std::vector< log_entry > >::shutting_down_, stats_, and kcenon::logger::batch_writer::batch_stats::total_entries.

Here is the call graph for this function:

Member Data Documentation

◆ config_

config kcenon::logger::batch_writer::config_
private

Definition at line 155 of file batch_writer.h.

Referenced by batch_writer(), should_flush_by_size(), and should_flush_by_time().

◆ last_flush_time_

std::chrono::steady_clock::time_point kcenon::logger::batch_writer::last_flush_time_
private

Definition at line 158 of file batch_writer.h.

Referenced by flush_batch_unsafe(), and should_flush_by_time().

◆ stats_

batch_stats kcenon::logger::batch_writer::stats_
mutableprivate

Definition at line 161 of file batch_writer.h.

Referenced by flush(), flush_batch_unsafe(), reset_stats(), and write().


The documentation for this class was generated from the following files: