[Lldb-commits] [lldb] [lldb] Add TeeLogHandler to log to 2 handlers (PR #90984)

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Fri May 3 10:14:16 PDT 2024


https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/90984

Add a T-style log handler that multiplexes messages to two log handlers. The goal is to use this in combination with the SystemLogHandler to log messages both to the user requested file as well as the system log. The latter is part of a sysdiagnose on Darwin which is commonly attached to bug reports.

>From d1adf630a9981f275f24e4d0c2c613a90ff38290 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Fri, 3 May 2024 10:11:40 -0700
Subject: [PATCH] [lldb] Add TeeLogHandler to log to 2 handlers

Add a T-style log handler that multiplexes messages to two log handlers.
The goal is to use this in combination with the SystemLogHandler to log
messages both to the user requested file as well as the system log. The
latter is part of a sysdiagnose on Darwin which is commonly attached to
bug reports.
---
 lldb/include/lldb/Utility/Log.h    | 16 ++++++++++++++++
 lldb/source/Utility/Log.cpp        | 13 +++++++++++++
 lldb/unittests/Utility/LogTest.cpp | 12 ++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/lldb/include/lldb/Utility/Log.h b/lldb/include/lldb/Utility/Log.h
index 01876ad732d4b5..bea117c440a46d 100644
--- a/lldb/include/lldb/Utility/Log.h
+++ b/lldb/include/lldb/Utility/Log.h
@@ -112,6 +112,22 @@ class RotatingLogHandler : public LogHandler {
   static char ID;
 };
 
+class TeeLogHandler : public LogHandler {
+public:
+  TeeLogHandler(std::shared_ptr<LogHandler> first_log_handler,
+                std::shared_ptr<LogHandler> second_log_handler);
+
+  void Emit(llvm::StringRef message) override;
+
+  bool isA(const void *ClassID) const override { return ClassID == &ID; }
+  static bool classof(const LogHandler *obj) { return obj->isA(&ID); }
+
+private:
+  std::shared_ptr<LogHandler> m_first_log_handler;
+  std::shared_ptr<LogHandler> m_second_log_handler;
+  static char ID;
+};
+
 class Log final {
 public:
   /// The underlying type of all log channel enums. Declare them as:
diff --git a/lldb/source/Utility/Log.cpp b/lldb/source/Utility/Log.cpp
index 3a45a0285d3e25..1e237e7ff5e219 100644
--- a/lldb/source/Utility/Log.cpp
+++ b/lldb/source/Utility/Log.cpp
@@ -39,6 +39,7 @@ char LogHandler::ID;
 char StreamLogHandler::ID;
 char CallbackLogHandler::ID;
 char RotatingLogHandler::ID;
+char TeeLogHandler::ID;
 
 llvm::ManagedStatic<Log::ChannelMap> Log::g_channel_map;
 
@@ -438,3 +439,15 @@ void RotatingLogHandler::Dump(llvm::raw_ostream &stream) const {
   }
   stream.flush();
 }
+
+TeeLogHandler::TeeLogHandler(std::shared_ptr<LogHandler> first_log_handler,
+                             std::shared_ptr<LogHandler> second_log_handler)
+    : m_first_log_handler(first_log_handler),
+      m_second_log_handler(second_log_handler) {}
+
+void TeeLogHandler::Emit(llvm::StringRef message) {
+  if (m_first_log_handler)
+    m_first_log_handler->Emit(message);
+  if (m_second_log_handler)
+    m_second_log_handler->Emit(message);
+}
diff --git a/lldb/unittests/Utility/LogTest.cpp b/lldb/unittests/Utility/LogTest.cpp
index 1dac19486a8f7f..b9b0af4133da92 100644
--- a/lldb/unittests/Utility/LogTest.cpp
+++ b/lldb/unittests/Utility/LogTest.cpp
@@ -200,6 +200,18 @@ TEST(LogHandlerTest, RotatingLogHandler) {
   EXPECT_EQ(GetDumpAsString(handler), "bazquxquux");
 }
 
+TEST(LogHandlerTest, TeeLogHandler) {
+  auto handler1 = std::make_shared<RotatingLogHandler>(2);
+  auto handler2 = std::make_shared<RotatingLogHandler>(2);
+  TeeLogHandler handler(handler1, handler2);
+
+  handler.Emit("foo");
+  handler.Emit("bar");
+
+  EXPECT_EQ(GetDumpAsString(*handler1), "foobar");
+  EXPECT_EQ(GetDumpAsString(*handler2), "foobar");
+}
+
 TEST_F(LogChannelTest, Enable) {
   EXPECT_EQ(nullptr, GetLog(TestChannel::FOO));
   std::string message;



More information about the lldb-commits mailing list