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

Synchronous wrapper ensuring critical logs are never lost. More...

#include <critical_writer.h>

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

Classes

struct  critical_stats
 Get statistics about critical writes. More...
 

Public Member Functions

 critical_writer (log_writer_ptr wrapped_writer, critical_writer_config config={})
 Constructor.
 
 ~critical_writer () override
 Destructor - ensures final flush.
 
common::VoidResult write (const log_entry &entry) override
 Write a log entry with critical handling.
 
common::VoidResult flush () override
 Flush all pending messages.
 
bool is_healthy () const override
 Check if the writer is healthy.
 
std::string get_name () const override
 Get the name of this writer.
 
void set_use_color (bool use_color) override
 Set whether to use color output.
 
void set_force_flush_on_critical (bool enable)
 Enable/disable critical flushing at runtime.
 
const critical_writer_configget_config () const
 Get current configuration.
 
const critical_statsget_stats () const
 
- Public Member Functions inherited from kcenon::logger::base_writer
 base_writer (std::unique_ptr< log_formatter_interface > formatter=nullptr)
 Constructor with optional formatter.
 
virtual ~base_writer ()=default
 
bool use_color () const
 Get current color output setting.
 
log_formatter_interfaceget_formatter () const
 Get the current formatter.
 
- 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 Member Functions

bool is_critical_level (common::interfaces::log_level level) const
 Check if log level requires critical handling.
 
void write_to_wal (const log_entry &entry)
 Write to write-ahead log.
 
void sync_file_descriptor ()
 Force sync of underlying file descriptor.
 

Private Attributes

critical_writer_config config_
 Configuration.
 
log_writer_ptr wrapped_writer_
 Wrapped writer.
 
std::mutex critical_mutex_
 Mutex for critical section.
 
std::unique_ptr< std::ofstream > wal_stream_
 Write-ahead log stream.
 
critical_stats stats_
 Statistics.
 
std::atomic< bool > shutting_down_ {false}
 Flag for shutdown.
 

Additional Inherited Members

- Static Public Attributes inherited from kcenon::logger::decorator_writer_tag
static constexpr writer_category category = writer_category::decorator
 
- Protected Member Functions inherited from kcenon::logger::base_writer
std::string format_log_entry (const log_entry &entry) const
 Format a log entry using the current formatter.
 

Detailed Description

Synchronous wrapper ensuring critical logs are never lost.

This writer prevents message loss by:

  1. Bypassing async queue for critical/fatal messages
  2. Forcing immediate flush after critical writes
  3. Optional write-ahead logging for crash recovery
  4. File descriptor synchronization (fsync) for durability

For signal handling, use signal_manager or crash_safe_logger instead.

Thread Safety: All methods are thread-safe. Critical writes are serialized to ensure ordering and prevent interleaving.

Category: Decorator (wraps another writer to add critical message handling)

Since
1.4.0 Added decorator_writer_tag for category classification

Definition at line 103 of file critical_writer.h.

Constructor & Destructor Documentation

◆ critical_writer()

kcenon::logger::critical_writer::critical_writer ( log_writer_ptr wrapped_writer,
critical_writer_config config = {} )
explicit

Constructor.

Parameters
wrapped_writerThe underlying writer to wrap
configConfiguration options
Exceptions
std::invalid_argumentif wrapped_writer is null

Definition at line 24 of file critical_writer.cpp.

28 : config_(std::move(config))
29 , wrapped_writer_(std::move(wrapped_writer))
30{
31 if (!wrapped_writer_) {
32 throw std::invalid_argument("Wrapped writer cannot be null");
33 }
34
35 // Initialize write-ahead log if enabled
37 auto wal_result = utils::try_open_operation([&]() -> common::VoidResult {
38 wal_stream_ = std::make_unique<std::ofstream>(
40 std::ios::app | std::ios::binary
41 );
42
43 auto check = utils::check_condition(
44 wal_stream_->is_open(),
46 "Failed to open WAL: " + config_.wal_path
47 );
48
49 if (check.is_err()) {
50 wal_stream_.reset();
51 return check;
52 }
53
54 return common::ok();
55 });
56
57 if (wal_result.is_err()) {
58 std::cerr << "[critical_writer] WAL initialization failed: "
59 << wal_result.error().message << std::endl;
60 wal_stream_.reset();
61 }
62 }
63
64}
critical_writer_config config_
Configuration.
std::unique_ptr< std::ofstream > wal_stream_
Write-ahead log stream.
log_writer_ptr wrapped_writer_
Wrapped writer.
VoidResult ok()
common::VoidResult try_open_operation(F &&operation)
Error handling helper for file open operations.
common::VoidResult check_condition(bool condition, logger_error_code error_code, const std::string &message)
Condition verification helper.
std::string wal_path
Path for write-ahead log file (only if write_ahead_log is true)
bool write_ahead_log
Enable write-ahead logging for maximum durability (default: false)

References config_, wrapped_writer_, and kcenon::logger::critical_writer_config::write_ahead_log.

◆ ~critical_writer()

kcenon::logger::critical_writer::~critical_writer ( )
override

Destructor - ensures final flush.

Definition at line 66 of file critical_writer.cpp.

66 {
67 shutting_down_.store(true);
68
69 // Final flush - use safe operation to log any errors
70 utils::safe_destructor_result_operation("final_flush", [this]() {
71 return flush();
72 });
73
74 // Close WAL with proper error logging
75 if (wal_stream_) {
76 utils::safe_destructor_operation("wal_close", [this]() {
77 wal_stream_->flush();
78 wal_stream_->close();
79 });
80 }
81}
std::atomic< bool > shutting_down_
Flag for shutdown.
common::VoidResult flush() override
Flush all pending messages.
void safe_destructor_operation(const std::string &operation_name, F &&operation) noexcept
Safe operation execution for destructors.
void safe_destructor_result_operation(const std::string &operation_name, F &&operation) noexcept
Safe operation with result for destructors.

Member Function Documentation

◆ flush()

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

Flush all pending messages.

Returns
common::VoidResult indicating success or error

Implements kcenon::logger::base_writer.

Definition at line 138 of file critical_writer.cpp.

138 {
139 std::lock_guard<std::mutex> lock(critical_mutex_);
140
141 // Flush WAL
142 if (wal_stream_ && wal_stream_->is_open()) {
143 wal_stream_->flush();
144 }
145
146 // Flush wrapped writer
147 auto result = wrapped_writer_->flush();
148 stats_.total_flushes.fetch_add(1, std::memory_order_relaxed);
149
150 return result;
151}
std::mutex critical_mutex_
Mutex for critical section.
critical_stats stats_
Statistics.

◆ get_config()

const critical_writer_config & kcenon::logger::critical_writer::get_config ( ) const
inline

Get current configuration.

Returns
Current configuration

Definition at line 173 of file critical_writer.h.

173{ return config_; }

◆ get_name()

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

Get the name of this writer.

Returns
Writer name

Implements kcenon::logger::base_writer.

Definition at line 162 of file critical_writer.cpp.

162 {
163 return "critical_" + wrapped_writer_->get_name();
164}

◆ get_stats()

const critical_stats & kcenon::logger::critical_writer::get_stats ( ) const
inline

Definition at line 185 of file critical_writer.h.

185{ return stats_; }

◆ is_critical_level()

bool kcenon::logger::critical_writer::is_critical_level ( common::interfaces::log_level level) const
private

Check if log level requires critical handling.

Parameters
levelLog level to check
Returns
true if level requires immediate flush

Definition at line 176 of file critical_writer.cpp.

176 {
177 // Critical and fatal always require immediate flush
178 if (level >= common::interfaces::log_level::critical) {
180 }
181
182 // Error level if configured
183 if (level == common::interfaces::log_level::error) {
185 }
186
187 return false;
188}
bool force_flush_on_error
Force immediate flush for error messages (default: false)
bool force_flush_on_critical
Force immediate flush for critical/fatal messages (default: true)

◆ is_healthy()

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

Check if the writer is healthy.

Returns
true if healthy, false otherwise

Reimplemented from kcenon::logger::base_writer.

Definition at line 153 of file critical_writer.cpp.

153 {
154 // Check WAL health
155 if (config_.write_ahead_log && (!wal_stream_ || !wal_stream_->good())) {
156 return false;
157 }
158
159 return wrapped_writer_->is_healthy();
160}

◆ set_force_flush_on_critical()

void kcenon::logger::critical_writer::set_force_flush_on_critical ( bool enable)

Enable/disable critical flushing at runtime.

Parameters
enableEnable or disable

Definition at line 172 of file critical_writer.cpp.

172 {
174}

◆ set_use_color()

void kcenon::logger::critical_writer::set_use_color ( bool use_color)
overridevirtual

Set whether to use color output.

Parameters
use_colorEnable/disable color output

Reimplemented from kcenon::logger::base_writer.

Definition at line 166 of file critical_writer.cpp.

166 {
167 // Color setting is now handled by formatter, not writer interface
168 // This method is kept for backward compatibility but is deprecated
169 (void)use_color; // Suppress unused parameter warning
170}
bool use_color() const
Get current color output setting.

◆ sync_file_descriptor()

void kcenon::logger::critical_writer::sync_file_descriptor ( )
private

Force sync of underlying file descriptor.

Definition at line 226 of file critical_writer.cpp.

226 {
227#ifdef _WIN32
228 // Windows: Use _commit() to flush file buffers to disk
229 // Note: std::ofstream doesn't expose HANDLE, so we flush the stream
230 // For a complete implementation, would need native Windows file handling
231 if (wal_stream_) {
232 wal_stream_->flush();
233 }
234 // Could use _flushall() to flush all open streams, but it's global
235 ::_flushall();
236#elif defined(__unix__) || defined(__APPLE__)
237 // POSIX: Use fsync() to synchronize file to disk
238 // Get file descriptor from wrapped writer if it's a file writer
239 // This is a simplified implementation - actual implementation would need
240 // to query the wrapped writer for its file descriptor
241
242 // For now, sync stdout/stderr as fallback
243 ::fsync(STDOUT_FILENO);
244 ::fsync(STDERR_FILENO);
245
246 // Sync WAL
247 if (wal_stream_) {
248 wal_stream_->flush();
249 // Note: std::ofstream doesn't expose fd, would need native file handling
250 }
251#endif
252}

◆ write()

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

Write a log entry with critical handling.

Parameters
entryThe log entry to write
Returns
common::VoidResult indicating success or error

For critical/fatal messages:

  • Acquires exclusive lock
  • Writes to WAL (if enabled)
  • Writes to wrapped writer
  • Forces immediate flush
  • Syncs file descriptor (if configured)

For non-critical messages, delegates to wrapped writer normally.

Since
3.5.0 Changed to use log_entry directly

Implements kcenon::logger::base_writer.

Definition at line 83 of file critical_writer.cpp.

83 {
84 // Convert log_level from logger_system to common::interfaces
85 auto level = static_cast<common::interfaces::log_level>(static_cast<int>(entry.level));
86
87 // Check if we're in emergency shutdown (signal received)
88 if (shutting_down_.load(std::memory_order_acquire)) {
89 // In shutdown mode, all writes become critical to ensure they're flushed
90 // before process termination
91 std::lock_guard<std::mutex> lock(critical_mutex_);
92
93 auto result = wrapped_writer_->write(entry);
94 if (result.is_ok()) {
95 wrapped_writer_->flush();
96 stats_.total_flushes.fetch_add(1, std::memory_order_relaxed);
97 }
98 return result;
99 }
100
101 // Check if this is a critical level
102 const bool is_critical = is_critical_level(level);
103
104 if (is_critical) {
105 // Acquire exclusive lock for critical writes
106 std::lock_guard<std::mutex> lock(critical_mutex_);
107
108 // Write to WAL first (if enabled)
109 if (wal_stream_ && wal_stream_->is_open()) {
110 write_to_wal(entry);
111 stats_.wal_writes.fetch_add(1, std::memory_order_relaxed);
112 }
113
114 // Write to wrapped writer
115 auto result = wrapped_writer_->write(entry);
116 if (result.is_err()) {
117 return result;
118 }
119
120 // Force flush immediately
121 auto flush_result = wrapped_writer_->flush();
122 stats_.total_flushes.fetch_add(1, std::memory_order_relaxed);
123
124 // Sync file descriptor if configured
127 stats_.sync_calls.fetch_add(1, std::memory_order_relaxed);
128 }
129
130 stats_.total_critical_writes.fetch_add(1, std::memory_order_relaxed);
131 return flush_result;
132 }
133
134 // Non-critical: delegate to wrapped writer normally
135 return wrapped_writer_->write(entry);
136}
void write_to_wal(const log_entry &entry)
Write to write-ahead log.
bool is_critical_level(common::interfaces::log_level level) const
Check if log level requires critical handling.
void sync_file_descriptor()
Force sync of underlying file descriptor.
bool sync_on_critical
Sync file descriptor after each critical write (default: true)

References kcenon::logger::log_entry::level.

◆ write_to_wal()

void kcenon::logger::critical_writer::write_to_wal ( const log_entry & entry)
private

Write to write-ahead log.

Parameters
entryLog entry to write to WAL

Definition at line 190 of file critical_writer.cpp.

190 {
191 if (!wal_stream_ || !wal_stream_->is_open()) {
192 return;
193 }
194
195 try {
196 // Convert log_level
197 auto level = static_cast<common::interfaces::log_level>(static_cast<int>(entry.level));
198
199 // Extract source location
200 std::string file = entry.location ? entry.location->file.to_string() : "";
201 int line = entry.location ? entry.location->line : 0;
202 std::string function = entry.location ? entry.location->function.to_string() : "";
203
204 // Format: [timestamp] [LEVEL] [file:line:function] message\n
205 auto time_t = std::chrono::system_clock::to_time_t(entry.timestamp);
206 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
207 entry.timestamp.time_since_epoch()
208 ).count() % 1000;
209
210 std::ostringstream oss;
211 oss << "[" << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S")
212 << "." << std::setfill('0') << std::setw(3) << ms << "] "
213 << "[" << utils::string_utils::level_to_string(level) << "] "
214 << "[" << file << ":" << line << ":" << function << "] "
215 << entry.message.to_string() << "\n";
216
217 *wal_stream_ << oss.str();
218 wal_stream_->flush();
219
220 } catch (const std::exception& e) {
221 std::cerr << "[critical_writer] WAL write exception: "
222 << e.what() << std::endl;
223 }
224}
static std::string level_to_string(log_level level)
Convert log level to human-readable string.

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

Here is the call graph for this function:

Member Data Documentation

◆ config_

critical_writer_config kcenon::logger::critical_writer::config_
private

Configuration.

Definition at line 208 of file critical_writer.h.

Referenced by critical_writer().

◆ critical_mutex_

std::mutex kcenon::logger::critical_writer::critical_mutex_
mutableprivate

Mutex for critical section.

Definition at line 214 of file critical_writer.h.

◆ shutting_down_

std::atomic<bool> kcenon::logger::critical_writer::shutting_down_ {false}
private

Flag for shutdown.

Definition at line 223 of file critical_writer.h.

223{false};

◆ stats_

critical_stats kcenon::logger::critical_writer::stats_
mutableprivate

Statistics.

Definition at line 220 of file critical_writer.h.

◆ wal_stream_

std::unique_ptr<std::ofstream> kcenon::logger::critical_writer::wal_stream_
private

Write-ahead log stream.

Definition at line 217 of file critical_writer.h.

◆ wrapped_writer_

log_writer_ptr kcenon::logger::critical_writer::wrapped_writer_
private

Wrapped writer.

Definition at line 211 of file critical_writer.h.

Referenced by critical_writer().


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