Logging: Add custom formatter

This commit is contained in:
James Rowe 2017-05-09 21:23:33 -06:00
parent 73658a7629
commit fee58ce458
7 changed files with 225 additions and 5 deletions

View File

@ -16,6 +16,8 @@
#include "game_list_p.h" #include "game_list_p.h"
#include "ui_settings.h" #include "ui_settings.h"
REGISTER_LOGGER("Class Name");
GameList::SearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist) { GameList::SearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist) {
this->gamelist = gamelist; this->gamelist = gamelist;
edit_filter_text_old = ""; edit_filter_text_old = "";
@ -198,6 +200,7 @@ GameList::GameList(GMainWindow* parent) : QWidget{parent} {
watcher = new QFileSystemWatcher(this); watcher = new QFileSystemWatcher(this);
connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory); connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory);
SPDLOG_WARNING("Test! {1} {0}", "world!", "Hello");
this->main_window = parent; this->main_window = parent;
layout = new QVBoxLayout; layout = new QVBoxLayout;
tree_view = new QTreeView; tree_view = new QTreeView;

View File

@ -28,9 +28,11 @@ set(SRCS
break_points.cpp break_points.cpp
file_util.cpp file_util.cpp
hash.cpp hash.cpp
logging/filter.cpp
logging/text_formatter.cpp
logging/backend.cpp logging/backend.cpp
logging/backend_spdlog.cpp
logging/filter.cpp
logging/formatter.cpp
logging/text_formatter.cpp
memory_util.cpp memory_util.cpp
microprofile.cpp microprofile.cpp
misc.cpp misc.cpp
@ -57,10 +59,12 @@ set(HEADERS
file_util.h file_util.h
hash.h hash.h
linear_disk_cache.h linear_disk_cache.h
logging/text_formatter.h
logging/filter.h
logging/log.h
logging/backend.h logging/backend.h
logging/backend_spdlog.h
logging/filter.h
logging/formatter.h
logging/log.h
logging/text_formatter.h
math_util.h math_util.h
memory_util.h memory_util.h
microprofile.h microprofile.h

View File

@ -0,0 +1,87 @@
#include "common/assert.h"
#include "common/logging/backend_spdlog.h"
#include "common/logging/formatter.h"
#include "common/string_util.h"
namespace Log {
SpdLogBackend& SpdLogBackend::instance() {
static SpdLogBackend instance;
return instance;
}
SpdLogBackend::SpdLogBackend() {
// setup the custom citra formatter
spdlog::set_formatter(std::make_shared<Formatter>());
// Define the sinks to be passed to the loggers
// true means truncate file
auto file_sink = std::make_shared<spdlog::sinks::simple_file_sink_mt>("citra_log.txt", true);
#ifdef _WIN32
auto color_sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_mt>();
#else
auto stderr_sink = spdlog::sinks::stderr_sink_mt::instance();
auto color_sink = std::make_shared<spdlog::sinks::ansicolor_sink>(stderr_sink);
#endif
sinks.push_back(file_sink);
sinks.push_back(color_sink);
}
SpdLogBackend::~SpdLogBackend() {
spdlog::drop_all();
}
const std::shared_ptr<spdlog::logger> SpdLogBackend::GetLogger(u32 logger) const {
return loggers[logger];
}
u32 SpdLogBackend::RegisterLogger(const char* class_name) {
loggers.push_back(std::make_shared<spdlog::logger>(class_name, sinks.begin(), sinks.end()));
return loggers.size() - 1;
}
spdlog::level_t GetLevel(Level log_level) {
switch (log_level) {
case Level::Trace:
return spdlog::level::trace;
case Level::Debug:
return spdlog::level::debug;
case Level::Info:
return spdlog::level::info;
case Level::Warning:
return spdlog::level::warn;
case Level::Error:
return spdlog::level::err;
case Level::Critical:
return spdlog::level::critical;
default:
UNREACHABLE();
break;
}
return spdlog::level::off;
}
template <typename Arg1, typename... Args>
void SpdLogMessage(u32 logger, Level log_level, const char* filename, unsigned int line_nr,
const char* function, const char* format, const Arg1& arg, const Args&... args) {
auto log = SpdLogBackend::instance().GetLogger(logger);
fmt::MemoryWriter formatting_buffer;
formatting_buffer << Common::TrimSourcePath(filename) << ':' << function << ':' << line_nr
<< ": " << format;
log->log(GetLevel(log_level), formatting_buffer.c_str(), arg, args...);
}
template <typename T>
void SpdLogMessage(u32 logger, Level log_level, const char* filename, unsigned int line_nr,
const char* function, const T& msg) {
auto log = SpdLogBackend::instance().GetLogger(logger);
fmt::MemoryWriter formatting_buffer;
formatting_buffer << Common::TrimSourcePath(filename) << ':' << function << ':' << line_nr
<< ": " << msg;
log->log(GetLevel(log_level), formatting_buffer.c_str());
}
u32 RegisterLogger(const char* class_name) {
return SpdLogBackend::instance().RegisterLogger(class_name);
}
}; // namespace Log

View File

@ -0,0 +1,27 @@
#include <memory>
#include <vector>
#include <spdlog/spdlog.h>
#include "common/logging/log.h"
namespace Log {
class SpdLogBackend {
public:
static SpdLogBackend& instance();
SpdLogBackend(SpdLogBackend const&) = delete;
void operator=(SpdLogBackend const&) = delete;
u32 RegisterLogger(const char* class_name);
const std::shared_ptr<spdlog::logger> GetLogger(u32 logger) const;
private:
SpdLogBackend();
~SpdLogBackend();
std::vector<std::shared_ptr<spdlog::logger>> loggers;
std::vector<spdlog::sink_ptr> sinks;
};
} // namespace Log

View File

@ -0,0 +1,48 @@
#include <chrono>
#include <string>
#include "common/assert.h"
#include "common/logging/formatter.h"
namespace Log {
Formatter::Formatter() {}
const char* GetLevelName(spdlog::level_t log_level) {
switch (log_level) {
case spdlog::level::trace:
return "Trace";
case spdlog::level::debug:
return "Debug";
case spdlog::level::info:
return "Info";
case spdlog::level::warn:
return "Warn";
case spdlog::level::err:
return "Error";
case spdlog::level::critical:
return "Critical";
default:
UNREACHABLE();
return "UNREACHABLE";
}
}
void Formatter::format(spdlog::details::log_msg& msg) {
using std::chrono::steady_clock;
using std::chrono::duration_cast;
static steady_clock::time_point time_origin = steady_clock::now();
auto timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
unsigned int time_seconds = static_cast<unsigned int>(timestamp.count() / 1000000);
unsigned int time_fractional = static_cast<unsigned int>(timestamp.count() % 1000000);
msg.formatted << '[' << fmt::pad(time_seconds, 4, ' ') << '.'
<< fmt::pad(time_fractional, 6, '0') << "] ";
msg.formatted << *msg.logger_name << " <" << GetLevelName(msg.level) << "> ";
msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
msg.formatted.write(spdlog::details::os::eol, spdlog::details::os::eol_size);
}
} // namespace Log

View File

@ -0,0 +1,14 @@
#include <spdlog/spdlog.h>
namespace Log {
class Formatter : public spdlog::formatter {
public:
explicit Formatter();
Formatter(const Formatter&) = delete;
Formatter& operator=(const Formatter&) = delete;
void format(spdlog::details::log_msg& msg) override;
};
} // namespace Log

View File

@ -106,6 +106,15 @@ void LogMessage(Class log_class, Level log_level, const char* filename, unsigned
#endif #endif
; ;
template <typename Arg1, typename... Args>
void SpdLogMessage(u32 logger, Level log_level, const char* filename, unsigned int line_nr,
const char* function, const char* format, const Arg1& arg, const Args&... args);
template <typename T>
void SpdLogMessage(u32 logger, Level log_level, const char* filename, unsigned int line_nr,
const char* function, const T& msg);
u32 RegisterLogger(const char* class_name);
} // namespace Log } // namespace Log
#define LOG_GENERIC(log_class, log_level, ...) \ #define LOG_GENERIC(log_class, log_level, ...) \
@ -128,3 +137,31 @@ void LogMessage(Class log_class, Level log_level, const char* filename, unsigned
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Error, __VA_ARGS__) LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Error, __VA_ARGS__)
#define LOG_CRITICAL(log_class, ...) \ #define LOG_CRITICAL(log_class, ...) \
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Critical, __VA_ARGS__) LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Critical, __VA_ARGS__)
// Define the spdlog level macros
#define REGISTER_LOGGER(class_name) static u32 _logger = ::Log::RegisterLogger(class_name)
#ifdef _DEBUG
#define SPDLOG_TRACE(fmt, ...) \
::Log::SpdLogMessage(_logger, ::Log::Level::Trace, __FILE__, __LINE__, __func__, fmt, \
##__VA_ARGS__)
#else
#define SPDLOG_TRACE(fmt, ...) (void(0))
#endif
#define SPDLOG_DEBUG(fmt, ...) \
::Log::SpdLogMessage(_logger, ::Log::Level::Debug, __FILE__, __LINE__, __func__, fmt, \
##__VA_ARGS__)
#define SPDLOG_INFO(fmt, ...) \
::Log::SpdLogMessage(_logger, ::Log::Level::Info, __FILE__, __LINE__, __func__, fmt, \
##__VA_ARGS__)
#define SPDLOG_WARNING(fmt, ...) \
::Log::SpdLogMessage(_logger, ::Log::Level::Warning, __FILE__, __LINE__, __func__, fmt, \
##__VA_ARGS__)
#define SPDLOG_ERROR(fmt, ...) \
::Log::SpdLogMessage(_logger, ::Log::Level::Error, __FILE__, __LINE__, __func__, fmt, \
##__VA_ARGS__)
#define SPDLOG_CRITICAL(fmt, ...) \
::Log::SpdLogMessage(_logger, ::Log::Level::Critical, __FILE__, __LINE__, __func__, fmt, \
##__VA_ARGS__)