Log: Add option coloured variants
This commit is contained in:
parent
596cca9be2
commit
3f41dcc97d
|
@ -44,36 +44,24 @@ static void UnregisterCallback(CallbackFunctionType callbackFunction, void* pUse
|
|||
const std::unique_lock<std::mutex>& lock);
|
||||
|
||||
static bool FilterTest(Channel channel, Level level);
|
||||
static void ExecuteCallbacks(Channel channel, const char* functionName, Level level, std::string_view message,
|
||||
const std::unique_lock<std::mutex>& lock);
|
||||
static void FormatLogMessageForDisplay(fmt::memory_buffer& buffer, const char* channelName, const char* functionName,
|
||||
Level level, std::string_view message, bool timestamp, bool ansi_color_code);
|
||||
static void ConsoleOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level,
|
||||
static void ExecuteCallbacks(MessageCategory cat, const char* functionName, std::string_view message);
|
||||
static void FormatLogMessageForDisplay(fmt::memory_buffer& buffer, MessageCategory cat, const char* functionName,
|
||||
std::string_view message, bool timestamp, bool ansi_color_code);
|
||||
static void ConsoleOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName,
|
||||
std::string_view message);
|
||||
static void DebugOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level,
|
||||
static void DebugOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName,
|
||||
std::string_view message);
|
||||
static void FileOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level,
|
||||
static void FileOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName,
|
||||
std::string_view message);
|
||||
template<typename T>
|
||||
static void FormatLogMessageAndPrint(const char* channelName, const char* functionName, Level level,
|
||||
std::string_view message, bool timestamp, bool ansi_color_code, const T& callback);
|
||||
static void FormatLogMessageAndPrint(MessageCategory cat, const char* functionName, std::string_view message,
|
||||
bool timestamp, bool ansi_color_code, const T& callback);
|
||||
#ifdef _WIN32
|
||||
template<typename T>
|
||||
static void FormatLogMessageAndPrintW(const char* channelName, const char* functionName, Level level,
|
||||
std::string_view message, bool timestamp, bool ansi_color_code,
|
||||
const T& callback);
|
||||
static void FormatLogMessageAndPrintW(MessageCategory cat, const char* functionName, std::string_view message,
|
||||
bool timestamp, bool ansi_color_code, const T& callback);
|
||||
#endif
|
||||
|
||||
ALWAYS_INLINE static Channel UnpackLogChannel(PackedChannelAndLevel cat)
|
||||
{
|
||||
return static_cast<Channel>(cat >> 3);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static Level UnpackLogLevel(PackedChannelAndLevel cat)
|
||||
{
|
||||
return static_cast<Level>(cat & 0x7);
|
||||
}
|
||||
|
||||
static constexpr const std::array<char, static_cast<size_t>(Level::MaxCount)> s_log_level_characters = {
|
||||
{'X', 'E', 'W', 'I', 'V', 'D', 'B', 'T'}};
|
||||
|
||||
|
@ -191,31 +179,59 @@ bool Log::IsDebugOutputEnabled()
|
|||
return s_state.debug_output_enabled;
|
||||
}
|
||||
|
||||
void Log::ExecuteCallbacks(Channel channel, const char* functionName, Level level, std::string_view message,
|
||||
const std::unique_lock<std::mutex>& lock)
|
||||
Log::Color Log::GetColorForLevel(Level level)
|
||||
{
|
||||
for (RegisteredCallback& callback : s_state.callbacks)
|
||||
callback.Function(callback.Parameter, s_log_channel_names[static_cast<size_t>(channel)], functionName, level,
|
||||
message);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& buffer, const char* channelName,
|
||||
const char* functionName, Level level,
|
||||
std::string_view message, bool timestamp,
|
||||
bool ansi_color_code)
|
||||
{
|
||||
static constexpr const std::array s_ansi_color_codes = {
|
||||
"\033[0m"sv, // None
|
||||
"\033[1;31m"sv, // Error
|
||||
"\033[1;33m"sv, // Warning
|
||||
"\033[1;37m"sv, // Info
|
||||
"\033[1;32m"sv, // Verbose
|
||||
"\033[0;37m"sv, // Dev
|
||||
"\033[0;32m"sv, // Debug
|
||||
"\033[0;34m"sv, // Trace
|
||||
static constexpr const std::array s_level_colours = {
|
||||
Color::Default, // None
|
||||
Color::StrongRed, // Error
|
||||
Color::StrongYellow, // Warning
|
||||
Color::StrongWhite, // Info
|
||||
Color::StrongGreen, // Verbose
|
||||
Color::White, // Dev
|
||||
Color::Green, // Debug
|
||||
Color::Blue, // Trace
|
||||
};
|
||||
|
||||
std::string_view color_start = ansi_color_code ? s_ansi_color_codes[static_cast<size_t>(level)] : ""sv;
|
||||
return s_level_colours[static_cast<size_t>(level)];
|
||||
}
|
||||
|
||||
void Log::ExecuteCallbacks(MessageCategory cat, const char* functionName, std::string_view message)
|
||||
{
|
||||
for (RegisteredCallback& callback : s_state.callbacks)
|
||||
callback.Function(callback.Parameter, cat, functionName, message);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& buffer, MessageCategory cat,
|
||||
const char* functionName, std::string_view message,
|
||||
bool timestamp, bool ansi_color_code)
|
||||
{
|
||||
static constexpr const std::array s_ansi_color_codes = {
|
||||
"\033[0m"sv, // default
|
||||
"\033[30m\033[1m"sv, // black
|
||||
"\033[32m"sv, // green
|
||||
"\033[31m"sv, // red
|
||||
"\033[34m"sv, // blue
|
||||
"\033[35m"sv, // magenta
|
||||
"\033[38;5;217m"sv, // orange
|
||||
"\033[36m"sv, // cyan
|
||||
"\033[33m"sv, // yellow
|
||||
"\033[37m"sv, // white
|
||||
"\033[30m\033[1m"sv, // strong black
|
||||
"\033[31m\033[1m"sv, // strong red
|
||||
"\033[32m\033[1m"sv, // strong green
|
||||
"\033[34m\033[1m"sv, // strong blue
|
||||
"\033[35m\033[1m"sv, // strong magenta
|
||||
"\033[38;5;202m"sv, // strong orange
|
||||
"\033[36m\033[1m"sv, // strong cyan
|
||||
"\033[33m\033[1m"sv, // strong yellow
|
||||
"\033[37m\033[1m"sv, // strong white
|
||||
};
|
||||
|
||||
const Level level = UnpackLevel(cat);
|
||||
const Color color = (UnpackColor(cat) == Color::Default) ? GetColorForLevel(level) : UnpackColor(cat);
|
||||
const char* channel_name = GetChannelName(UnpackChannel(cat));
|
||||
|
||||
std::string_view color_start = ansi_color_code ? s_ansi_color_codes[static_cast<size_t>(color)] : ""sv;
|
||||
std::string_view color_end = ansi_color_code ? s_ansi_color_codes[0] : ""sv;
|
||||
|
||||
auto appender = std::back_inserter(buffer);
|
||||
|
@ -243,7 +259,7 @@ ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& b
|
|||
else
|
||||
{
|
||||
fmt::format_to(appender, "[{:10.4f}] {}{}/{}: {}{}{}", message_time, color_start,
|
||||
s_log_level_characters[static_cast<size_t>(level)], channelName, sub_message, color_end,
|
||||
s_log_level_characters[static_cast<size_t>(level)], channel_name, sub_message, color_end,
|
||||
end_message);
|
||||
}
|
||||
|
||||
|
@ -263,30 +279,30 @@ ALWAYS_INLINE_RELEASE void Log::FormatLogMessageForDisplay(fmt::memory_buffer& b
|
|||
else
|
||||
{
|
||||
fmt::format_to(appender, "{}{}/{}: {}{}\n", color_start, s_log_level_characters[static_cast<size_t>(level)],
|
||||
channelName, message, color_end);
|
||||
channel_name, message, color_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrint(const char* channelName, const char* functionName, Level level,
|
||||
ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrint(MessageCategory cat, const char* functionName,
|
||||
std::string_view message, bool timestamp, bool ansi_color_code,
|
||||
const T& callback)
|
||||
{
|
||||
fmt::memory_buffer buffer;
|
||||
FormatLogMessageForDisplay(buffer, channelName, functionName, level, message, timestamp, ansi_color_code);
|
||||
FormatLogMessageForDisplay(buffer, cat, functionName, message, timestamp, ansi_color_code);
|
||||
callback(std::string_view(buffer.data(), buffer.size()));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
template<typename T>
|
||||
ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrintW(const char* channelName, const char* functionName,
|
||||
Level level, std::string_view message, bool timestamp,
|
||||
ALWAYS_INLINE_RELEASE void Log::FormatLogMessageAndPrintW(MessageCategory cat, const char* functionName,
|
||||
std::string_view message, bool timestamp,
|
||||
bool ansi_color_code, const T& callback)
|
||||
{
|
||||
fmt::memory_buffer buffer;
|
||||
FormatLogMessageForDisplay(buffer, channelName, functionName, level, message, timestamp, ansi_color_code);
|
||||
FormatLogMessageForDisplay(buffer, cat, functionName, message, timestamp, ansi_color_code);
|
||||
|
||||
// Convert to UTF-16 first so unicode characters display correctly. NT is going to do it
|
||||
// anyway...
|
||||
|
@ -326,7 +342,7 @@ static bool EnableVirtualTerminalProcessing(HANDLE hConsole)
|
|||
|
||||
#endif
|
||||
|
||||
void Log::ConsoleOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level,
|
||||
void Log::ConsoleOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName,
|
||||
std::string_view message)
|
||||
{
|
||||
if (!s_state.console_output_enabled)
|
||||
|
@ -334,29 +350,28 @@ void Log::ConsoleOutputLogCallback(void* pUserParam, const char* channelName, co
|
|||
|
||||
#if defined(_WIN32)
|
||||
FormatLogMessageAndPrintW(
|
||||
channelName, functionName, level, message, s_state.console_output_timestamps, true,
|
||||
[level](const std::wstring_view& message) {
|
||||
HANDLE hOutput = (level <= Level::Warning) ? s_state.hConsoleStdErr : s_state.hConsoleStdOut;
|
||||
cat, functionName, message, s_state.console_output_timestamps, true, [cat](const std::wstring_view& message) {
|
||||
HANDLE hOutput = (UnpackLevel(cat) <= Level::Warning) ? s_state.hConsoleStdErr : s_state.hConsoleStdOut;
|
||||
DWORD chars_written;
|
||||
WriteConsoleW(hOutput, message.data(), static_cast<DWORD>(message.length()), &chars_written, nullptr);
|
||||
});
|
||||
#elif !defined(__ANDROID__)
|
||||
FormatLogMessageAndPrint(channelName, functionName, level, message, s_state.console_output_timestamps, true,
|
||||
[level](std::string_view message) {
|
||||
const int outputFd = (level <= Log::Level::Warning) ? STDERR_FILENO : STDOUT_FILENO;
|
||||
write(outputFd, message.data(), message.length());
|
||||
});
|
||||
FormatLogMessageAndPrint(
|
||||
cat, functionName, message, s_state.console_output_timestamps, true, [cat](std::string_view message) {
|
||||
const int outputFd = (UnpackLevel(cat) <= Log::Level::Warning) ? STDERR_FILENO : STDOUT_FILENO;
|
||||
write(outputFd, message.data(), message.length());
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void Log::DebugOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level,
|
||||
void Log::DebugOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName,
|
||||
std::string_view message)
|
||||
{
|
||||
if (!s_state.debug_output_enabled)
|
||||
return;
|
||||
|
||||
#if defined(_WIN32)
|
||||
FormatLogMessageAndPrintW(channelName, functionName, level, message, false, false,
|
||||
FormatLogMessageAndPrintW(cat, functionName, message, false, false,
|
||||
[](const std::wstring_view& message) { OutputDebugStringW(message.data()); });
|
||||
#elif defined(__ANDROID__)
|
||||
if (message.empty())
|
||||
|
@ -373,8 +388,8 @@ void Log::DebugOutputLogCallback(void* pUserParam, const char* channelName, cons
|
|||
ANDROID_LOG_DEBUG, // Trace
|
||||
};
|
||||
|
||||
__android_log_print(logPriority[static_cast<size_t>(level)], channelName, "%.*s", static_cast<int>(message.length()),
|
||||
message.data());
|
||||
__android_log_print(logPriority[static_cast<size_t>(UnpackLevel(cat))], GetChannelName(UnpackChannel(cat)), "%.*s",
|
||||
static_cast<int>(message.length()), message.data());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -471,13 +486,13 @@ void Log::SetDebugOutputParams(bool enabled)
|
|||
UnregisterCallback(DebugOutputLogCallback, nullptr, lock);
|
||||
}
|
||||
|
||||
void Log::FileOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, Level level,
|
||||
void Log::FileOutputLogCallback(void* pUserParam, MessageCategory cat, const char* functionName,
|
||||
std::string_view message)
|
||||
{
|
||||
if (!s_state.file_output_enabled)
|
||||
return;
|
||||
|
||||
FormatLogMessageAndPrint(channelName, functionName, level, message, true, false, [](std::string_view message) {
|
||||
FormatLogMessageAndPrint(cat, functionName, message, true, false, [](std::string_view message) {
|
||||
std::fwrite(message.data(), 1, message.size(), s_state.file_handle.get());
|
||||
std::fflush(s_state.file_handle.get());
|
||||
});
|
||||
|
@ -494,8 +509,8 @@ void Log::SetFileOutputParams(bool enabled, const char* filename, bool timestamp
|
|||
s_state.file_handle = FileSystem::OpenManagedCFile(filename, "wb");
|
||||
if (!s_state.file_handle) [[unlikely]]
|
||||
{
|
||||
ExecuteCallbacks(Log::Channel::Log, __FUNCTION__, Level::Error,
|
||||
TinyString::from_format("Failed to open log file '{}'", filename), lock);
|
||||
ExecuteCallbacks(PackCategory(Channel::Log, Level::Error, Color::Default), nullptr,
|
||||
TinyString::from_format("Failed to open log file '{}'", filename));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -535,57 +550,54 @@ void Log::SetLogChannelEnabled(Channel channel, bool enabled)
|
|||
s_state.log_channels_enabled[static_cast<size_t>(channel)] = enabled;
|
||||
}
|
||||
|
||||
const char* Log::GetChannelName(Channel channel)
|
||||
{
|
||||
return s_log_channel_names[static_cast<size_t>(channel)];
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE bool Log::FilterTest(Channel channel, Level level)
|
||||
{
|
||||
return (level <= s_state.log_level && s_state.log_channels_enabled[static_cast<size_t>(channel)]);
|
||||
}
|
||||
|
||||
void Log::Write(PackedChannelAndLevel cat, std::string_view message)
|
||||
void Log::Write(MessageCategory cat, std::string_view message)
|
||||
{
|
||||
const Channel channel = UnpackLogChannel(cat);
|
||||
const Level level = UnpackLogLevel(cat);
|
||||
if (!FilterTest(channel, level))
|
||||
if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat)))
|
||||
return;
|
||||
|
||||
std::unique_lock lock(s_state.callbacks_mutex);
|
||||
ExecuteCallbacks(channel, nullptr, level, message, lock);
|
||||
ExecuteCallbacks(cat, nullptr, message);
|
||||
}
|
||||
|
||||
void Log::Write(PackedChannelAndLevel cat, const char* functionName, std::string_view message)
|
||||
void Log::Write(MessageCategory cat, const char* functionName, std::string_view message)
|
||||
{
|
||||
const Channel channel = UnpackLogChannel(cat);
|
||||
const Level level = UnpackLogLevel(cat);
|
||||
if (!FilterTest(channel, level))
|
||||
if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat)))
|
||||
return;
|
||||
|
||||
std::unique_lock lock(s_state.callbacks_mutex);
|
||||
ExecuteCallbacks(channel, functionName, level, message, lock);
|
||||
ExecuteCallbacks(cat, functionName, message);
|
||||
}
|
||||
|
||||
void Log::WriteFmtArgs(PackedChannelAndLevel cat, fmt::string_view fmt, fmt::format_args args)
|
||||
void Log::WriteFmtArgs(MessageCategory cat, fmt::string_view fmt, fmt::format_args args)
|
||||
{
|
||||
const Channel channel = UnpackLogChannel(cat);
|
||||
const Level level = UnpackLogLevel(cat);
|
||||
if (!FilterTest(channel, level))
|
||||
if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat)))
|
||||
return;
|
||||
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::vformat_to(std::back_inserter(buffer), fmt, args);
|
||||
|
||||
std::unique_lock lock(s_state.callbacks_mutex);
|
||||
ExecuteCallbacks(channel, nullptr, level, std::string_view(buffer.data(), buffer.size()), lock);
|
||||
ExecuteCallbacks(cat, nullptr, std::string_view(buffer.data(), buffer.size()));
|
||||
}
|
||||
|
||||
void Log::WriteFmtArgs(PackedChannelAndLevel cat, const char* functionName, fmt::string_view fmt, fmt::format_args args)
|
||||
void Log::WriteFmtArgs(MessageCategory cat, const char* functionName, fmt::string_view fmt, fmt::format_args args)
|
||||
{
|
||||
const Channel channel = UnpackLogChannel(cat);
|
||||
const Level level = UnpackLogLevel(cat);
|
||||
if (!FilterTest(channel, level))
|
||||
if (!FilterTest(UnpackChannel(cat), UnpackLevel(cat)))
|
||||
return;
|
||||
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::vformat_to(std::back_inserter(buffer), fmt, args);
|
||||
|
||||
std::unique_lock lock(s_state.callbacks_mutex);
|
||||
ExecuteCallbacks(channel, functionName, level, std::string_view(buffer.data(), buffer.size()), lock);
|
||||
ExecuteCallbacks(cat, functionName, std::string_view(buffer.data(), buffer.size()));
|
||||
}
|
||||
|
|
122
src/common/log.h
122
src/common/log.h
|
@ -29,6 +29,31 @@ enum class Level : u32
|
|||
MaxCount
|
||||
};
|
||||
|
||||
enum class Color : u32
|
||||
{
|
||||
Default,
|
||||
Black,
|
||||
Green,
|
||||
Red,
|
||||
Blue,
|
||||
Magenta,
|
||||
Orange,
|
||||
Cyan,
|
||||
Yellow,
|
||||
White,
|
||||
StrongBlack,
|
||||
StrongRed,
|
||||
StrongGreen,
|
||||
StrongBlue,
|
||||
StrongMagenta,
|
||||
StrongOrange,
|
||||
StrongCyan,
|
||||
StrongYellow,
|
||||
StrongWhite,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class Channel : u32
|
||||
{
|
||||
#define LOG_CHANNEL_ENUM(X) X,
|
||||
|
@ -38,8 +63,28 @@ enum class Channel : u32
|
|||
MaxCount
|
||||
};
|
||||
|
||||
// Packs a level and channel into one 16-bit number.
|
||||
using MessageCategory = u32;
|
||||
[[maybe_unused]] ALWAYS_INLINE static constexpr u32 PackCategory(Channel channel, Level level, Color colour)
|
||||
{
|
||||
return ((static_cast<MessageCategory>(colour) << 10) | (static_cast<MessageCategory>(channel) << 3) |
|
||||
static_cast<MessageCategory>(level));
|
||||
}
|
||||
[[maybe_unused]] ALWAYS_INLINE static constexpr Color UnpackColor(MessageCategory cat)
|
||||
{
|
||||
return static_cast<Color>((cat >> 10) & 0x1f);
|
||||
}
|
||||
[[maybe_unused]] ALWAYS_INLINE static constexpr Channel UnpackChannel(MessageCategory cat)
|
||||
{
|
||||
return static_cast<Channel>((cat >> 3) & 0x7f);
|
||||
}
|
||||
[[maybe_unused]] ALWAYS_INLINE static constexpr Level UnpackLevel(MessageCategory cat)
|
||||
{
|
||||
return static_cast<Level>(cat & 0x7);
|
||||
}
|
||||
|
||||
// log message callback type
|
||||
using CallbackFunctionType = void (*)(void* pUserParam, const char* channelName, const char* functionName, Level level,
|
||||
using CallbackFunctionType = void (*)(void* pUserParam, MessageCategory category, const char* functionName,
|
||||
std::string_view message);
|
||||
|
||||
// registers a log callback
|
||||
|
@ -79,41 +124,65 @@ void SetLogLevel(Level level);
|
|||
// Sets global filter, any messages from these channels won't be sent to any of the logging sinks.
|
||||
void SetLogChannelEnabled(Channel channel, bool enabled);
|
||||
|
||||
// Packs a level and channel into one 16-bit number.
|
||||
using PackedChannelAndLevel = u32;
|
||||
[[maybe_unused]] ALWAYS_INLINE static u32 PackChannelAndLevel(Channel channel, Level level)
|
||||
{
|
||||
return ((static_cast<PackedChannelAndLevel>(channel) << 3) | static_cast<PackedChannelAndLevel>(level));
|
||||
}
|
||||
// Returns the name of the specified log channel.
|
||||
const char* GetChannelName(Channel channel);
|
||||
|
||||
// Returns the default colour for a log level.
|
||||
Color GetColorForLevel(Level level);
|
||||
|
||||
// writes a message to the log
|
||||
void Write(PackedChannelAndLevel cat, std::string_view message);
|
||||
void Write(PackedChannelAndLevel cat, const char* functionName, std::string_view message);
|
||||
void WriteFmtArgs(PackedChannelAndLevel cat, fmt::string_view fmt, fmt::format_args args);
|
||||
void WriteFmtArgs(PackedChannelAndLevel cat, const char* functionName, fmt::string_view fmt, fmt::format_args args);
|
||||
void Write(MessageCategory cat, std::string_view message);
|
||||
void Write(MessageCategory cat, const char* functionName, std::string_view message);
|
||||
void WriteFmtArgs(MessageCategory cat, fmt::string_view fmt, fmt::format_args args);
|
||||
void WriteFmtArgs(MessageCategory cat, const char* functionName, fmt::string_view fmt, fmt::format_args args);
|
||||
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, Level level, std::string_view message)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
Write(PackChannelAndLevel(channel, level), message);
|
||||
Write(PackCategory(channel, level, Color::Default), message);
|
||||
}
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level, std::string_view message)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
Write(PackChannelAndLevel(channel, level), functionName, message);
|
||||
Write(PackCategory(channel, level, Color::Default), functionName, message);
|
||||
}
|
||||
template<typename... T>
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, Level level, fmt::format_string<T...> fmt, T&&... args)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
WriteFmtArgs(PackChannelAndLevel(channel, level), fmt, fmt::make_format_args(args...));
|
||||
WriteFmtArgs(PackCategory(channel, level, Color::Default), fmt, fmt::make_format_args(args...));
|
||||
}
|
||||
template<typename... T>
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level,
|
||||
fmt::format_string<T...> fmt, T&&... args)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
WriteFmtArgs(PackChannelAndLevel(channel, level), functionName, fmt, fmt::make_format_args(args...));
|
||||
WriteFmtArgs(PackCategory(channel, level, Color::Default), functionName, fmt, fmt::make_format_args(args...));
|
||||
}
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, Level level, Color colour, std::string_view message)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
Write(PackCategory(channel, level, colour), message);
|
||||
}
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level, Color colour,
|
||||
std::string_view message)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
Write(PackCategory(channel, level, colour), functionName, message);
|
||||
}
|
||||
template<typename... T>
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, Level level, Color colour, fmt::format_string<T...> fmt,
|
||||
T&&... args)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
WriteFmtArgs(PackCategory(channel, level, colour), fmt, fmt::make_format_args(args...));
|
||||
}
|
||||
template<typename... T>
|
||||
ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, Level level, Color colour,
|
||||
fmt::format_string<T...> fmt, T&&... args)
|
||||
{
|
||||
if (level <= GetLogLevel()) [[unlikely]]
|
||||
WriteFmtArgs(PackCategory(channel, level, colour), functionName, fmt, fmt::make_format_args(args...));
|
||||
}
|
||||
} // namespace Log
|
||||
|
||||
|
@ -139,3 +208,26 @@ ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, L
|
|||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#define ERROR_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Error, Log::Color::colour, __VA_ARGS__)
|
||||
#define WARNING_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Warning, Log::Color::colour, __VA_ARGS__)
|
||||
#define INFO_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Info, Log::Color::colour, __VA_ARGS__)
|
||||
#define VERBOSE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Verbose, Log::Color::colour, __VA_ARGS__)
|
||||
#define DEV_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Dev, Log::Color::colour, __VA_ARGS__)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Debug, Log::Color::colour, __VA_ARGS__)
|
||||
#define TRACE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Trace, Log::Color::colour,__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_COLOR_LOG(colour, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define TRACE_COLOR_LOG(colour, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
{
|
||||
if (!stop_on_error)
|
||||
{
|
||||
Log::WriteFmtArgs(Log::PackChannelAndLevel(Log::Channel::Cheats, Log::Level::Warning), fmt,
|
||||
Log::WriteFmtArgs(Log::PackCategory(Log::Channel::Cheats, Log::Level::Warning, Log::Color::StrongOrange), fmt,
|
||||
fmt::make_format_args(args...));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -254,7 +254,7 @@ void LogWindow::onSaveTriggered()
|
|||
tr("Log was written to %1.\n").arg(path));
|
||||
}
|
||||
|
||||
void LogWindow::logCallback(void* pUserParam, const char* channelName, const char* functionName, Log::Level level,
|
||||
void LogWindow::logCallback(void* pUserParam, Log::MessageCategory cat, const char* functionName,
|
||||
std::string_view message)
|
||||
{
|
||||
LogWindow* this_ptr = static_cast<LogWindow*>(pUserParam);
|
||||
|
@ -267,16 +267,17 @@ void LogWindow::logCallback(void* pUserParam, const char* channelName, const cha
|
|||
qmessage.append(QUtf8StringView(message.data(), message.length()));
|
||||
qmessage.append(QChar('\n'));
|
||||
|
||||
const QLatin1StringView qchannel((level <= Log::Level::Warning) ? functionName : channelName);
|
||||
const QLatin1StringView qchannel(
|
||||
(Log::UnpackLevel(cat) <= Log::Level::Warning) ? functionName : Log::GetChannelName(Log::UnpackChannel(cat)));
|
||||
|
||||
if (QThread::isMainThread())
|
||||
{
|
||||
this_ptr->appendMessage(qchannel, static_cast<u32>(level), qmessage);
|
||||
this_ptr->appendMessage(qchannel, static_cast<u32>(cat), qmessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(this_ptr, "appendMessage", Qt::QueuedConnection,
|
||||
Q_ARG(const QLatin1StringView&, qchannel), Q_ARG(quint32, static_cast<u32>(level)),
|
||||
Q_ARG(const QLatin1StringView&, qchannel), Q_ARG(quint32, static_cast<u32>(cat)),
|
||||
Q_ARG(const QString&, qmessage));
|
||||
}
|
||||
}
|
||||
|
@ -304,7 +305,7 @@ void LogWindow::changeEvent(QEvent* event)
|
|||
QMainWindow::changeEvent(event);
|
||||
}
|
||||
|
||||
void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 level, const QString& message)
|
||||
void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 cat, const QString& message)
|
||||
{
|
||||
QTextCursor temp_cursor = m_text->textCursor();
|
||||
QScrollBar* scrollbar = m_text->verticalScrollBar();
|
||||
|
@ -316,28 +317,50 @@ void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 level, c
|
|||
{
|
||||
static constexpr const QChar level_characters[static_cast<size_t>(Log::Level::MaxCount)] = {'X', 'E', 'W', 'I',
|
||||
'V', 'D', 'B', 'T'};
|
||||
static constexpr const QColor level_colors[2][static_cast<size_t>(Log::Level::MaxCount)] = {
|
||||
static constexpr const QColor message_colors[2][static_cast<size_t>(Log::Color::MaxCount)] = {
|
||||
// Light theme
|
||||
{
|
||||
// Light theme
|
||||
QColor(0, 0, 0), // NONE
|
||||
QColor(0x80, 0x00, 0x00), // ERROR, Red Intensity
|
||||
QColor(0xb4, 0xb4, 0x00), // WARNING, Yellow Intensity
|
||||
QColor(0x0d, 0x0d, 0x0d), // INFO, White Intensity
|
||||
QColor(0x00, 0x80, 0x00), // VERBOSE, Green Intensity
|
||||
QColor(0x70, 0x70, 0x70), // DEV, White
|
||||
QColor(0xec, 0x5e, 0xf1), // DEBUG, Green
|
||||
QColor(0xe9, 0x39, 0xf3), // TRACE, Blue
|
||||
QColor(0x00, 0x00, 0x00), // Default
|
||||
QColor(0x00, 0x00, 0x00), // Black
|
||||
QColor(0x70, 0x00, 0x00), // Red
|
||||
QColor(0xec, 0x5e, 0xf1), // Green
|
||||
QColor(0xe9, 0x39, 0xf3), // Blue
|
||||
QColor(0xA0, 0x00, 0xA0), // Magenta
|
||||
QColor(0xA0, 0x78, 0x00), // Orange
|
||||
QColor(0x80, 0xB4, 0xB4), // Cyan
|
||||
QColor(0xB4, 0xB4, 0x80), // Yellow
|
||||
QColor(0x70, 0x70, 0x70), // White
|
||||
QColor(0x00, 0x00, 0x00), // StrongBlack
|
||||
QColor(0x80, 0x00, 0x00), // StrongRed
|
||||
QColor(0x00, 0x80, 0x00), // StrongGreen
|
||||
QColor(0x00, 0x00, 0x80), // StrongBlue
|
||||
QColor(0xA0, 0x00, 0xA0), // StrongMagenta
|
||||
QColor(0xA0, 0x78, 0x00), // StrongOrange
|
||||
QColor(0x80, 0xB4, 0xB4), // StrongCyan
|
||||
QColor(0xb4, 0xb4, 0x00), // StrongYellow
|
||||
QColor(0x0D, 0x0d, 0x0D) // StrongWhite
|
||||
},
|
||||
// Dark theme
|
||||
{
|
||||
// Dark theme
|
||||
QColor(255, 255, 255), // NONE
|
||||
QColor(0xE7, 0x48, 0x56), // ERROR, Red Intensity
|
||||
QColor(0xF9, 0xF1, 0xA5), // WARNING, Yellow Intensity
|
||||
QColor(0xF2, 0xF2, 0xF2), // INFO, White Intensity
|
||||
QColor(0x16, 0xC6, 0x0C), // VERBOSE, Green Intensity
|
||||
QColor(0xCC, 0xCC, 0xCC), // DEV, White
|
||||
QColor(0x13, 0xA1, 0x0E), // DEBUG, Green
|
||||
QColor(0x00, 0x37, 0xDA), // TRACE, Blue
|
||||
QColor(0xD0, 0xD0, 0xD0), // Default
|
||||
QColor(0xFF, 0xFF, 0xFF), // Black
|
||||
QColor(0xB4, 0x00, 0x00), // Red
|
||||
QColor(0x13, 0xA1, 0x0E), // Green
|
||||
QColor(0x00, 0x37, 0xDA), // Blue
|
||||
QColor(0xA0, 0x00, 0xA0), // Magenta
|
||||
QColor(0xA0, 0x78, 0x00), // Orange
|
||||
QColor(0x80, 0xB4, 0xB4), // Cyan
|
||||
QColor(0xB4, 0xB4, 0x80), // Yellow
|
||||
QColor(0xCC, 0xCC, 0xCC), // White
|
||||
QColor(0xFF, 0xFF, 0xFF), // StrongBlack
|
||||
QColor(0xE7, 0x48, 0x56), // StrongRed
|
||||
QColor(0x16, 0xC6, 0x0C), // StrongGreen
|
||||
QColor(0x20, 0x20, 0xCC), // StrongBlue
|
||||
QColor(0xA0, 0x00, 0xA0), // StrongMagenta
|
||||
QColor(0xB4, 0x96, 0x00), // StrongOrange
|
||||
QColor(0x80, 0xB4, 0xB4), // StrongCyan
|
||||
QColor(0xF9, 0xF1, 0xA5), // StrongYellow
|
||||
QColor(0xFF, 0xFF, 0xFF), // StrongWhite
|
||||
},
|
||||
};
|
||||
static constexpr const QColor timestamp_color[2] = {QColor(0x60, 0x60, 0x60), QColor(0xcc, 0xcc, 0xcc)};
|
||||
|
@ -355,15 +378,20 @@ void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 level, c
|
|||
temp_cursor.insertText(qtimestamp);
|
||||
}
|
||||
|
||||
const QString qchannel = (level <= static_cast<u32>(Log::Level::Warning)) ?
|
||||
QStringLiteral("%1(%2): ").arg(level_characters[level]).arg(channel) :
|
||||
QStringLiteral("%1/%2: ").arg(level_characters[level]).arg(channel);
|
||||
const Log::Level level = Log::UnpackLevel(static_cast<Log::MessageCategory>(cat));
|
||||
const Log::Color color = (Log::UnpackColor(static_cast<Log::MessageCategory>(cat)) == Log::Color::Default) ?
|
||||
Log::GetColorForLevel(level) :
|
||||
Log::UnpackColor(static_cast<Log::MessageCategory>(cat));
|
||||
const QString qchannel =
|
||||
(level <= Log::Level::Warning) ?
|
||||
QStringLiteral("%1(%2): ").arg(level_characters[static_cast<size_t>(level)]).arg(channel) :
|
||||
QStringLiteral("%1/%2: ").arg(level_characters[static_cast<size_t>(level)]).arg(channel);
|
||||
format.setForeground(QBrush(channel_color[dark]));
|
||||
temp_cursor.setCharFormat(format);
|
||||
temp_cursor.insertText(qchannel);
|
||||
|
||||
// message has \n already
|
||||
format.setForeground(QBrush(level_colors[dark][level]));
|
||||
format.setForeground(QBrush(message_colors[dark][static_cast<size_t>(color)]));
|
||||
temp_cursor.setCharFormat(format);
|
||||
temp_cursor.insertText(message);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ private:
|
|||
void updateLogLevelUi();
|
||||
void setLogLevel(Log::Level level);
|
||||
|
||||
static void logCallback(void* pUserParam, const char* channelName, const char* functionName, Log::Level level,
|
||||
static void logCallback(void* pUserParam, Log::MessageCategory cat, const char* functionName,
|
||||
std::string_view message);
|
||||
|
||||
protected:
|
||||
|
@ -42,7 +42,7 @@ protected:
|
|||
private Q_SLOTS:
|
||||
void onClearTriggered();
|
||||
void onSaveTriggered();
|
||||
void appendMessage(const QLatin1StringView& channel, quint32 level, const QString& message);
|
||||
void appendMessage(const QLatin1StringView& channel, quint32 cat, const QString& message);
|
||||
|
||||
private:
|
||||
static constexpr int DEFAULT_WIDTH = 750;
|
||||
|
|
Loading…
Reference in New Issue