Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
console_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
10#include <iostream>
11#include <iomanip>
12#include <cstdlib>
13#include <sstream>
14#include <thread>
15
16#ifdef _WIN32
17#include <windows.h>
18#include <io.h>
19#else
20#include <unistd.h>
21#endif
22
23namespace kcenon::logger {
24
26 bool auto_detect_color,
27 std::unique_ptr<log_formatter_interface> formatter)
28 : use_stderr_(use_stderr)
29 , formatter_(formatter ? std::move(formatter) : std::make_unique<timestamp_formatter>()) {
30 if (auto_detect_color) {
32 } else {
33 // Apply color setting to formatter
34 auto opts = formatter_->get_options();
35 opts.use_colors = use_color_;
36 formatter_->set_options(opts);
37 }
38}
39
43
45 std::lock_guard<std::mutex> lock(mutex_);
47 // Convert logger_system::log_level to common::interfaces::log_level for comparison
48 auto level = static_cast<common::interfaces::log_level>(static_cast<int>(entry.level));
49
50 auto& stream = (use_stderr_ || level <= common::interfaces::log_level::error)
51 ? std::cerr : std::cout;
52
53 if (use_color()) {
54 // Simple color mapping based on level
55 switch (level) {
56 case common::interfaces::log_level::fatal:
57 case common::interfaces::log_level::error:
58 stream << "\033[31m"; // Red
59 break;
60 case common::interfaces::log_level::warning:
61 stream << "\033[33m"; // Yellow
62 break;
63 case common::interfaces::log_level::info:
64 stream << "\033[32m"; // Green
65 break;
66 case common::interfaces::log_level::debug:
67 stream << "\033[36m"; // Cyan
68 break;
69 case common::interfaces::log_level::trace:
70 stream << "\033[37m"; // White
71 break;
72 default:
73 break;
74 }
75 }
76
77 stream << format_entry(entry);
78
79 if (use_color()) {
80 stream << "\033[0m"; // Reset color
81 }
82
83 stream << '\n';
84
85 // Verify stream state
86 return utils::check_stream_state(stream, "console write");
88}
89
91 std::lock_guard<std::mutex> lock(mutex_);
93 std::cout.flush();
94 std::cerr.flush();
95
96 if (std::cout.fail() || std::cerr.fail()) {
97 return make_logger_void_result(logger_error_code::flush_timeout, "Console flush failed");
98 }
99
100 return common::ok();
102}
103
105 return std::cout.good() && std::cerr.good();
106}
107
108void console_writer::set_use_stderr(bool use_stderr) {
109 std::lock_guard<std::mutex> lock(mutex_);
110 use_stderr_ = use_stderr;
111}
112
113void console_writer::set_use_color(bool use_color) {
115 if (formatter_) {
116 auto opts = formatter_->get_options();
117 opts.use_colors = use_color_;
118 formatter_->set_options(opts);
119 }
120}
121
123 return use_color_;
124}
125
126std::string console_writer::format_entry(const log_entry& entry) const {
127 if (!formatter_) {
128 // Fallback if formatter is somehow null
129 return entry.message.to_string();
130 }
131 return formatter_->format(entry);
132}
133
135#ifdef _WIN32
136 // Check if running in Windows Terminal or if ANSI is enabled
137 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
138 if (hOut == INVALID_HANDLE_VALUE) {
139 return false;
140 }
141
142 DWORD dwMode = 0;
143 if (!GetConsoleMode(hOut, &dwMode)) {
144 return false;
145 }
146
147 // Check for ENABLE_VIRTUAL_TERMINAL_PROCESSING flag
148 return (dwMode & 0x0004) != 0;
149#else
150 // Check if output is to a terminal and TERM is set
151 const char* term = std::getenv("TERM");
152 return isatty(STDOUT_FILENO) && term && std::string(term) != "dumb";
153#endif
154}
155
156} // namespace kcenon::logger
console_writer(bool use_stderr=false, bool auto_detect_color=true, std::unique_ptr< log_formatter_interface > formatter=nullptr)
Constructor.
bool is_healthy() const override
Check if writer is healthy.
bool use_color() const
Get current color output setting.
bool is_color_supported() const
Check if terminal supports color.
std::unique_ptr< log_formatter_interface > formatter_
void set_use_stderr(bool use_stderr)
Set whether to use stderr for all output.
~console_writer() override
Destructor.
void set_use_color(bool use_color)
Set whether to use color output (if supported)
common::VoidResult write(const log_entry &entry) override
Write a log entry to console.
std::string format_entry(const log_entry &entry) const
Format a log entry using the current formatter.
common::VoidResult flush() override
Flush console streams.
std::string to_string() const
Convert to std::string.
Default formatter with human-readable timestamp format.
Console writer for logging to stdout/stderr.
Structured error context for debugging log system failures.
Data structures for representing log entries and source locations kcenon.
VoidResult ok()
common::VoidResult check_stream_state(const Stream &stream, const std::string &operation_name="operation")
Stream state verification helper.
common::VoidResult try_write_operation(F &&operation, logger_error_code default_error_code=logger_error_code::file_write_failed)
Error handling helper for write operations.
common::VoidResult make_logger_void_result(logger_error_code code, const std::string &message="")
Small String Optimization (SSO) for short log messages.
Represents a single log entry with all associated metadata.
Definition log_entry.h:155
log_level level
Severity level of the log message.
Definition log_entry.h:162
small_string_256 message
The actual log message.
Definition log_entry.h:169
Default human-readable formatter with timestamps kcenon.