diff --git a/lldb/source/Commands/CommandObjectHealthcheck.cpp b/lldb/source/Commands/CommandObjectHealthcheck.cpp index 20f379304f11e..4c71af233216c 100644 --- a/lldb/source/Commands/CommandObjectHealthcheck.cpp +++ b/lldb/source/Commands/CommandObjectHealthcheck.cpp @@ -51,8 +51,7 @@ void CommandObjectHealthcheck::DoExecute(Args &args, } llvm::raw_fd_ostream temp_stream(temp_fd, true, true); - llvm::StringRef data = GetSwiftHealthLogData(); - temp_stream << data; + DumpSwiftHealthLog(temp_stream); result.AppendMessageWithFormat("Health check written to %s\n", temp_path.c_str()); diff --git a/lldb/source/Plugins/Language/Swift/LogChannelSwift.cpp b/lldb/source/Plugins/Language/Swift/LogChannelSwift.cpp index 8c4599d6ea21b..d070e9e25d2a7 100644 --- a/lldb/source/Plugins/Language/Swift/LogChannelSwift.cpp +++ b/lldb/source/Plugins/Language/Swift/LogChannelSwift.cpp @@ -8,8 +8,10 @@ #include "LogChannelSwift.h" #include "lldb/Host/Host.h" +#include "lldb/Utility/Diagnostics.h" #include "lldb/Utility/Log.h" #include "lldb/Version/Version.h" +#include "llvm/Support/FileSystem.h" using namespace lldb_private; @@ -21,39 +23,20 @@ static constexpr Log::Category g_categories[] = { static Log::Channel g_channel(g_categories, SwiftLog::Health); -static std::string g_swift_log_buffer; +static constexpr size_t g_health_log_size = 5000; +static std::shared_ptr g_health_log_handler; +static std::optional g_diagnostics_callback_id; template <> Log::Channel &lldb_private::LogChannelFor() { return g_channel; } -class StringLogHandler : public LogHandler { -public: - StringLogHandler(std::string& str) : m_string(str) {} - - void Emit(llvm::StringRef message) override { - std::lock_guard guard(m_mutex); - m_string += std::string(message); - } - - bool isA(const void *ClassID) const override { return ClassID == &ID; } - static bool classof(const LogHandler *obj) { return obj->isA(&ID); } - -private: - std::mutex m_mutex; - std::string& m_string; - static char ID; -}; - -char StringLogHandler::ID; - void LogChannelSwift::Initialize() { Log::Register("swift", g_channel); - auto string_log_handler_sp = - std::make_shared(g_swift_log_buffer); + g_health_log_handler = std::make_shared(g_health_log_size); auto system_log_handler_sp = std::make_shared(); - auto log_handler_sp = std::make_shared(string_log_handler_sp, + auto log_handler_sp = std::make_shared(g_health_log_handler, system_log_handler_sp); Log::EnableLogChannel(log_handler_sp, 0, "swift", {"health"}, llvm::nulls()); @@ -65,12 +48,34 @@ void LogChannelSwift::Initialize() { "The swift-healthcheck command is meant to be run *after* an error " "has occurred.\n%s", lldb_private::GetVersion()); + + if (Diagnostics::Enabled()) { + g_diagnostics_callback_id = Diagnostics::Instance().AddCallback( + [](const FileSpec &dir) -> llvm::Error { + FileSpec log_file = + dir.CopyByAppendingPathComponent("swift-healthcheck.log"); + std::error_code ec; + llvm::raw_fd_ostream stream(log_file.GetPath(), ec); + if (ec) + return llvm::errorCodeToError(ec); + if (g_health_log_handler) + g_health_log_handler->Dump(stream); + return llvm::Error::success(); + }); + } } -void LogChannelSwift::Terminate() { Log::Unregister("swift"); } +void LogChannelSwift::Terminate() { + if (g_diagnostics_callback_id && Diagnostics::Enabled()) + Diagnostics::Instance().RemoveCallback(*g_diagnostics_callback_id); + g_diagnostics_callback_id.reset(); + g_health_log_handler.reset(); + Log::Unregister("swift"); +} Log *lldb_private::GetSwiftHealthLog() { return GetLog(SwiftLog::Health); } -llvm::StringRef lldb_private::GetSwiftHealthLogData() { - return g_swift_log_buffer; +void lldb_private::DumpSwiftHealthLog(llvm::raw_ostream &stream) { + if (g_health_log_handler) + g_health_log_handler->Dump(stream); } diff --git a/lldb/source/Plugins/Language/Swift/LogChannelSwift.h b/lldb/source/Plugins/Language/Swift/LogChannelSwift.h index 4c5ba464ec53b..6a82ca762d638 100644 --- a/lldb/source/Plugins/Language/Swift/LogChannelSwift.h +++ b/lldb/source/Plugins/Language/Swift/LogChannelSwift.h @@ -11,7 +11,7 @@ #include "lldb/Utility/Log.h" #include "llvm/ADT/BitmaskEnum.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" namespace lldb_private { @@ -31,7 +31,7 @@ struct LogChannelSwift { template <> Log::Channel &LogChannelFor(); Log *GetSwiftHealthLog(); -llvm::StringRef GetSwiftHealthLogData(); +void DumpSwiftHealthLog(llvm::raw_ostream &stream); } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_LOGCHANNELDWARF_H