9 #include "quill/core/Attributes.h" 10 #include "quill/core/LogLevel.h" 11 #include "quill/sinks/StreamSink.h" 18 #include <string_view> 23 #if !defined(WIN32_LEAN_AND_MEAN) 24 #define WIN32_LEAN_AND_MEAN 27 #if !defined(NOMINMAX) 59 Colours() { apply_default_colours(); }
68 assign_colour_to_log_level(LogLevel::TraceL3, white);
69 assign_colour_to_log_level(LogLevel::TraceL2, white);
70 assign_colour_to_log_level(LogLevel::TraceL1, white);
71 assign_colour_to_log_level(LogLevel::Debug, cyan);
72 assign_colour_to_log_level(LogLevel::Info, green);
73 assign_colour_to_log_level(LogLevel::Notice, white_bold);
74 assign_colour_to_log_level(LogLevel::Warning, yellow_bold);
75 assign_colour_to_log_level(LogLevel::Error, red_bold);
76 assign_colour_to_log_level(LogLevel::Critical, bold_on_red);
77 assign_colour_to_log_level(LogLevel::Backtrace, magenta);
87 auto const log_lvl =
static_cast<uint32_t
>(log_level);
88 _log_level_colours[log_lvl] = colour;
89 _colours_enabled =
true;
92 QUILL_ATTRIBUTE_COLD
void set_colours_enabled(
bool value) { _colours_enabled = value; }
99 return _colour_output_supported && _colours_enabled;
109 auto const log_lvl =
static_cast<uint32_t
>(log_level);
110 return _log_level_colours[log_lvl];
114 static constexpr std::string_view reset{
"\033[0m"};
115 static constexpr std::string_view bold{
"\033[1m"};
116 static constexpr std::string_view dark{
"\033[2m"};
117 static constexpr std::string_view underline{
"\033[4m"};
118 static constexpr std::string_view blink{
"\033[5m"};
119 static constexpr std::string_view reverse{
"\033[7m"};
120 static constexpr std::string_view concealed{
"\033[8m"};
121 static constexpr std::string_view clear_line{
"\033[K"};
124 static constexpr std::string_view black{
"\033[30m"};
125 static constexpr std::string_view red{
"\033[31m"};
126 static constexpr std::string_view green{
"\033[32m"};
127 static constexpr std::string_view yellow{
"\033[33m"};
128 static constexpr std::string_view blue{
"\033[34m"};
129 static constexpr std::string_view magenta{
"\033[35m"};
130 static constexpr std::string_view cyan{
"\033[36m"};
131 static constexpr std::string_view white{
"\033[37m"};
134 static constexpr std::string_view on_black{
"\033[40m"};
135 static constexpr std::string_view on_red{
"\033[41m"};
136 static constexpr std::string_view on_green{
"\033[42m"};
137 static constexpr std::string_view on_yellow{
"\033[43m"};
138 static constexpr std::string_view on_blue{
"\033[44m"};
139 static constexpr std::string_view on_magenta{
"\033[45m"};
140 static constexpr std::string_view on_cyan{
"\033[46m"};
141 static constexpr std::string_view on_white{
"\033[47m"};
144 static constexpr std::string_view white_bold{
"\033[97m\033[1m"};
145 static constexpr std::string_view yellow_bold{
"\033[33m\033[1m"};
146 static constexpr std::string_view red_bold{
"\033[31m\033[1m"};
147 static constexpr std::string_view bold_on_red{
"\033[1m\033[41m"};
153 QUILL_NODISCARD QUILL_ATTRIBUTE_COLD
static bool _supports_colour_output() noexcept
160 auto* env_p = std::getenv(
"TERM");
162 if (env_p ==
nullptr)
167 static constexpr
char const* terms[] = {
168 "ansi",
"color",
"console",
"cygwin",
"gnome",
169 "konsole",
"kterm",
"linux",
"msys",
"putty",
170 "rxvt",
"screen",
"vt100",
"xterm",
"tmux",
171 "terminator",
"alacritty",
"gnome-terminal",
"xfce4-terminal",
"lxterminal",
172 "mate-terminal",
"uxterm",
"eterm",
"tilix",
"rxvt-unicode",
176 for (
char const* term : terms)
178 if (std::strstr(env_p, term) !=
nullptr)
191 QUILL_NODISCARD QUILL_ATTRIBUTE_COLD
static bool _is_terminal_output(FILE* file) noexcept
194 return _isatty(_fileno(file)) != 0;
196 return ::isatty(fileno(file)) != 0;
202 QUILL_ATTRIBUTE_COLD
bool _activate_ansi_support(FILE* file)
const noexcept
204 if (!_colour_output_supported)
210 auto const out_handle =
reinterpret_cast<HANDLE
>(_get_osfhandle(_fileno(file)));
211 if (out_handle == INVALID_HANDLE_VALUE)
217 if (!GetConsoleMode(out_handle, &dw_mode))
222 dw_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
223 dw_mode |= ENABLE_PROCESSED_OUTPUT;
225 return SetConsoleMode(out_handle, dw_mode) != 0;
230 void _configure_colour_support(FILE* file, ColourMode colour_mode) noexcept
232 if (colour_mode == ColourMode::Always)
234 _colour_output_supported =
true;
236 else if (colour_mode == ColourMode::Automatic)
238 _colour_output_supported = _is_terminal_output(file) && _supports_colour_output();
242 _colour_output_supported =
false;
247 if ((colour_mode == ColourMode::Automatic) && !_activate_ansi_support(file))
249 _colour_output_supported =
false;
251 else if (colour_mode == ColourMode::Always)
253 static_cast<void>(_activate_ansi_support(file));
259 static_assert(static_cast<size_t>(LogLevel::None) < LogLevelCount,
260 "_log_level_colours must be large enough to be indexed by every LogLevel value");
262 std::array<std::string_view, LogLevelCount> _log_level_colours;
263 bool _colours_enabled{
true};
264 bool _colour_output_supported{
false};
291 QUILL_ATTRIBUTE_COLD
void set_colour_mode(ColourMode colour_mode) { _colour_mode = colour_mode; }
305 QUILL_ATTRIBUTE_COLD
void set_stream(std::string
const& stream) { _stream = stream; }
318 _override_pattern_formatter_options = options;
323 QUILL_NODISCARD ColourMode colour_mode()
const noexcept {
return _colour_mode; }
324 QUILL_NODISCARD std::string
const& stream()
const noexcept {
return _stream; }
325 QUILL_NODISCARD std::optional<PatternFormatterOptions>
const& override_pattern_formatter_options()
const noexcept
327 return _override_pattern_formatter_options;
333 std::optional<PatternFormatterOptions> _override_pattern_formatter_options;
334 std::string _stream =
"stdout";
336 ColourMode _colour_mode{ColourMode::Automatic};
349 :
StreamSink{config.stream(),
nullptr, config.override_pattern_formatter_options(),
350 std::move(file_event_notifier)},
353 if (QUILL_UNLIKELY(_config.stream() !=
"stdout" && _config.stream() !=
"stderr"))
356 QuillError{
"Invalid stream name in ConsoleSink constructor, must be 'stdout' or 'stderr'"});
359 if (_config.colour_mode() == ConsoleSinkConfig::ColourMode::Never)
361 _config._colours.set_colours_enabled(
false);
365 _config._colours._configure_colour_support(_file, _config.colour_mode());
366 _config._colours.set_colours_enabled(
true);
388 std::string_view thread_id, std::string_view thread_name,
389 std::string
const& process_id, std::string_view logger_name,
390 LogLevel log_level, std::string_view log_level_description,
391 std::string_view log_level_short_code,
392 std::vector<std::pair<std::string, std::string>>
const* named_args,
393 std::string_view log_message, std::string_view log_statement)
override 395 if (_config.colours().colours_enabled())
398 std::string_view
const colour_code = _config.colours().log_level_colour(log_level);
399 safe_fwrite(colour_code.data(),
sizeof(char), colour_code.size(), _file);
403 logger_name, log_level, log_level_description, log_level_short_code,
404 named_args, log_message, log_statement);
407 safe_fwrite(ConsoleSinkConfig::Colours::reset.data(),
sizeof(
char),
408 ConsoleSinkConfig::Colours::reset.size(), _file);
414 logger_name, log_level, log_level_description, log_level_short_code,
415 named_args, log_message, log_statement);
QUILL_ATTRIBUTE_HOT void write_log(MacroMetadata const *, uint64_t, std::string_view, std::string_view, std::string const &, std::string_view, LogLevel, std::string_view, std::string_view, std::vector< std::pair< std::string, std::string >> const *, std::string_view, std::string_view log_statement) override
Writes a formatted log message to the stream.
Definition: StreamSink.h:123
QUILL_ATTRIBUTE_COLD void set_stream(std::string const &stream)
Sets the output stream for console logging.
Definition: ConsoleSink.h:305
Definition: ConsoleSink.h:340
QUILL_ATTRIBUTE_COLD void set_colour_mode(ColourMode colour_mode)
Sets the colour mode for console output.
Definition: ConsoleSink.h:291
QUILL_NODISCARD Colours const & colours() const noexcept
Getters.
Definition: ConsoleSink.h:322
void assign_colour_to_log_level(LogLevel log_level, std::string_view colour) noexcept
Sets a custom colour per log level.
Definition: ConsoleSink.h:85
QUILL_ATTRIBUTE_COLD void set_override_pattern_formatter_options(std::optional< PatternFormatterOptions > const &options)
Sets custom pattern formatter options for this sink.
Definition: ConsoleSink.h:316
Definition: ConsoleSink.h:43
void apply_default_colours() noexcept
Sets some default colours for terminal.
Definition: ConsoleSink.h:66
QUILL_NODISCARD bool colours_enabled() const noexcept
Definition: ConsoleSink.h:97
QUILL_NODISCARD std::string_view log_level_colour(LogLevel log_level) const noexcept
The colour for the given log level.
Definition: ConsoleSink.h:107
QUILL_ATTRIBUTE_HOT void write_log(MacroMetadata const *log_metadata, uint64_t log_timestamp, std::string_view thread_id, std::string_view thread_name, std::string const &process_id, std::string_view logger_name, LogLevel log_level, std::string_view log_level_description, std::string_view log_level_short_code, std::vector< std::pair< std::string, std::string >> const *named_args, std::string_view log_message, std::string_view log_statement) override
Write a formatted log message to the stream.
Definition: ConsoleSink.h:387
Represents console colours.
Definition: ConsoleSink.h:56
custom exception
Definition: QuillError.h:47
QUILL_ATTRIBUTE_COLD void set_colours(Colours colours)
Sets custom colours for each log level.
Definition: ConsoleSink.h:275
Notifies on file events by calling the appropriate callback.
Definition: StreamSink.h:68
ConsoleSink(ConsoleSinkConfig const &config=ConsoleSinkConfig{}, FileEventNotifier file_event_notifier=FileEventNotifier{})
Constructor with custom ConsoleColours config.
Definition: ConsoleSink.h:347
StreamSink class for handling log messages.
Definition: StreamSink.h:80