Logging: Add custom formatter
This commit is contained in:
		| @@ -16,6 +16,8 @@ | ||||
| #include "game_list_p.h" | ||||
| #include "ui_settings.h" | ||||
|  | ||||
| REGISTER_LOGGER("Class Name"); | ||||
|  | ||||
| GameList::SearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist) { | ||||
|     this->gamelist = gamelist; | ||||
|     edit_filter_text_old = ""; | ||||
| @@ -198,6 +200,7 @@ GameList::GameList(GMainWindow* parent) : QWidget{parent} { | ||||
|     watcher = new QFileSystemWatcher(this); | ||||
|     connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory); | ||||
|  | ||||
|     SPDLOG_WARNING("Test! {1} {0}", "world!", "Hello"); | ||||
|     this->main_window = parent; | ||||
|     layout = new QVBoxLayout; | ||||
|     tree_view = new QTreeView; | ||||
|   | ||||
| @@ -28,9 +28,11 @@ set(SRCS | ||||
|             break_points.cpp | ||||
|             file_util.cpp | ||||
|             hash.cpp | ||||
|             logging/filter.cpp | ||||
|             logging/text_formatter.cpp | ||||
|             logging/backend.cpp | ||||
|             logging/backend_spdlog.cpp | ||||
|             logging/filter.cpp | ||||
|             logging/formatter.cpp | ||||
|             logging/text_formatter.cpp | ||||
|             memory_util.cpp | ||||
|             microprofile.cpp | ||||
|             misc.cpp | ||||
| @@ -57,10 +59,12 @@ set(HEADERS | ||||
|             file_util.h | ||||
|             hash.h | ||||
|             linear_disk_cache.h | ||||
|             logging/text_formatter.h | ||||
|             logging/filter.h | ||||
|             logging/log.h | ||||
|             logging/backend.h | ||||
|             logging/backend_spdlog.h | ||||
|             logging/filter.h | ||||
|             logging/formatter.h | ||||
|             logging/log.h | ||||
|             logging/text_formatter.h | ||||
|             math_util.h | ||||
|             memory_util.h | ||||
|             microprofile.h | ||||
|   | ||||
							
								
								
									
										87
									
								
								src/common/logging/backend_spdlog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/common/logging/backend_spdlog.cpp
									
									
									
									
									
										Normal 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 | ||||
							
								
								
									
										27
									
								
								src/common/logging/backend_spdlog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/common/logging/backend_spdlog.h
									
									
									
									
									
										Normal 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 | ||||
							
								
								
									
										48
									
								
								src/common/logging/formatter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/common/logging/formatter.cpp
									
									
									
									
									
										Normal 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 | ||||
							
								
								
									
										14
									
								
								src/common/logging/formatter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/common/logging/formatter.h
									
									
									
									
									
										Normal 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 | ||||
| @@ -106,6 +106,15 @@ void LogMessage(Class log_class, Level log_level, const char* filename, unsigned | ||||
| #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 | ||||
|  | ||||
| #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__) | ||||
| #define LOG_CRITICAL(log_class, ...)                                                               \ | ||||
|     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__) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 James Rowe
					James Rowe