JDevlieghere created this revision. JDevlieghere added reviewers: labath, clayborg, kastiglione, mib. Herald added a project: All. JDevlieghere requested review of this revision.
This patch adds a new flag to `log enable` allowing the user to specify a log handler. This makes it possible to enable logging to a circular buffer (D127937 <https://reviews.llvm.org/D127937>) or with OSLog (D128321 <https://reviews.llvm.org/D128321>) as well as the default stream handler. As is the patch is more of an RFC/POC. It needs some cleaning up as well as a test case, which I'll add if everyone is happy with the direction. https://reviews.llvm.org/D128323 Files: lldb/include/lldb/Core/Debugger.h lldb/include/lldb/lldb-private-enumerations.h lldb/source/API/SBDebugger.cpp lldb/source/Commands/CommandObjectLog.cpp lldb/source/Commands/Options.td lldb/source/Core/Debugger.cpp lldb/tools/lldb-test/lldb-test.cpp
Index: lldb/tools/lldb-test/lldb-test.cpp =================================================================== --- lldb/tools/lldb-test/lldb-test.cpp +++ lldb/tools/lldb-test/lldb-test.cpp @@ -1120,7 +1120,7 @@ /*add_to_history*/ eLazyBoolNo, Result); if (!opts::Log.empty()) - Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, errs()); + Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs()); if (opts::BreakpointSubcommand) return opts::breakpoint::evaluateBreakpoints(*Dbg); Index: lldb/source/Core/Debugger.cpp =================================================================== --- lldb/source/Core/Debugger.cpp +++ lldb/source/Core/Debugger.cpp @@ -1406,10 +1406,30 @@ debugger_id, once); } +static std::shared_ptr<LogHandler> +CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close, + size_t buffer_size) { + + switch (log_handler_kind) { + case eLogHandlerStream: + return std::make_shared<StreamLogHandler>(fd, should_close, buffer_size); + case eLogHandlerRotating: + return std::make_shared<RotatingLogHandler>(buffer_size); +#if defined(__APPLE__) + case eLogHandlerOSLog: + return std::make_shared<OSLogLogHandler>(); +#endif + case eLogHandlerCallback: + return {}; + } + return {}; +} + bool Debugger::EnableLog(llvm::StringRef channel, llvm::ArrayRef<const char *> categories, llvm::StringRef log_file, uint32_t log_options, - size_t buffer_size, llvm::raw_ostream &error_stream) { + size_t buffer_size, LogHandlerKind log_handler_kind, + llvm::raw_ostream &error_stream) { const bool should_close = true; std::shared_ptr<LogHandler> log_handler_sp; @@ -1419,8 +1439,9 @@ log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; } else if (log_file.empty()) { - log_handler_sp = std::make_shared<StreamLogHandler>( - GetOutputFile().GetDescriptor(), !should_close, buffer_size); + log_handler_sp = + CreateLogHandler(log_handler_kind, GetOutputFile().GetDescriptor(), + !should_close, buffer_size); } else { auto pos = m_stream_handlers.find(log_file); if (pos != m_stream_handlers.end()) @@ -1440,8 +1461,9 @@ return false; } - log_handler_sp = std::make_shared<StreamLogHandler>( - (*file)->GetDescriptor(), should_close, buffer_size); + log_handler_sp = + CreateLogHandler(log_handler_kind, (*file)->GetDescriptor(), + !should_close, buffer_size); m_stream_handlers[log_file] = log_handler_sp; } } Index: lldb/source/Commands/Options.td =================================================================== --- lldb/source/Commands/Options.td +++ lldb/source/Commands/Options.td @@ -433,6 +433,8 @@ Desc<"Set the destination file to log to.">; def log_buffer_size : Option<"buffer", "b">, Group<1>, Arg<"UnsignedInteger">, Desc<"Set the log to be buffered, using the specified buffer size.">; + def log_handler : Option<"handler", "h">, Group<1>, + EnumArg<"Value", "LogHandlerType()">, Desc<"Use a custom handler.">; def log_threadsafe : Option<"threadsafe", "t">, Group<1>, Desc<"Enable thread safe logging to avoid interweaved log lines.">; def log_verbose : Option<"verbose", "v">, Group<1>, Index: lldb/source/Commands/CommandObjectLog.cpp =================================================================== --- lldb/source/Commands/CommandObjectLog.cpp +++ lldb/source/Commands/CommandObjectLog.cpp @@ -11,6 +11,7 @@ #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionValueEnumeration.h" #include "lldb/Interpreter/OptionValueUInt64.h" #include "lldb/Interpreter/Options.h" #include "lldb/Utility/Args.h" @@ -22,6 +23,30 @@ using namespace lldb; using namespace lldb_private; +static constexpr OptionEnumValueElement g_log_handler_type[] = { + { + eLogHandlerStream, + "stream", + "Use the stream log handler", + }, + { + eLogHandlerRotating, + "rotating", + "Use the rotating log handler", + }, +#if defined(__APPLE__) + { + eLogHandlerOSLog, + "oslog", + "Use the OSLog log handler", + }, +#endif +}; + +static constexpr OptionEnumValues LogHandlerType() { + return OptionEnumValues(g_log_handler_type); +} + #define LLDB_OPTIONS_log_enable #include "CommandOptions.inc" @@ -94,6 +119,14 @@ error = buffer_size.SetValueFromString(option_arg, eVarSetOperationAssign); break; + case 'h': + handler = (LogHandlerKind)OptionArgParser::ToOptionEnum( + option_arg, GetDefinitions()[option_idx].enum_values, 0, error); + if (!error.Success()) + error.SetErrorStringWithFormat( + "unrecognized value for log provider '%s'", + option_arg.str().c_str()); + break; case 't': log_options |= LLDB_LOG_OPTION_THREADSAFE; break; @@ -131,6 +164,7 @@ void OptionParsingStarting(ExecutionContext *execution_context) override { log_file.Clear(); buffer_size.Clear(); + handler = eLogHandlerStream; log_options = 0; } @@ -140,6 +174,7 @@ FileSpec log_file; OptionValueUInt64 buffer_size; + LogHandlerKind handler = eLogHandlerStream; uint32_t log_options = 0; }; @@ -171,7 +206,8 @@ llvm::raw_string_ostream error_stream(error); bool success = GetDebugger().EnableLog( channel, args.GetArgumentArrayRef(), log_file, m_options.log_options, - m_options.buffer_size.GetCurrentValue(), error_stream); + m_options.buffer_size.GetCurrentValue(), m_options.handler, + error_stream); result.GetErrorStream() << error_stream.str(); if (success) Index: lldb/source/API/SBDebugger.cpp =================================================================== --- lldb/source/API/SBDebugger.cpp +++ lldb/source/API/SBDebugger.cpp @@ -1621,7 +1621,8 @@ std::string error; llvm::raw_string_ostream error_stream(error); return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "", - log_options, /*buffer_size=*/0, error_stream); + log_options, /*buffer_size=*/0, + eLogHandlerStream, error_stream); } else return false; } Index: lldb/include/lldb/lldb-private-enumerations.h =================================================================== --- lldb/include/lldb/lldb-private-enumerations.h +++ lldb/include/lldb/lldb-private-enumerations.h @@ -222,6 +222,15 @@ StatisticMax = 4 }; +// Enumeration that can be used to specify a log handler. +enum LogHandlerKind { + eLogHandlerStream, + eLogHandlerCallback, + eLogHandlerRotating, +#if defined(__APPLE__) + eLogHandlerOSLog, +#endif +}; inline std::string GetStatDescription(lldb_private::StatisticKind K) { switch (K) { Index: lldb/include/lldb/Core/Debugger.h =================================================================== --- lldb/include/lldb/Core/Debugger.h +++ lldb/include/lldb/Core/Debugger.h @@ -245,7 +245,8 @@ bool EnableLog(llvm::StringRef channel, llvm::ArrayRef<const char *> categories, llvm::StringRef log_file, uint32_t log_options, - size_t buffer_size, llvm::raw_ostream &error_stream); + size_t buffer_size, LogHandlerKind log_handler_kind, + llvm::raw_ostream &error_stream); void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits