Skip to content

Commit a8fbe50

Browse files
authored
[lldb] Add TeeLogHandler to log to 2 handlers (#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.
1 parent e2b3e4e commit a8fbe50

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

lldb/include/lldb/Utility/Log.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,23 @@ class RotatingLogHandler : public LogHandler {
112112
static char ID;
113113
};
114114

115+
/// A T-style log handler that multiplexes messages to two log handlers.
116+
class TeeLogHandler : public LogHandler {
117+
public:
118+
TeeLogHandler(std::shared_ptr<LogHandler> first_log_handler,
119+
std::shared_ptr<LogHandler> second_log_handler);
120+
121+
void Emit(llvm::StringRef message) override;
122+
123+
bool isA(const void *ClassID) const override { return ClassID == &ID; }
124+
static bool classof(const LogHandler *obj) { return obj->isA(&ID); }
125+
126+
private:
127+
std::shared_ptr<LogHandler> m_first_log_handler;
128+
std::shared_ptr<LogHandler> m_second_log_handler;
129+
static char ID;
130+
};
131+
115132
class Log final {
116133
public:
117134
/// The underlying type of all log channel enums. Declare them as:

lldb/source/Utility/Log.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ char LogHandler::ID;
3939
char StreamLogHandler::ID;
4040
char CallbackLogHandler::ID;
4141
char RotatingLogHandler::ID;
42+
char TeeLogHandler::ID;
4243

4344
llvm::ManagedStatic<Log::ChannelMap> Log::g_channel_map;
4445

@@ -438,3 +439,16 @@ void RotatingLogHandler::Dump(llvm::raw_ostream &stream) const {
438439
}
439440
stream.flush();
440441
}
442+
443+
TeeLogHandler::TeeLogHandler(std::shared_ptr<LogHandler> first_log_handler,
444+
std::shared_ptr<LogHandler> second_log_handler)
445+
: m_first_log_handler(first_log_handler),
446+
m_second_log_handler(second_log_handler) {
447+
assert(m_first_log_handler && "first log handler must be valid");
448+
assert(m_second_log_handler && "second log handler must be valid");
449+
}
450+
451+
void TeeLogHandler::Emit(llvm::StringRef message) {
452+
m_first_log_handler->Emit(message);
453+
m_second_log_handler->Emit(message);
454+
}

lldb/unittests/Utility/LogTest.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,18 @@ TEST(LogHandlerTest, RotatingLogHandler) {
200200
EXPECT_EQ(GetDumpAsString(handler), "bazquxquux");
201201
}
202202

203+
TEST(LogHandlerTest, TeeLogHandler) {
204+
auto handler1 = std::make_shared<RotatingLogHandler>(2);
205+
auto handler2 = std::make_shared<RotatingLogHandler>(2);
206+
TeeLogHandler handler(handler1, handler2);
207+
208+
handler.Emit("foo");
209+
handler.Emit("bar");
210+
211+
EXPECT_EQ(GetDumpAsString(*handler1), "foobar");
212+
EXPECT_EQ(GetDumpAsString(*handler2), "foobar");
213+
}
214+
203215
TEST_F(LogChannelTest, Enable) {
204216
EXPECT_EQ(nullptr, GetLog(TestChannel::FOO));
205217
std::string message;

0 commit comments

Comments
 (0)