From 373efd3158392ef105287f675daf235d27537bab Mon Sep 17 00:00:00 2001 From: Daniel Lim Wee Soong Date: Fri, 16 Mar 2018 11:56:40 +0800 Subject: [PATCH] Logging: Remove customizable logging backends Separate code for customizing logging backends from this branch --- src/citra/citra.cpp | 7 +- .../configuration/configure_debug.cpp | 2 +- src/citra_qt/main.cpp | 7 +- src/common/logging/backend.cpp | 129 ++---------------- src/common/logging/backend.h | 75 +--------- 5 files changed, 12 insertions(+), 208 deletions(-) diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index eb7a7d181..d8209fec9 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -239,12 +239,7 @@ int main(int argc, char** argv) { Log::Filter log_filter; log_filter.ParseFilterString(Settings::values.log_filter); - Log::SetGlobalFilter(log_filter); - - Log::AddBackend(std::make_unique()); - FileUtil::CreateFullPath(FileUtil::GetUserPath(D_LOGS_IDX)); - Log::AddBackend( - std::make_unique(FileUtil::GetUserPath(D_LOGS_IDX) + LOG_FILE)); + Log::SetFilter(&log_filter); // Apply the command line arguments Settings::values.gdbstub_port = gdb_port; diff --git a/src/citra_qt/configuration/configure_debug.cpp b/src/citra_qt/configuration/configure_debug.cpp index 9744ac6c0..b9eb0e3d1 100644 --- a/src/citra_qt/configuration/configure_debug.cpp +++ b/src/citra_qt/configuration/configure_debug.cpp @@ -44,7 +44,7 @@ void ConfigureDebug::applyConfiguration() { Debugger::ToggleConsole(); Log::Filter filter; filter.ParseFilterString(Settings::values.log_filter); - Log::SetGlobalFilter(filter); + Log::SetFilter(&filter); Settings::Apply(); } diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index d60d8f511..c164eeb81 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -1298,8 +1298,6 @@ void GMainWindow::SyncMenuUISettings() { #endif int main(int argc, char* argv[]) { - Log::AddBackend(std::make_unique()); - MicroProfileOnThreadCreate("Frontend"); SCOPE_EXIT({ MicroProfileShutdown(); }); @@ -1318,10 +1316,7 @@ int main(int argc, char* argv[]) { // After settings have been loaded by GMainWindow, apply the filter Log::Filter log_filter; log_filter.ParseFilterString(Settings::values.log_filter); - Log::SetGlobalFilter(log_filter); - FileUtil::CreateFullPath(FileUtil::GetUserPath(D_LOGS_IDX)); - Log::AddBackend( - std::make_unique(FileUtil::GetUserPath(D_LOGS_IDX) + LOG_FILE)); + Log::SetFilter(&log_filter); main_window.show(); return app.exec(); diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 20b4fe5ea..3c0361713 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -4,118 +4,17 @@ #include #include -#include #include -#include -#include -#include -#ifdef _WIN32 -#include // For _SH_DENYWR -#else -#define _SH_DENYWR 0 -#endif #include "common/assert.h" #include "common/common_funcs.h" // snprintf compatibility define #include "common/logging/backend.h" +#include "common/logging/filter.h" #include "common/logging/log.h" #include "common/logging/text_formatter.h" #include "common/string_util.h" -#include "common/threadsafe_queue.h" namespace Log { -/** - * Static state as a singleton. - */ -class Impl { -public: - static Impl& Instance() { - static Impl backend; - return backend; - } - - Impl(Impl const&) = delete; - const Impl& operator=(Impl const&) = delete; - - void PushEntry(Entry e) { - message_queue.Push(std::move(e)); - } - - void AddBackend(std::unique_ptr backend) { - backends.push_back(std::move(backend)); - } - - void RemoveBackend(const std::string& backend_name) { - std::remove_if(backends.begin(), backends.end(), - [&backend_name](const auto& i) { return i->GetName() == backend_name; }); - } - - const Filter& GetGlobalFilter() const { - return filter; - } - - void SetGlobalFilter(const Filter& f) { - filter = f; - } - - boost::optional GetBackend(const std::string& backend_name) { - auto it = std::find_if(backends.begin(), backends.end(), [&backend_name](const auto& i) { - return i->GetName() == backend_name; - }); - if (it == backends.end()) - return boost::none; - return it->get(); - } - -private: - Impl() { - backend_thread = std::async(std::launch::async, [&] { - using namespace std::chrono_literals; - Entry entry; - while (running) { - if (!message_queue.PopWait(entry)) { - continue; - } - for (const auto& backend : backends) { - backend->Write(entry); - } - } - }); - } - ~Impl() { - running = false; - backend_thread.get(); - } - - std::atomic_bool running{true}; - std::future backend_thread; - std::vector> backends; - Common::MPSCQueue message_queue; - Filter filter; -}; - -void ConsoleBackend::Write(const Entry& entry) { - PrintMessage(entry); -} - -void ColorConsoleBackend::Write(const Entry& entry) { - PrintColoredMessage(entry); -} - -// _SH_DENYWR allows read only access to the file for other programs. -// It is #defined to 0 on other platforms -FileBackend::FileBackend(const std::string& filename) : file(filename, "w", _SH_DENYWR) {} - -void FileBackend::Write(const Entry& entry) { - if (!file.IsOpen()) { - return; - } - file.WriteString(FormatLogMessage(entry) + '\n'); - if (entry.log_level >= Level::Error) { - file.Flush(); - } -} - /// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. #define ALL_LOG_CLASSES() \ CLS(Log) \ @@ -233,26 +132,15 @@ Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsign return entry; } -void SetGlobalFilter(const Filter& filter) { - Impl::Instance().SetGlobalFilter(filter); -} +static Filter* filter = nullptr; -void AddBackend(std::unique_ptr backend) { - Impl::Instance().AddBackend(std::move(backend)); -} - -void RemoveBackend(const std::string& backend_name) { - Impl::Instance().RemoveBackend(backend_name); -} - -boost::optional GetBackend(const std::string& backend_name) { - return Impl::Instance().GetBackend(backend_name); +void SetFilter(Filter* new_filter) { + filter = new_filter; } void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, const char* format, ...) { - auto filter = Impl::Instance().GetGlobalFilter(); - if (!filter.CheckMessage(log_class, log_level)) + if (!filter->CheckMessage(log_class, log_level)) return; std::array formatting_buffer; va_list args; @@ -262,14 +150,13 @@ void LogMessage(Class log_class, Level log_level, const char* filename, unsigned Entry entry = CreateEntry(log_class, log_level, filename, line_num, function, std::string(formatting_buffer.data())); - Impl::Instance().PushEntry(std::move(entry)); + PrintColoredMessage(entry); } void LogEntry(Entry& entry) { - auto filter = Impl::Instance().GetGlobalFilter(); - if (!filter.CheckMessage(entry.log_class, entry.log_level)) + if (!filter->CheckMessage(entry.log_class, entry.log_level)) return; - Impl::Instance().PushEntry(std::move(entry)); + PrintColoredMessage(entry); } } // namespace Log diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index 0bf9b8fd7..d5b9834e1 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -6,81 +6,14 @@ #include #include -#include #include #include -#include -#include "common/file_util.h" -#include "common/logging/filter.h" #include "common/logging/log.h" namespace Log { class Filter; -/** - * Interface for logging backends. As loggers can be created and removed at runtime, this can be - * used by a frontend for adding a custom logging backend as needed - */ -class Backend { -public: - virtual ~Backend() = default; - virtual void SetFilter(const Filter& new_filter) { - filter = new_filter; - } - virtual const char* GetName() const = 0; - virtual void Write(const Entry& entry) = 0; - -private: - Filter filter; -}; - -/** - * Backend that writes to stderr without any color commands - */ -class ConsoleBackend : public Backend { -public: - const char* GetName() const override { - return "console"; - } - void Write(const Entry& entry) override; -}; - -/** - * Backend that writes to stderr and with color - */ -class ColorConsoleBackend : public Backend { -public: - const char* GetName() const override { - return "color_console"; - } - void Write(const Entry& entry) override; -}; - -/** - * Backend that writes to a file passed into the constructor. If a log level is error or higher, it - * will flush immediately after writing - */ -class FileBackend : public Backend { -public: - explicit FileBackend(const std::string& filename); - - const char* GetName() const override { - return "file"; - } - - void Write(const Entry& entry) override; - -private: - FileUtil::IOFile file; -}; - -void AddBackend(std::unique_ptr backend); - -void RemoveBackend(const std::string& backend_name); - -boost::optional GetBackend(const std::string& backend_name); - /** * Returns the name of the passed log class as a C-string. Subclasses are separated by periods * instead of underscores as in the enumeration. @@ -92,11 +25,5 @@ const char* GetLogClassName(Class log_class); */ const char* GetLevelName(Level log_level); -/** - * The global filter will prevent any messages from even being processed if they are filtered. Each - * backend can have a filter, but if the level is lower than the global filter, the backend will - * never get the message - */ -void SetGlobalFilter(const Filter& filter); - +void SetFilter(Filter* filter); } // namespace Log