[lldb] [llvm] [lldb][telemetry] Implement LLDB Telemetry (part 1) (PR #119716)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 12 07:53:53 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Vy Nguyen (oontvoo)

<details>
<summary>Changes</summary>

Details:
- This is a subset of PR/98528.( Pavel's suggestion was to split up the patch to make reviewing easier)
- This contains only the concrete implementation of the framework to be used but no usages yet.
- I plan to send two follow-up patches:
  + part2 : includes changes in the plugin-manager to set up the plugin stuff.
  + part3 : includes changes in LLDB/LLDB-DAP to use the framework

Note: Please ignore all changes under llvm/.... These will be reverted after the pending LLVM patch is submitted.

---

Patch is 32.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/119716.diff


9 Files Affected:

- (added) lldb/include/lldb/Core/Telemetry.h (+309) 
- (modified) lldb/include/lldb/lldb-enumerations.h (+2-2) 
- (modified) lldb/source/Core/CMakeLists.txt (+2) 
- (added) lldb/source/Core/Telemetry.cpp (+338) 
- (modified) lldb/test/CMakeLists.txt (+10-10) 
- (added) llvm/include/llvm/Telemetry/Telemetry.h (+133) 
- (modified) llvm/lib/CMakeLists.txt (+1) 
- (added) llvm/lib/Telemetry/CMakeLists.txt (+6) 
- (added) llvm/lib/Telemetry/Telemetry.cpp (+11) 


``````````diff
diff --git a/lldb/include/lldb/Core/Telemetry.h b/lldb/include/lldb/Core/Telemetry.h
new file mode 100644
index 00000000000000..241d957672b6ca
--- /dev/null
+++ b/lldb/include/lldb/Core/Telemetry.h
@@ -0,0 +1,309 @@
+//===-- Telemetry.h ----------------------------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_CORE_TELEMETRY_H
+#define LLDB_CORE_TELEMETRY_H
+
+#include <atomic>
+#include <chrono>
+#include <ctime>
+#include <memory>
+#include <optional>
+#include <string>
+#include <unordered_map>
+
+#include "lldb/Core/StructuredDataImpl.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Utility/StructuredData.h"
+#include "lldb/lldb-forward.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Telemetry/Telemetry.h"
+
+namespace lldb_private {
+
+using llvm::telemetry::Destination;
+using llvm::telemetry::KindType;
+using llvm::telemetry::Serializer;
+using llvm::telemetry::TelemetryInfo;
+
+struct LldbEntryKind : public ::llvm::telemetry::EntryKind {
+  static const KindType BaseInfo = 0b11000;
+  static const KindType DebuggerInfo = 0b11001;
+  static const KindType TargetInfo = 0b11010;
+  static const KindType ClientInfo = 0b11100;
+  static const KindType CommandInfo = 0b11101;
+  static const KindType MiscInfo = 0b11110;
+};
+
+/// Defines a convenient type for timestamp of various events.
+/// This is used by the EventStats below.
+using SteadyTimePoint = std::chrono::time_point<std::chrono::steady_clock>;
+
+/// Various time (and possibly memory) statistics of an event.
+struct EventStats {
+  // REQUIRED: Start time of an event
+  SteadyTimePoint start;
+  // OPTIONAL: End time of an event - may be empty if not meaningful.
+  std::optional<SteadyTimePoint> end;
+  // TBD: could add some memory stats here too?
+
+  EventStats() = default;
+  EventStats(SteadyTimePoint start) : start(start) {}
+  EventStats(SteadyTimePoint start, SteadyTimePoint end)
+      : start(start), end(end) {}
+};
+
+/// Describes the exit signal of an event.
+struct ExitDescription {
+  int exit_code;
+  std::string description;
+};
+
+struct LldbBaseTelemetryInfo : public TelemetryInfo {
+  EventStats stats;
+
+  // For dyn_cast, isa, etc operations.
+  KindType getKind() const override { return LldbEntryKind::BaseInfo; }
+
+  static bool classof(const TelemetryInfo *t) {
+    if (t == nullptr)
+      return false;
+    // Subclasses of this is also acceptable.
+    return (t->getKind() & LldbEntryKind::BaseInfo) == LldbEntryKind::BaseInfo;
+  }
+
+  void serialize(Serializer &serializer) const override;
+};
+
+struct DebuggerTelemetryInfo : public LldbBaseTelemetryInfo {
+  std::string username;
+  std::string lldb_git_sha;
+  std::string lldb_path;
+  std::string cwd;
+
+  std::optional<ExitDescription> exit_desc;
+  DebuggerTelemetryInfo() = default;
+
+  // Provide a copy ctor because we may need to make a copy before
+  // sanitizing the data.
+  // (The sanitization might differ between different Destination classes).
+  DebuggerTelemetryInfo(const DebuggerTelemetryInfo &other) {
+    username = other.username;
+    lldb_git_sha = other.lldb_git_sha;
+    lldb_path = other.lldb_path;
+    cwd = other.cwd;
+  };
+
+  KindType getKind() const override { return LldbEntryKind::DebuggerInfo; }
+
+  static bool classof(const TelemetryInfo *T) {
+    if (T == nullptr)
+      return false;
+    return T->getKind() == LldbEntryKind::DebuggerInfo;
+  }
+
+  void serialize(Serializer &serializer) const override;
+};
+
+struct TargetTelemetryInfo : public LldbBaseTelemetryInfo {
+  lldb::ModuleSP exec_mod;
+  Target *target_ptr;
+
+  // The same as the executable-module's UUID.
+  std::string target_uuid;
+  std::string file_format;
+
+  std::string binary_path;
+  size_t binary_size;
+
+  std::optional<ExitDescription> exit_desc;
+  TargetTelemetryInfo() = default;
+
+  TargetTelemetryInfo(const TargetTelemetryInfo &other) {
+    exec_mod = other.exec_mod;
+    target_uuid = other.target_uuid;
+    file_format = other.file_format;
+    binary_path = other.binary_path;
+    binary_size = other.binary_size;
+    exit_desc = other.exit_desc;
+  }
+
+  KindType getKind() const override { return LldbEntryKind::TargetInfo; }
+
+  static bool classof(const TelemetryInfo *T) {
+    if (T == nullptr)
+      return false;
+    return T->getKind() == LldbEntryKind::TargetInfo;
+  }
+
+  void serialize(Serializer &serializer) const override;
+};
+
+// Entry from client (eg., SB-API)
+struct ClientTelemetryInfo : public LldbBaseTelemetryInfo {
+  std::string request_name;
+  std::string error_msg;
+
+  ClientTelemetryInfo() = default;
+
+  ClientTelemetryInfo(const ClientTelemetryInfo &other) {
+    request_name = other.request_name;
+    error_msg = other.error_msg;
+  }
+
+  KindType getKind() const override { return LldbEntryKind::ClientInfo; }
+
+  static bool classof(const TelemetryInfo *T) {
+    if (T == nullptr)
+      return false;
+    return T->getKind() == LldbEntryKind::ClientInfo;
+  }
+
+  void serialize(Serializer &serializer) const override;
+};
+
+struct CommandTelemetryInfo : public LldbBaseTelemetryInfo {
+  Target *target_ptr;
+  CommandReturnObject *result;
+
+  // If the command is/can be associated with a target entry,
+  // this field contains that target's UUID.
+  // <EMPTY> otherwise.
+  std::string target_uuid;
+  std::string command_uuid;
+
+  // Eg., "breakpoint set"
+  std::string command_name;
+
+  // !!NOTE!!: The following fields may be omitted due to PII risk.
+  // (Configurable via the telemery::Config struct)
+  std::string original_command;
+  std::string args;
+
+  std::optional<ExitDescription> exit_desc;
+  lldb::ReturnStatus ret_status;
+
+  CommandTelemetryInfo() = default;
+
+  CommandTelemetryInfo(const CommandTelemetryInfo &other) {
+    target_uuid = other.target_uuid;
+    command_uuid = other.command_uuid;
+    command_name = other.command_name;
+    original_command = other.original_command;
+    args = other.args;
+    exit_desc = other.exit_desc;
+    ret_status = other.ret_status;
+  }
+
+  KindType getKind() const override { return LldbEntryKind::CommandInfo; }
+
+  static bool classof(const TelemetryInfo *T) {
+    if (T == nullptr)
+      return false;
+    return T->getKind() == LldbEntryKind::CommandInfo;
+  }
+
+  void serialize(Serializer &serializer) const override;
+};
+
+/// The "catch-all" entry to store a set of custom/non-standard
+/// data.
+struct MiscTelemetryInfo : public LldbBaseTelemetryInfo {
+  /// If the event is/can be associated with a target entry,
+  /// this field contains that target's UUID.
+  /// <EMPTY> otherwise.
+  std::string target_uuid;
+
+  /// Set of key-value pairs for any optional (or impl-specific) data
+  std::map<std::string, std::string> meta_data;
+
+  MiscTelemetryInfo() = default;
+
+  MiscTelemetryInfo(const MiscTelemetryInfo &other) {
+    target_uuid = other.target_uuid;
+    meta_data = other.meta_data;
+  }
+
+  KindType getKind() const override { return LldbEntryKind::MiscInfo; }
+
+  static bool classof(const TelemetryInfo *T) {
+    if (T == nullptr)
+      return false;
+    return T->getKind() == LldbEntryKind::MiscInfo;
+  }
+
+  void serialize(Serializer &serializer) const override;
+};
+
+/// The base Telemetry manager instance in LLDB
+/// This class declares additional instrumentation points
+/// applicable to LLDB.
+class TelemetryManager : public llvm::telemetry::Manager {
+public:
+  /// Creates an instance of TelemetryManager.
+  /// This uses the plugin registry to find an instance:
+  ///  - If a vendor supplies a implementation, it will use it.
+  ///  - If not, it will either return a no-op instance or a basic
+  ///    implementation for testing.
+  ///
+  /// See also lldb_private::TelemetryVendor.
+  static std::unique_ptr<TelemetryManager>
+  CreateInstance(std::unique_ptr<llvm::telemetry::Config> config,
+                 Debugger *debugger);
+
+  /// To be invoked upon LLDB startup.
+  virtual void LogStartup(DebuggerTelemetryInfo *entry);
+
+  /// To be invoked upon LLDB exit.
+  virtual void LogExit(DebuggerTelemetryInfo *entry);
+
+  /// To be invoked upon loading the main executable module.
+  /// We log in a fire-n-forget fashion so that if the load
+  /// crashes, we don't lose the entry.
+  virtual void LogMainExecutableLoadStart(TargetTelemetryInfo *entry);
+  virtual void LogMainExecutableLoadEnd(TargetTelemetryInfo *entry);
+
+  /// To be invoked upon process exit.
+  virtual void LogProcessExit(TargetTelemetryInfo *entry);
+
+  /// Invoked for each command
+  /// We log in a fire-n-forget fashion so that if the command execution
+  /// crashes, we don't lose the entry.
+  virtual void LogCommandStart(CommandTelemetryInfo *entry);
+  virtual void LogCommandEnd(CommandTelemetryInfo *entry);
+
+  /// For client (eg., SB API) to send telemetry entries.
+  virtual void
+  LogClientTelemetry(const lldb_private::StructuredDataImpl &entry);
+
+  virtual std::string GetNextUUID() {
+    return std::to_string(uuid_seed.fetch_add(1));
+  }
+
+  llvm::Error dispatch(TelemetryInfo *entry) override;
+  void addDestination(std::unique_ptr<Destination> destination) override;
+
+protected:
+  TelemetryManager(std::unique_ptr<llvm::telemetry::Config> config,
+                   Debugger *debugger);
+  TelemetryManager() = default;
+  virtual void CollectMiscBuildInfo();
+
+private:
+  std::atomic<size_t> uuid_seed = 0;
+  std::unique_ptr<llvm::telemetry::Config> m_config;
+  Debugger *m_debugger;
+  const std::string m_session_uuid;
+  std::vector<std::unique_ptr<Destination>> m_destinations;
+};
+
+} // namespace lldb_private
+#endif // LLDB_CORE_TELEMETRY_H
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 938f6e3abe8f2a..8015f42c5ffc8c 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -257,8 +257,8 @@ enum StopReason {
 };
 
 /// Command Return Status Types.
-enum ReturnStatus {
-  eReturnStatusInvalid,
+enum ReturnStatus : int {
+  eReturnStatusInvalid = 0,
   eReturnStatusSuccessFinishNoResult,
   eReturnStatusSuccessFinishResult,
   eReturnStatusSuccessContinuingNoResult,
diff --git a/lldb/source/Core/CMakeLists.txt b/lldb/source/Core/CMakeLists.txt
index dbc620b91b1ed1..4a02f7f1fc85e5 100644
--- a/lldb/source/Core/CMakeLists.txt
+++ b/lldb/source/Core/CMakeLists.txt
@@ -51,6 +51,7 @@ add_lldb_library(lldbCore
   Section.cpp
   SourceLocationSpec.cpp
   SourceManager.cpp
+  Telemetry.cpp
   StreamAsynchronousIO.cpp
   ThreadedCommunication.cpp
   UserSettingsController.cpp
@@ -94,6 +95,7 @@ add_lldb_library(lldbCore
     Support
     Demangle
     TargetParser
+    Telemetry
   )
 
 add_dependencies(lldbCore
diff --git a/lldb/source/Core/Telemetry.cpp b/lldb/source/Core/Telemetry.cpp
new file mode 100644
index 00000000000000..5ddad030ef962e
--- /dev/null
+++ b/lldb/source/Core/Telemetry.cpp
@@ -0,0 +1,338 @@
+
+//===-- Telemetry.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "lldb/Core/Telemetry.h"
+
+#include <chrono>
+#include <cstdlib>
+#include <ctime>
+#include <fstream>
+#include <memory>
+#include <string>
+#include <typeinfo>
+#include <utility>
+#include <vector>
+
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Statistics.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/UUID.h"
+#include "lldb/Version/Version.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Telemetry/Telemetry.h"
+
+namespace lldb_private {
+
+using ::llvm::Error;
+using ::llvm::telemetry::Destination;
+using ::llvm::telemetry::TelemetryInfo;
+
+static size_t ToNanosecOrZero(const std::optional<SteadyTimePoint> &Point) {
+  if (!Point.has_value())
+    return 0;
+
+  return Point.value().time_since_epoch().count();
+}
+
+void LldbBaseTelemetryInfo::serialize(Serializer &serializer) const {
+  serializer.writeInt32("EntryKind", getKind());
+  serializer.writeString("SessionId", SessionId);
+}
+
+void DebuggerTelemetryInfo::serialize(Serializer &serializer) const {
+  LldbBaseTelemetryInfo::serialize(serializer);
+  serializer.writeString("username", username);
+  serializer.writeString("lldb_path", lldb_path);
+  serializer.writeString("cwd", cwd);
+  serializer.writeSizeT("start", stats.start.time_since_epoch().count());
+  serializer.writeSizeT("end", ToNanosecOrZero(stats.end));
+}
+
+void ClientTelemetryInfo::serialize(Serializer &serializer) const {
+  LldbBaseTelemetryInfo::serialize(serializer);
+  serializer.writeString("request_name", request_name);
+  serializer.writeString("error_msg", error_msg);
+  serializer.writeSizeT("start", stats.start.time_since_epoch().count());
+  serializer.writeSizeT("end", ToNanosecOrZero(stats.end));
+}
+
+void TargetTelemetryInfo::serialize(Serializer &serializer) const {
+  LldbBaseTelemetryInfo::serialize(serializer);
+  serializer.writeString("target_uuid", target_uuid);
+  serializer.writeString("binary_path", binary_path);
+  serializer.writeSizeT("binary_size", binary_size);
+}
+
+void CommandTelemetryInfo::serialize(Serializer &serializer) const {
+  LldbBaseTelemetryInfo::serialize(serializer);
+  serializer.writeString("target_uuid", target_uuid);
+  serializer.writeString("command_uuid", command_uuid);
+  serializer.writeString("args", args);
+  serializer.writeString("original_command", original_command);
+  serializer.writeSizeT("start", stats.start.time_since_epoch().count());
+  serializer.writeSizeT("end", ToNanosecOrZero(stats.end));
+
+  // If this entry was emitted at the end of the command-execution,
+  // then calculate the runtime too.
+  if (stats.end.has_value()) {
+    serializer.writeSizeT("command_runtime",
+                          (stats.end.value() - stats.start).count());
+    if (exit_desc.has_value()) {
+      serializer.writeInt32("exit_code", exit_desc->exit_code);
+      serializer.writeString("exit_msg", exit_desc->description);
+      serializer.writeInt32("return_status", static_cast<int>(ret_status));
+    }
+  }
+}
+
+void MiscTelemetryInfo::serialize(Serializer &serializer) const {
+  LldbBaseTelemetryInfo::serialize(serializer);
+  serializer.writeString("target_uuid", target_uuid);
+  serializer.writeKeyValueMap("meta_data", meta_data);
+}
+
+static std::string MakeUUID(lldb_private::Debugger *debugger) {
+  std::string ret;
+  uint8_t random_bytes[16];
+  if (auto ec = llvm::getRandomBytes(random_bytes, 16)) {
+    LLDB_LOG(GetLog(LLDBLog::Object),
+             "Failed to generate random bytes for UUID: {0}", ec.message());
+    // fallback to using timestamp + debugger ID.
+    ret = std::to_string(
+              std::chrono::steady_clock::now().time_since_epoch().count()) +
+          "_" + std::to_string(debugger->GetID());
+  } else {
+    ret = lldb_private::UUID(random_bytes).GetAsString();
+  }
+
+  return ret;
+}
+
+TelemetryManager::TelemetryManager(
+    std::unique_ptr<llvm::telemetry::Config> config,
+    lldb_private::Debugger *debugger)
+    : m_config(std::move(config)), m_debugger(debugger),
+      m_session_uuid(MakeUUID(debugger)) {}
+
+std::unique_ptr<TelemetryManager> TelemetryManager::CreateInstance(
+    std::unique_ptr<llvm::telemetry::Config> config,
+    lldb_private::Debugger *debugger) {
+
+  TelemetryManager *ins = new TelemetryManager(std::move(config), debugger);
+
+  return std::unique_ptr<TelemetryManager>(ins);
+}
+
+llvm::Error TelemetryManager::dispatch(TelemetryInfo *entry) {
+  entry->SessionId = m_session_uuid;
+
+  for (auto &destination : m_destinations) {
+    llvm::Error err = destination->receiveEntry(entry);
+    if (err) {
+      return std::move(err);
+    }
+  }
+  return Error::success();
+}
+
+void TelemetryManager::addDestination(
+    std::unique_ptr<Destination> destination) {
+  m_destinations.push_back(std::move(destination));
+}
+
+void TelemetryManager::LogStartup(DebuggerTelemetryInfo *entry) {
+  UserIDResolver &resolver = lldb_private::HostInfo::GetUserIDResolver();
+  std::optional<llvm::StringRef> opt_username =
+      resolver.GetUserName(lldb_private::HostInfo::GetUserID());
+  if (opt_username)
+    entry->username = *opt_username;
+
+  entry->lldb_git_sha =
+      lldb_private::GetVersion(); // TODO: find the real git sha?
+
+  llvm::SmallString<64> cwd;
+  if (!llvm::sys::fs::current_path(cwd)) {
+    entry->cwd = cwd.c_str();
+  } else {
+    MiscTelemetryInfo misc_info;
+    misc_info.meta_data["internal_errors"] = "Cannot determine CWD";
+    if (auto er = dispatch(&misc_info)) {
+      LLDB_LOG(GetLog(LLDBLog::Object),
+               "Failed to dispatch misc-info from startup");
+    }
+  }
+
+  if (auto er = dispatch(entry)) {
+    LLDB_LOG(GetLog(LLDBLog::Object), "Failed to dispatch entry from startup");
+  }
+
+  // Optional part
+  CollectMiscBuildInfo();
+}
+
+void TelemetryManager::LogExit(DebuggerTelemetryInfo *entry) {
+  if (auto *selected_target =
+          m_debugger->GetSelectedExecutionContext().GetTargetPtr()) {
+    if (!selected_target->IsDummyTarget()) {
+      const lldb::ProcessSP proc = selected_target->GetProcessSP();
+      if (proc == nullptr) {
+        // no process has been launched yet.
+        entry->exit_desc = {-1, "no process launched."};
+      } else {
+        entry->exit_desc = {proc->GetExitStatus(), ""};
+        if (const char *description = proc->GetExitDescription())
+          entry->exit_desc->description = std::string(description);
+      }
+    }
+  }
+  dispatch(entry);
+}
+
+void TelemetryManager::LogProcessExit(TargetTelemetryInfo *entry) {
+  entry->target_uuid =
+      entry->target_ptr && !entry->target_ptr->IsDummyTarget()
+          ? entry->target_ptr->GetExecutableModule()->GetUUID().GetAsString()
+          : "";
+
+  dispatch(entry);
+}
+
+void TelemetryManager::CollectMiscBuildInfo() {
+  // collecting use-case specific data
+}
+
+void TelemetryManager::LogMainExecutableLoadStart(TargetTelemetryInfo *entry) {
+  entry->binary_path =
+      entry->exec_mod->GetFileSpec().GetPathAsConstString().GetCString();
+  entry->file_format = entry->exec_mod->GetArchitecture().GetArchitectureName();
+  entry->target_uuid = entry->exec_mod->GetUUID().GetAsString();
+  if (auto err = llvm::sys::fs::file_size(
+          entry->exec_mod->GetFileSpec().GetPath(), entry->binary_size)) {
+    // If there was error obtaining it, just reset the size to 0.
+    // Maybe log the error too?
+    entry->binary_size = 0;
+  }
+  dispatch(entry);
+}
+
+void TelemetryManager::LogMainExecutableLoadEnd(TargetTelemetryInfo *entry) {
+  lldb::ModuleSP exec_mod = entry->exec_mod;
+  entry->binary_path =
+      exec_mod->GetFileSpec().GetPathAsConstString().GetCString();
+  entry->file_format = exec_mod->GetArchitecture().GetArchitectureName();
+  entry->target_uuid = exec_mod->GetUUID().GetAsString();
+  entry->binary_size = exec_mod->GetObjectFile()->GetByteSize();
+
+  dispatch(entry);
+
+  // Collect some more info, might be useful?
+  MiscTelemetryInfo misc_info;
+  misc_info.target_uuid = exec_mod->GetUUID().GetAsString();
+  misc_info.m...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/119716


More information about the llvm-commits mailing list