-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add console_log and file_log classes.
- Loading branch information
Showing
13 changed files
with
360 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// SPDX-FileCopyrightText: 2023 C. J. Howard | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#include <engine/debug/console-log.hpp> | ||
#include <engine/debug/log.hpp> | ||
#include <engine/debug/logger.hpp> | ||
#include <engine/debug/contract.hpp> | ||
#include <algorithm> | ||
#include <filesystem> | ||
#include <format> | ||
#include <iostream> | ||
#include <syncstream> | ||
|
||
#if defined(_WIN32) | ||
#define WIN32_LEAN_AND_MEAN | ||
#include <windows.h> | ||
#endif | ||
|
||
namespace | ||
{ | ||
/// Maps log message severity to ANSI color codes. | ||
const char* console_log_colors[] = | ||
{ | ||
"\33[37m", // trace: FG_WHITE | ||
"\33[34;1m", // debug: FG_BRIGHT_BLUE | ||
"\33[32;1m", // info: FG_BRIGHT_GREEN | ||
"\33[33m", // warning: FG_YELLOW | ||
"\33[31m", // error: FG_RED | ||
"\33[37;\33[41;1m" // fatal: FG_WHITE, BG_BRIGHT_RED | ||
}; | ||
|
||
/// ANSI color reset code. | ||
const char* ansi_reset = "\33[0m"; | ||
|
||
#if defined(_WIN32) | ||
|
||
/// Enables UTF-8 output. | ||
void enable_utf8() | ||
{ | ||
SetConsoleOutputCP(CP_UTF8); | ||
} | ||
|
||
/// Enables VT100 virtual terminal sequences. | ||
void enable_vt100() | ||
{ | ||
DWORD mode = 0; | ||
HANDLE std_output_handle = GetStdHandle(STD_OUTPUT_HANDLE); | ||
GetConsoleMode(std_output_handle, &mode); | ||
SetConsoleMode(std_output_handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); | ||
} | ||
|
||
/// Disables VT100 virtual terminal sequences. | ||
void disable_vt100() | ||
{ | ||
DWORD mode = 0; | ||
HANDLE std_output_handle = GetStdHandle(STD_OUTPUT_HANDLE); | ||
GetConsoleMode(std_output_handle, &mode); | ||
SetConsoleMode(std_output_handle, mode & (~ENABLE_VIRTUAL_TERMINAL_PROCESSING)); | ||
} | ||
|
||
#endif | ||
} | ||
|
||
namespace debug { | ||
|
||
console_log::console_log() | ||
{ | ||
// Get current time zone | ||
m_time_zone = std::chrono::current_zone(); | ||
|
||
// Subscribe to log messages from default logger | ||
m_message_logged_subscription = default_logger().message_logged_channel().subscribe | ||
( | ||
[this](const auto& event) | ||
{ | ||
this->message_logged(event); | ||
} | ||
); | ||
|
||
// Enable UTF-8 output and VT100 sequences on Windows | ||
#if defined(_WIN32) | ||
enable_utf8(); | ||
enable_vt100(); | ||
#endif | ||
|
||
debug::postcondition(m_time_zone); | ||
} | ||
|
||
console_log::~console_log() | ||
{} | ||
|
||
void console_log::message_logged(const message_logged_event& event) | ||
{ | ||
debug::precondition(m_time_zone); | ||
|
||
// Clamp severity index to valid range | ||
const auto severity_index = std::to_underlying(std::clamp(event.severity, log_message_severity::trace, log_message_severity::fatal)); | ||
|
||
// Round time to the millisecond and convert to local time zone | ||
const std::chrono::zoned_time zoned_time{m_time_zone, std::chrono::floor<std::chrono::milliseconds>(event.time)}; | ||
|
||
// Select and synchronize output stream based on severity | ||
std::osyncstream output_stream(event.severity >= log_message_severity::error ? std::cerr : std::cout); | ||
|
||
// Format and output log message | ||
output_stream << std::format | ||
( | ||
"[{:%T}] {}{:7}: {}:{}: {}\33[0m\n", | ||
zoned_time, | ||
console_log_colors[severity_index], | ||
log_message_severity_to_string(event.severity), | ||
std::filesystem::path(event.location.file_name()).filename().string(), | ||
event.location.line(), | ||
event.message | ||
); | ||
} | ||
|
||
} // namespace debug |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// SPDX-FileCopyrightText: 2023 C. J. Howard | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#ifndef ANTKEEPER_DEBUG_CONSOLE_LOG_HPP | ||
#define ANTKEEPER_DEBUG_CONSOLE_LOG_HPP | ||
|
||
#include <engine/debug/log-events.hpp> | ||
#include <engine/event/subscription.hpp> | ||
#include <chrono> | ||
#include <memory> | ||
|
||
namespace debug { | ||
|
||
/// @name Logging | ||
/// @{ | ||
|
||
/** | ||
* Logs messages to the console. | ||
*/ | ||
class console_log | ||
{ | ||
public: | ||
/** | ||
* Opens a console log. | ||
* | ||
* @exception std::runtime_error Failed to get current time zone. | ||
*/ | ||
console_log(); | ||
|
||
/// Closes a console log. | ||
~console_log(); | ||
|
||
private: | ||
void message_logged(const message_logged_event& event); | ||
|
||
console_log(const console_log&) = delete; | ||
console_log(console_log&&) = delete; | ||
console_log& operator=(const console_log&) = delete; | ||
console_log& operator=(console_log&&) = delete; | ||
|
||
const std::chrono::time_zone* m_time_zone{}; | ||
std::shared_ptr<event::subscription> m_message_logged_subscription; | ||
}; | ||
|
||
/// @} | ||
|
||
} // namespace debug | ||
|
||
#endif // ANTKEEPER_DEBUG_CONSOLE_LOG_HPP |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// SPDX-FileCopyrightText: 2023 C. J. Howard | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#include <engine/debug/file-log.hpp> | ||
#include <engine/debug/logger.hpp> | ||
#include <engine/debug/contract.hpp> | ||
#include <algorithm> | ||
#include <filesystem> | ||
#include <format> | ||
#include <syncstream> | ||
#include <stdexcept> | ||
|
||
namespace debug { | ||
|
||
file_log::file_log(const std::filesystem::path& path) | ||
{ | ||
// Open log file | ||
m_output_stream.open(path.string()); | ||
if (!m_output_stream.is_open()) | ||
{ | ||
throw std::runtime_error(std::format("Failed to open log file \"{}\"", path.string())); | ||
} | ||
|
||
// Write log file header | ||
m_output_stream << "time\tseverity\tfile\tline\tthread\tmessage"; | ||
if (!m_output_stream.good()) | ||
{ | ||
throw std::runtime_error(std::format("Failed to write to log file \"{}\"", path.string())); | ||
} | ||
|
||
// Get current time zone | ||
m_time_zone = std::chrono::current_zone(); | ||
|
||
// Subscribe to log messages from default logger | ||
m_message_logged_subscription = default_logger().message_logged_channel().subscribe | ||
( | ||
[this](const auto& event) | ||
{ | ||
this->message_logged(event); | ||
} | ||
); | ||
|
||
debug::postcondition(m_time_zone); | ||
} | ||
|
||
file_log::~file_log() | ||
{} | ||
|
||
void file_log::message_logged(const message_logged_event& event) | ||
{ | ||
debug::precondition(m_time_zone); | ||
|
||
// Round time to the millisecond and convert to local time zone | ||
const std::chrono::zoned_time zoned_time{m_time_zone, std::chrono::floor<std::chrono::milliseconds>(event.time)}; | ||
|
||
// Format and output log message | ||
std::osyncstream(m_output_stream) << std::format | ||
( | ||
"\n{:%FT%T%Ez}\t{}\t{}\t{}\t{}\t{}", | ||
zoned_time, | ||
log_message_severity_to_string(event.severity), | ||
std::filesystem::path(event.location.file_name()).filename().string(), | ||
event.location.line(), | ||
event.thread_id, | ||
event.message | ||
); | ||
} | ||
|
||
} // namespace debug |
Oops, something went wrong.