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

Decorator that buffers log entries before writing to wrapped writer. More...

#include <buffered_writer.h>

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

Classes

struct  stats
 Statistics for the buffered writer. More...
 

Public Member Functions

 buffered_writer (std::unique_ptr< log_writer_interface > wrapped, size_t max_entries=DEFAULT_BUFFER_SIZE, std::chrono::milliseconds flush_interval=DEFAULT_FLUSH_INTERVAL)
 Construct a buffered writer.
 
 ~buffered_writer () override
 Destructor - flushes any remaining buffered entries.
 
 buffered_writer (const buffered_writer &)=delete
 
buffered_writeroperator= (const buffered_writer &)=delete
 
 buffered_writer (buffered_writer &&)=delete
 
buffered_writeroperator= (buffered_writer &&)=delete
 
common::VoidResult write (const log_entry &entry) override
 Write a log entry to the buffer.
 
common::VoidResult flush () override
 Flush all buffered entries to the wrapped writer.
 
size_t get_buffer_count () const
 Get the current number of buffered entries.
 
size_t get_max_entries () const noexcept
 Get the maximum buffer size.
 
std::chrono::milliseconds get_flush_interval () const noexcept
 Get the configured flush interval.
 
const statsget_stats () const noexcept
 Get buffered writer statistics.
 
void reset_stats ()
 Reset statistics counters.
 
- 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.
 
bool is_healthy () const override
 Check if the writer is healthy.
 
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.
 

Static Public Attributes

static constexpr size_t DEFAULT_BUFFER_SIZE = 100
 Default buffer size (number of entries)
 
static constexpr std::chrono::milliseconds DEFAULT_FLUSH_INTERVAL {5000}
 Default flush interval.
 
- Static Public Attributes inherited from kcenon::logger::decorator_writer_tag
static constexpr writer_category category = writer_category::decorator
 

Private Member Functions

common::VoidResult flush_buffer_unsafe ()
 Flush buffer without acquiring mutex (caller must hold lock)
 
bool should_flush_by_time () const
 Check if time-based flush is needed.
 

Static Private Member Functions

static log_entry copy_entry (const log_entry &entry)
 Copy a log entry for buffer storage.
 

Private Attributes

size_t max_entries_
 
std::chrono::milliseconds flush_interval_
 
std::mutex mutex_
 
std::vector< log_entrybuffer_
 
std::chrono::steady_clock::time_point last_flush_time_
 
stats stats_
 

Additional Inherited Members

- 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.
 

Detailed Description

Decorator that buffers log entries before writing to wrapped writer.

This class implements the Decorator pattern for log writers. It wraps any log_writer_interface implementation and buffers log entries up to a configurable limit before flushing them to the wrapped writer.

Key features:

  • Configurable buffer size (number of entries)
  • Configurable flush interval for time-based flushing
  • Auto-flushes when buffer is full
  • Thread-safe implementation with mutex protection
  • Can be nested with other decorators

Flush triggers:

  1. Buffer reaches max_entries limit
  2. Flush interval elapsed since last flush
  3. Explicit flush() call
  4. Destructor (ensures no data loss)

Category: Synchronous (immediate return), Decorator

Note
Thread-safe: All operations are protected by mutex.
Destructor flushes remaining entries to prevent data loss.
Since
4.0.0
Examples
decorator_usage.cpp.

Definition at line 81 of file buffered_writer.h.

Constructor & Destructor Documentation

◆ buffered_writer() [1/3]

kcenon::logger::buffered_writer::buffered_writer ( std::unique_ptr< log_writer_interface > wrapped,
size_t max_entries = DEFAULT_BUFFER_SIZE,
std::chrono::milliseconds flush_interval = DEFAULT_FLUSH_INTERVAL )
explicit

Construct a buffered writer.

Parameters
wrappedThe writer to wrap with buffering
max_entriesMaximum number of entries to buffer before auto-flush
flush_intervalMaximum time between flushes (0 disables time-based flush)
Exceptions
std::invalid_argumentif wrapped is nullptr
std::invalid_argumentif max_entries is 0
Since
4.0.0

Definition at line 18 of file buffered_writer.cpp.

21 : decorator_writer_base(std::move(wrapped), "buffered")
22 , max_entries_(max_entries)
23 , flush_interval_(flush_interval)
24 , last_flush_time_(std::chrono::steady_clock::now()) {
25 if (max_entries_ == 0) {
26 throw std::invalid_argument("buffered_writer: max_entries must be greater than 0");
27 }
28 buffer_.reserve(max_entries_);
29}
std::vector< log_entry > buffer_
std::chrono::steady_clock::time_point last_flush_time_
std::chrono::milliseconds flush_interval_
decorator_writer_base(std::unique_ptr< log_writer_interface > wrapped, std::string_view decorator_name)
Construct a decorator writer base.
log_writer_interface & wrapped() noexcept
Access the wrapped writer (non-const)

References buffer_, and max_entries_.

◆ ~buffered_writer()

kcenon::logger::buffered_writer::~buffered_writer ( )
override

Destructor - flushes any remaining buffered entries.

Ensures no log entries are lost by flushing the buffer before destruction. Any errors during final flush are silently ignored as there's no way to report them.

Since
4.0.0

Definition at line 31 of file buffered_writer.cpp.

31 {
32 // Flush remaining entries - ignore errors as we can't report them
33 std::lock_guard<std::mutex> lock(mutex_);
34 if (!buffer_.empty()) {
36 }
37}
common::VoidResult flush_buffer_unsafe()
Flush buffer without acquiring mutex (caller must hold lock)

References buffer_, flush_buffer_unsafe(), and mutex_.

Here is the call graph for this function:

◆ buffered_writer() [2/3]

kcenon::logger::buffered_writer::buffered_writer ( const buffered_writer & )
delete

◆ buffered_writer() [3/3]

kcenon::logger::buffered_writer::buffered_writer ( buffered_writer && )
delete

Member Function Documentation

◆ copy_entry()

log_entry kcenon::logger::buffered_writer::copy_entry ( const log_entry & entry)
staticprivate

Copy a log entry for buffer storage.

Parameters
entrySource entry to copy
Returns
Copied log entry

Definition at line 109 of file buffered_writer.cpp.

109 {
110 if (entry.location) {
111 return log_entry(entry.level,
112 entry.message.to_string(),
113 entry.location->file.to_string(),
114 entry.location->line,
115 entry.location->function.to_string(),
116 entry.timestamp);
117 }
118 return log_entry(entry.level, entry.message.to_string(), entry.timestamp);
119}

References kcenon::logger::log_entry::level, kcenon::logger::log_entry::location, kcenon::logger::log_entry::message, kcenon::logger::log_entry::timestamp, and kcenon::logger::small_string< SSO_SIZE >::to_string().

Referenced by write().

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

◆ flush()

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

Flush all buffered entries to the wrapped writer.

Returns
common::VoidResult Success if all entries written, error otherwise

Writes all buffered entries to the wrapped writer and clears the buffer. Also calls flush() on the wrapped writer.

Note
Thread-safe operation.
Since
4.0.0

Implements kcenon::logger::log_writer_interface.

Definition at line 66 of file buffered_writer.cpp.

66 {
67 std::lock_guard<std::mutex> lock(mutex_);
68
69 if (!buffer_.empty()) {
70 stats_.manual_flushes.fetch_add(1, std::memory_order_relaxed);
71 }
72
73 return flush_buffer_unsafe();
74}

References buffer_, flush_buffer_unsafe(), kcenon::logger::buffered_writer::stats::manual_flushes, mutex_, and stats_.

Here is the call graph for this function:

◆ flush_buffer_unsafe()

common::VoidResult kcenon::logger::buffered_writer::flush_buffer_unsafe ( )
private

Flush buffer without acquiring mutex (caller must hold lock)

Returns
common::VoidResult indicating success or failure

Definition at line 76 of file buffered_writer.cpp.

76 {
77 // Write all buffered entries to wrapped writer
78 for (const auto& entry : buffer_) {
79 auto result = wrapped().write(entry);
80 if (result.is_err()) {
81 // Clear buffer even on error to avoid infinite retry
82 buffer_.clear();
83 last_flush_time_ = std::chrono::steady_clock::now();
84 return result;
85 }
86 }
87
88 buffer_.clear();
89 last_flush_time_ = std::chrono::steady_clock::now();
90
91 if (!buffer_.empty() || stats_.total_flushes > 0) {
92 stats_.total_flushes.fetch_add(1, std::memory_order_relaxed);
93 }
94
95 // Delegate to wrapped writer's flush
96 return wrapped().flush();
97}
virtual common::VoidResult flush()=0
Flush any buffered data.
virtual common::VoidResult write(const log_entry &entry)=0
Write a log entry.

References buffer_, kcenon::logger::log_writer_interface::flush(), last_flush_time_, stats_, kcenon::logger::buffered_writer::stats::total_flushes, kcenon::logger::decorator_writer_base::wrapped(), and kcenon::logger::log_writer_interface::write().

Referenced by flush(), write(), and ~buffered_writer().

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

◆ get_buffer_count()

size_t kcenon::logger::buffered_writer::get_buffer_count ( ) const

Get the current number of buffered entries.

Returns
Number of entries currently in the buffer
Since
4.0.0

Definition at line 121 of file buffered_writer.cpp.

121 {
122 std::lock_guard<std::mutex> lock(mutex_);
123 return buffer_.size();
124}

References buffer_, and mutex_.

◆ get_flush_interval()

std::chrono::milliseconds kcenon::logger::buffered_writer::get_flush_interval ( ) const
noexcept

Get the configured flush interval.

Returns
Flush interval in milliseconds
Since
4.0.0

Definition at line 130 of file buffered_writer.cpp.

130 {
131 return flush_interval_;
132}

References flush_interval_.

◆ get_max_entries()

size_t kcenon::logger::buffered_writer::get_max_entries ( ) const
noexcept

Get the maximum buffer size.

Returns
Maximum number of entries the buffer can hold
Since
4.0.0

Definition at line 126 of file buffered_writer.cpp.

126 {
127 return max_entries_;
128}

References max_entries_.

◆ get_stats()

const buffered_writer::stats & kcenon::logger::buffered_writer::get_stats ( ) const
noexcept

Get buffered writer statistics.

Returns
Reference to current statistics
Since
4.0.0

Definition at line 134 of file buffered_writer.cpp.

134 {
135 return stats_;
136}

References stats_.

◆ operator=() [1/2]

buffered_writer & kcenon::logger::buffered_writer::operator= ( buffered_writer && )
delete

◆ operator=() [2/2]

buffered_writer & kcenon::logger::buffered_writer::operator= ( const buffered_writer & )
delete

◆ reset_stats()

void kcenon::logger::buffered_writer::reset_stats ( )

Reset statistics counters.

Since
4.0.0

Definition at line 138 of file buffered_writer.cpp.

138 {
139 stats_.total_entries_written.store(0, std::memory_order_relaxed);
140 stats_.total_flushes.store(0, std::memory_order_relaxed);
141 stats_.flush_on_full.store(0, std::memory_order_relaxed);
142 stats_.flush_on_interval.store(0, std::memory_order_relaxed);
143 stats_.manual_flushes.store(0, std::memory_order_relaxed);
144}
std::atomic< uint64_t > total_entries_written
std::atomic< uint64_t > flush_on_interval

References kcenon::logger::buffered_writer::stats::flush_on_full, kcenon::logger::buffered_writer::stats::flush_on_interval, kcenon::logger::buffered_writer::stats::manual_flushes, stats_, kcenon::logger::buffered_writer::stats::total_entries_written, and kcenon::logger::buffered_writer::stats::total_flushes.

◆ should_flush_by_time()

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

Check if time-based flush is needed.

Returns
true if flush interval has elapsed since last flush

Definition at line 99 of file buffered_writer.cpp.

99 {
100 if (flush_interval_.count() == 0) {
101 return false; // Time-based flush disabled
102 }
103
104 auto now = std::chrono::steady_clock::now();
105 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_flush_time_);
106 return elapsed >= flush_interval_;
107}

References flush_interval_, and last_flush_time_.

Referenced by write().

Here is the caller graph for this function:

◆ write()

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

Write a log entry to the buffer.

Parameters
entryThe log entry to write
Returns
common::VoidResult Success on buffering, error if flush fails

Adds the entry to the internal buffer. If the buffer becomes full or the flush interval has elapsed, triggers an automatic flush.

Note
Thread-safe operation.
Since
4.0.0

Implements kcenon::logger::decorator_writer_base.

Definition at line 39 of file buffered_writer.cpp.

39 {
40 std::lock_guard<std::mutex> lock(mutex_);
41
42 // Add entry to buffer
43 buffer_.push_back(copy_entry(entry));
44 stats_.total_entries_written.fetch_add(1, std::memory_order_relaxed);
45
46 // Check if we need to flush
47 bool flush_needed = false;
48 bool flush_by_size = buffer_.size() >= max_entries_;
49 bool flush_by_time = should_flush_by_time();
50
51 if (flush_by_size) {
52 stats_.flush_on_full.fetch_add(1, std::memory_order_relaxed);
53 flush_needed = true;
54 } else if (flush_by_time) {
55 stats_.flush_on_interval.fetch_add(1, std::memory_order_relaxed);
56 flush_needed = true;
57 }
58
59 if (flush_needed) {
60 return flush_buffer_unsafe();
61 }
62
63 return common::ok();
64}
bool should_flush_by_time() const
Check if time-based flush is needed.
static log_entry copy_entry(const log_entry &entry)
Copy a log entry for buffer storage.
VoidResult ok()

References buffer_, copy_entry(), flush_buffer_unsafe(), kcenon::logger::buffered_writer::stats::flush_on_full, kcenon::logger::buffered_writer::stats::flush_on_interval, max_entries_, mutex_, kcenon::common::ok(), should_flush_by_time(), stats_, and kcenon::logger::buffered_writer::stats::total_entries_written.

Here is the call graph for this function:

Member Data Documentation

◆ buffer_

std::vector<log_entry> kcenon::logger::buffered_writer::buffer_
private

◆ DEFAULT_BUFFER_SIZE

size_t kcenon::logger::buffered_writer::DEFAULT_BUFFER_SIZE = 100
staticconstexpr

Default buffer size (number of entries)

Definition at line 86 of file buffered_writer.h.

◆ DEFAULT_FLUSH_INTERVAL

std::chrono::milliseconds kcenon::logger::buffered_writer::DEFAULT_FLUSH_INTERVAL {5000}
staticconstexpr

Default flush interval.

Definition at line 91 of file buffered_writer.h.

91{5000};

◆ flush_interval_

std::chrono::milliseconds kcenon::logger::buffered_writer::flush_interval_
private

Definition at line 236 of file buffered_writer.h.

Referenced by get_flush_interval(), and should_flush_by_time().

◆ last_flush_time_

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

Definition at line 240 of file buffered_writer.h.

Referenced by flush_buffer_unsafe(), and should_flush_by_time().

◆ max_entries_

size_t kcenon::logger::buffered_writer::max_entries_
private

Definition at line 235 of file buffered_writer.h.

Referenced by buffered_writer(), get_max_entries(), and write().

◆ mutex_

std::mutex kcenon::logger::buffered_writer::mutex_
mutableprivate

Definition at line 238 of file buffered_writer.h.

Referenced by flush(), get_buffer_count(), write(), and ~buffered_writer().

◆ stats_

stats kcenon::logger::buffered_writer::stats_
mutableprivate

Definition at line 242 of file buffered_writer.h.

Referenced by flush(), flush_buffer_unsafe(), get_stats(), reset_stats(), and write().


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