diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index fd161977493ac97bb039d8bf94fe898b970e8d68..2cdd6cf06a5e6a43e02aaa2ff6f13617a73a875a 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -4,6 +4,7 @@ #include <atomic> #include <chrono> #include <climits> +#include <mutex> #include <thread> #include <fmt/format.h> @@ -231,8 +232,15 @@ public: if (!filter.CheckMessage(log_class, log_level)) { return; } - message_queue.EmplaceWait( - CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); + + auto entry = + CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)); + if (Settings::values.log_async) { + message_queue.EmplaceWait(entry); + } else { + std::scoped_lock l{sync_mutex}; + ForEachBackend([&entry](Backend& backend) { backend.Write(entry); }); + } } private: @@ -313,6 +321,7 @@ private: #endif MPSCQueue<Entry> message_queue{}; + std::mutex sync_mutex; std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; std::jthread backend_thread; }; @@ -345,9 +354,11 @@ void SetColorConsoleBackendEnabled(bool enabled) { void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) { - if (!initialization_in_progress_suppress_logging) { - Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, - fmt::vformat(format, args)); + if (initialization_in_progress_suppress_logging) { + return; } + + Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, + fmt::vformat(format, args)); } } // namespace Common::Log diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 4e3a614a451bd8b51482828d0cf23cec98f1c459..c16f4df3aaf8fc9590f88e7a6f25309f855e6738 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -171,6 +171,7 @@ const char* GetLogClassName(Class log_class) { #define SUB(x, y) \ case Class::x##_##y: \ return #x "." #y; +// return #x "_" #y; ALL_LOG_CLASSES() #undef CLS #undef SUB diff --git a/src/common/settings.h b/src/common/settings.h index 48f127bde8ba35f82413fcb3957cdfc2804697bb..829759c94b2493d5b3f88a6d59712cdb7b4acdcf 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -604,6 +604,7 @@ struct Values { // Miscellaneous Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; + Setting<bool> log_async{linkage, true, "log_async", Category::Miscellaneous}; Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous}; // Network diff --git a/src/suyu/configuration/configure_debug.cpp b/src/suyu/configuration/configure_debug.cpp index b4fa4eca091a67ef1fa20ef437d0cbe70e838e9e..6f9bb36340dc28943cbc7d53f46d7ec799b30e57 100644 --- a/src/suyu/configuration/configure_debug.cpp +++ b/src/suyu/configuration/configure_debug.cpp @@ -73,6 +73,7 @@ void ConfigureDebug::SetConfiguration() { ui->disable_loop_safety_checks->setChecked( Settings::values.disable_shader_loop_safety_checks.GetValue()); ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); + ui->log_async->setChecked(Settings::values.log_async.GetValue()); ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue()); #ifdef SUYU_USE_QT_WEB_ENGINE @@ -115,6 +116,7 @@ void ConfigureDebug::ApplyConfiguration() { Common::Log::Filter filter; filter.ParseFilterString(Settings::values.log_filter.GetValue()); Common::Log::SetGlobalFilter(filter); + Settings::values.log_async = ui->log_async->isChecked(); } void ConfigureDebug::changeEvent(QEvent* event) { diff --git a/src/suyu/configuration/configure_debug.ui b/src/suyu/configuration/configure_debug.ui index ed48b2f8f6afacb0d43567787c997d4a67f59dfa..e5b76290e66d6ac09f4c3ca0de628bc7396a2d95 100644 --- a/src/suyu/configuration/configure_debug.ui +++ b/src/suyu/configuration/configure_debug.ui @@ -164,6 +164,20 @@ </property> </widget> </item> + <item row="2" column="1"> + <widget class="QCheckBox" name="log_async"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="toolTip"> + <string>When checked, logging will run asynchronously. This may cut the log on crashes. +When unchecked, logging will run synchronously. This will slow down the emulator, but allow all logs to be written. Useful for debugging.</string> + </property> + <property name="text"> + <string>Log asynchronously</string> + </property> + </widget> + </item> <item row="0" column="0" colspan="2"> <widget class="QWidget" name="logging_widget" native="true"> <property name="sizePolicy"> @@ -199,7 +213,14 @@ </widget> </item> <item> - <widget class="QLineEdit" name="log_filter_edit"/> + <widget class="QLineEdit" name="log_filter_edit"> + <property name="toolTip"> + <string>Log filter in the form <class>:<level>. +Separate multiple filters with a space. +Levels: Trace, Debug, Info, Warning, Error, Critical +Classes: See Common/logging/types.h</string> + </property> + </widget> </item> </layout> </widget>