JDevlieghere created this revision.
JDevlieghere added reviewers: labath, DavidSpickett, jingham, mib, clayborg.
Herald added a project: All.
JDevlieghere requested review of this revision.

Add an "always on" log channel. The channel is meant to be used sparsely and 
deliberately for logging high-value information. Unlike other log channels, 
it's not exposed to the user. Log messages are logged to a ring buffer with a 
fixed number of entries. The ring buffer is dumped to disk as part of the 
diagnostics, i.e. when the debugger crashes or when the user explicitly 
requests a dump.


https://reviews.llvm.org/D135621

Files:
  lldb/include/lldb/Utility/Diagnostics.h
  lldb/include/lldb/Utility/LLDBLog.h
  lldb/include/lldb/Utility/Log.h
  lldb/source/Utility/Diagnostics.cpp
  lldb/source/Utility/LLDBLog.cpp
  lldb/source/Utility/Log.cpp

Index: lldb/source/Utility/Log.cpp
===================================================================
--- lldb/source/Utility/Log.cpp
+++ lldb/source/Utility/Log.cpp
@@ -48,7 +48,8 @@
   lambda("all", "all available logging categories");
   lambda("default", "default set of logging categories");
   for (const auto &category : entry.second.m_channel.categories)
-    lambda(category.name, category.description);
+    if (!category.internal)
+      lambda(category.name, category.description);
 }
 
 void Log::ListCategories(llvm::raw_ostream &stream,
Index: lldb/source/Utility/LLDBLog.cpp
===================================================================
--- lldb/source/Utility/LLDBLog.cpp
+++ lldb/source/Utility/LLDBLog.cpp
@@ -63,6 +63,10 @@
     {{"on-demand"},
      {"log symbol on-demand related activities"},
      LLDBLog::OnDemand},
+    {{"always-on"},
+     {"log pertinent activities for diagnosing issues in the debugger"},
+     LLDBLog::AlwaysOn,
+     /*internal=*/true},
 };
 
 static Log::Channel g_log_channel(g_categories,
Index: lldb/source/Utility/Diagnostics.cpp
===================================================================
--- lldb/source/Utility/Diagnostics.cpp
+++ lldb/source/Utility/Diagnostics.cpp
@@ -8,6 +8,7 @@
 
 #include "lldb/Utility/Diagnostics.h"
 #include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/LLDBLog.h"
 
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
@@ -17,6 +18,8 @@
 using namespace lldb;
 using namespace llvm;
 
+const size_t Diagnostics::g_log_messages = 100;
+
 void Diagnostics::Initialize() {
   lldbassert(!InstanceImpl() && "Already initialized.");
   InstanceImpl().emplace();
@@ -34,9 +37,18 @@
 
 Diagnostics &Diagnostics::Instance() { return *InstanceImpl(); }
 
-Diagnostics::Diagnostics() {}
+Diagnostics::Diagnostics()
+    : m_always_on_log_handler(
+          std::make_shared<RotatingLogHandler>(g_log_messages)) {
+  const uint32_t log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
+  Log::EnableLogChannel(m_always_on_log_handler, log_options, "lldb",
+                        {"always-on"}, llvm::nulls());
+  AddCallback([&](const FileSpec &dir) { return DumpAlwaysOnLog(dir); });
+}
 
-Diagnostics::~Diagnostics() {}
+Diagnostics::~Diagnostics() {
+  Log::DisableLogChannel("lldb", {"always-on"}, llvm::nulls());
+}
 
 void Diagnostics::AddCallback(Callback callback) {
   std::lock_guard<std::mutex> guard(m_callbacks_mutex);
@@ -66,9 +78,22 @@
 }
 
 Error Diagnostics::Create(const FileSpec &dir) {
+  LLDB_LOG(GetLog(LLDBLog::AlwaysOn), "Dumping {0} diagnostics to '{1}'",
+           m_callbacks.size(), dir.GetPath());
+
   for (Callback c : m_callbacks) {
     if (Error err = c(dir))
       return err;
   }
   return Error::success();
 }
+
+llvm::Error Diagnostics::DumpAlwaysOnLog(const FileSpec &dir) const {
+  FileSpec log_file = dir.CopyByAppendingPathComponent("always-on.log");
+  std::error_code ec;
+  llvm::raw_fd_ostream stream(log_file.GetPath(), ec, llvm::sys::fs::OF_None);
+  if (ec)
+    return errorCodeToError(ec);
+  m_always_on_log_handler->Dump(stream);
+  return Error::success();
+}
Index: lldb/include/lldb/Utility/Log.h
===================================================================
--- lldb/include/lldb/Utility/Log.h
+++ lldb/include/lldb/Utility/Log.h
@@ -131,11 +131,14 @@
     llvm::StringLiteral name;
     llvm::StringLiteral description;
     MaskType flag;
+    bool internal;
 
     template <typename Cat>
     constexpr Category(llvm::StringLiteral name,
-                       llvm::StringLiteral description, Cat mask)
-        : name(name), description(description), flag(MaskType(mask)) {
+                       llvm::StringLiteral description, Cat mask,
+                       bool internal = false)
+        : name(name), description(description), flag(MaskType(mask)),
+          internal(internal) {
       static_assert(
           std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value);
     }
Index: lldb/include/lldb/Utility/LLDBLog.h
===================================================================
--- lldb/include/lldb/Utility/LLDBLog.h
+++ lldb/include/lldb/Utility/LLDBLog.h
@@ -48,7 +48,8 @@
   Unwind = Log::ChannelFlag<29>,
   Watchpoints = Log::ChannelFlag<30>,
   OnDemand = Log::ChannelFlag<31>,
-  LLVM_MARK_AS_BITMASK_ENUM(OnDemand),
+  AlwaysOn = Log::ChannelFlag<32>,
+  LLVM_MARK_AS_BITMASK_ENUM(AlwaysOn),
 };
 
 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
Index: lldb/include/lldb/Utility/Diagnostics.h
===================================================================
--- lldb/include/lldb/Utility/Diagnostics.h
+++ lldb/include/lldb/Utility/Diagnostics.h
@@ -46,6 +46,11 @@
 
 private:
   static llvm::Optional<Diagnostics> &InstanceImpl();
+  static const size_t g_log_messages;
+
+  llvm::Error DumpAlwaysOnLog(const FileSpec &dir) const;
+
+  std::shared_ptr<RotatingLogHandler> m_always_on_log_handler;
 
   llvm::SmallVector<Callback, 4> m_callbacks;
   std::mutex m_callbacks_mutex;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to