17#elif defined(__unix__) || defined(__APPLE__)
28 : config_(std::move(config))
29 , wrapped_writer_(std::move(wrapped_writer))
32 throw std::invalid_argument(
"Wrapped writer cannot be null");
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
43 auto check = utils::check_condition(
44 wal_stream_->is_open(),
45 logger_error_code::file_open_failed,
46 "Failed to open WAL: " + config_.wal_path
57 if (wal_result.is_err()) {
58 std::cerr <<
"[critical_writer] WAL initialization failed: "
59 << wal_result.error().message << std::endl;
66critical_writer::~critical_writer() {
67 shutting_down_.store(
true);
70 utils::safe_destructor_result_operation(
"final_flush", [
this]() {
76 utils::safe_destructor_operation(
"wal_close", [
this]() {
85 auto level =
static_cast<common::interfaces::log_level
>(
static_cast<int>(entry.
level));
88 if (shutting_down_.load(std::memory_order_acquire)) {
91 std::lock_guard<std::mutex> lock(critical_mutex_);
93 auto result = wrapped_writer_->write(entry);
95 wrapped_writer_->flush();
96 stats_.total_flushes.fetch_add(1, std::memory_order_relaxed);
102 const bool is_critical = is_critical_level(level);
106 std::lock_guard<std::mutex> lock(critical_mutex_);
109 if (wal_stream_ && wal_stream_->is_open()) {
111 stats_.wal_writes.fetch_add(1, std::memory_order_relaxed);
115 auto result = wrapped_writer_->write(entry);
121 auto flush_result = wrapped_writer_->flush();
122 stats_.total_flushes.fetch_add(1, std::memory_order_relaxed);
125 if (config_.sync_on_critical) {
126 sync_file_descriptor();
127 stats_.sync_calls.fetch_add(1, std::memory_order_relaxed);
130 stats_.total_critical_writes.fetch_add(1, std::memory_order_relaxed);
135 return wrapped_writer_->write(entry);
139 std::lock_guard<std::mutex> lock(critical_mutex_);
142 if (wal_stream_ && wal_stream_->is_open()) {
143 wal_stream_->flush();
147 auto result = wrapped_writer_->flush();
148 stats_.total_flushes.fetch_add(1, std::memory_order_relaxed);
153bool critical_writer::is_healthy()
const {
155 if (config_.write_ahead_log && (!wal_stream_ || !wal_stream_->good())) {
159 return wrapped_writer_->is_healthy();
162std::string critical_writer::get_name()
const {
163 return "critical_" + wrapped_writer_->get_name();
166void critical_writer::set_use_color(
bool use_color) {
172void critical_writer::set_force_flush_on_critical(
bool enable) {
173 config_.force_flush_on_critical = enable;
176bool critical_writer::is_critical_level(common::interfaces::log_level level)
const {
178 if (level >= common::interfaces::log_level::critical) {
179 return config_.force_flush_on_critical;
183 if (level == common::interfaces::log_level::error) {
184 return config_.force_flush_on_error;
190void critical_writer::write_to_wal(
const log_entry& entry) {
191 if (!wal_stream_ || !wal_stream_->is_open()) {
197 auto level =
static_cast<common::interfaces::log_level
>(
static_cast<int>(entry.
level));
202 std::string function = entry.
location ? entry.
location->function.to_string() :
"";
205 auto time_t = std::chrono::system_clock::to_time_t(entry.
timestamp);
206 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
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 <<
"] "
217 *wal_stream_ << oss.str();
218 wal_stream_->flush();
220 }
catch (
const std::exception& e) {
221 std::cerr <<
"[critical_writer] WAL write exception: "
222 << e.what() << std::endl;
226void critical_writer::sync_file_descriptor() {
232 wal_stream_->flush();
236#elif defined(__unix__) || defined(__APPLE__)
243 ::fsync(STDOUT_FILENO);
244 ::fsync(STDERR_FILENO);
248 wal_stream_->flush();
258hybrid_writer::hybrid_writer(
261 std::size_t async_queue_size
263 : async_queue_size_(async_queue_size)
267 std::move(wrapped_writer),
268 std::move(critical_config)
bool use_color() const
Get current color output setting.
critical_writer_config config_
Configuration.
critical_writer(log_writer_ptr wrapped_writer, critical_writer_config config={})
Constructor.
log_writer_ptr wrapped_writer_
Wrapped writer.
log_writer_ptr critical_writer_
std::string get_name() const override
~hybrid_writer() override
bool is_healthy() const override
Check if the writer is healthy and operational.
common::VoidResult write(const log_entry &entry) override
Write a log entry.
common::VoidResult flush() override
Flush any buffered data.
void set_use_color(bool use_color) override
Set whether to use color output (if supported)
std::string to_string() const
Convert to std::string.
Synchronous wrapper for critical log messages to prevent loss.
Error codes specific to the logger system.
Structured error context for debugging log system failures.
std::unique_ptr< log_writer_interface > log_writer_ptr
Type alias for writer unique pointer.
String utility functions for log formatting and conversion.
Configuration for critical log writer.
bool write_ahead_log
Enable write-ahead logging for maximum durability (default: false)
Represents a single log entry with all associated metadata.
std::optional< source_location > location
Optional source code location information.
log_level level
Severity level of the log message.
small_string_256 message
The actual log message.
std::chrono::system_clock::time_point timestamp
Timestamp when the log entry was created.