Skip to content

Commit 0d6a36d

Browse files
committed
[LLDB][Telemetry]Define TargetInfo for collecting data about a target
1 parent 5ecce45 commit 0d6a36d

File tree

2 files changed

+170
-15
lines changed

2 files changed

+170
-15
lines changed

lldb/include/lldb/Core/Telemetry.h

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "lldb/Interpreter/CommandReturnObject.h"
1414
#include "lldb/Utility/StructuredData.h"
1515
#include "lldb/lldb-forward.h"
16+
#include "llvm/ADT/DenseMap.h"
1617
#include "llvm/ADT/StringExtras.h"
1718
#include "llvm/ADT/StringRef.h"
1819
#include "llvm/Support/JSON.h"
@@ -29,6 +30,9 @@ namespace telemetry {
2930

3031
struct LLDBEntryKind : public ::llvm::telemetry::EntryKind {
3132
static const llvm::telemetry::KindType BaseInfo = 0b11000;
33+
static const KindType TargetInfo = 0b11010;
34+
// There are other entries in between (added in separate PRs)
35+
static const llvm::telemetry::KindType MiscInfo = 0b11110;
3236
};
3337

3438
/// Defines a convenient type for timestamp of various events.
@@ -56,14 +60,88 @@ struct LLDBBaseTelemetryInfo : public llvm::telemetry::TelemetryInfo {
5660
void serialize(llvm::telemetry::Serializer &serializer) const override;
5761
};
5862

63+
/// Describes an exit status.
64+
struct ExitDescription {
65+
int exit_code;
66+
std::string description;
67+
};
68+
69+
struct TargetTelemetryInfo : public LldbBaseTelemetryInfo {
70+
lldb::ModuleSP exec_mod;
71+
Target *target_ptr;
72+
73+
// The same as the executable-module's UUID.
74+
std::string target_uuid;
75+
std::string file_format;
76+
77+
std::string binary_path;
78+
size_t binary_size;
79+
80+
std::optional<ExitDescription> exit_desc;
81+
TargetTelemetryInfo() = default;
82+
83+
TargetTelemetryInfo(const TargetTelemetryInfo &other) {
84+
exec_mod = other.exec_mod;
85+
target_uuid = other.target_uuid;
86+
file_format = other.file_format;
87+
binary_path = other.binary_path;
88+
binary_size = other.binary_size;
89+
exit_desc = other.exit_desc;
90+
}
91+
92+
KindType getKind() const override { return LldbEntryKind::TargetInfo; }
93+
94+
static bool classof(const TelemetryInfo *T) {
95+
if (T == nullptr)
96+
return false;
97+
return T->getKind() == LldbEntryKind::TargetInfo;
98+
}
99+
100+
void serialize(Serializer &serializer) const override;
101+
};
102+
103+
/// The "catch-all" entry to store a set of non-standard data, such as
104+
/// error-messages, etc.
105+
struct MiscTelemetryInfo : public LLDBBaseTelemetryInfo {
106+
/// If the event is/can be associated with a target entry,
107+
/// this field contains that target's UUID.
108+
/// <EMPTY> otherwise.
109+
std::string target_uuid;
110+
111+
/// Set of key-value pairs for any optional (or impl-specific) data
112+
std::map<std::string, std::string> meta_data;
113+
114+
MiscTelemetryInfo() = default;
115+
116+
MiscTelemetryInfo(const MiscTelemetryInfo &other) {
117+
target_uuid = other.target_uuid;
118+
meta_data = other.meta_data;
119+
}
120+
121+
llvm::telemetry::KindType getKind() const override {
122+
return LLDBEntryKind::MiscInfo;
123+
}
124+
125+
static bool classof(const llvm::telemetry::TelemetryInfo *T) {
126+
return T->getKind() == LLDBEntryKind::MiscInfo;
127+
}
128+
129+
void serialize(llvm::telemetry::Serializer &serializer) const override;
130+
};
131+
59132
/// The base Telemetry manager instance in LLDB.
60133
/// This class declares additional instrumentation points
61134
/// applicable to LLDB.
62-
class TelemetryManager : public llvm::telemetry::Manager {
135+
class TelemetryMager : public llvm::telemetry::Manager {
63136
public:
64137
llvm::Error preDispatch(llvm::telemetry::TelemetryInfo *entry) override;
65138

66-
virtual llvm::StringRef GetInstanceName() const = 0;
139+
const llvm::telemetry::Config *getConfig();
140+
141+
virtual void AtMainExecutableLoadStart(TargetInfo * entry);
142+
virtual void AtMainExecutableLoadEnd(TargetInfo *entry);
143+
144+
virtual llvm::StringRef GetInstanceName() const = 0;
67145
static TelemetryManager *getInstance();
68146

69147
protected:
@@ -73,6 +151,10 @@ class TelemetryManager : public llvm::telemetry::Manager {
73151

74152
private:
75153
std::unique_ptr<llvm::telemetry::Config> m_config;
154+
// Each debugger is assigned a unique ID (session_id).
155+
// All TelemetryInfo entries emitted for the same debugger instance
156+
// will get the same session_id.
157+
llvm::DenseMap<Debugger *, std::string> session_ids;
76158
static std::unique_ptr<TelemetryManager> g_instance;
77159
};
78160

lldb/source/Core/Telemetry.cpp

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@
1010

1111
#ifdef LLVM_BUILD_TELEMETRY
1212

13-
#include "lldb/Core/Telemetry.h"
1413
#include "lldb/Core/Debugger.h"
14+
#include "lldb/Core/Telemetry.h"
15+
#include "lldb/Host/FileSystem.h"
16+
#include "lldb/Host/HostInfo.h"
17+
#include "lldb/Target/Process.h"
18+
#include "lldb/Target/Statistics.h"
1519
#include "lldb/Utility/LLDBLog.h"
1620
#include "lldb/Utility/UUID.h"
21+
#include "lldb/Version/Version.h"
1722
#include "lldb/lldb-enumerations.h"
1823
#include "lldb/lldb-forward.h"
1924
#include "llvm/ADT/StringRef.h"
2025
#include "llvm/Support/Error.h"
26+
#include "llvm/Support/Path.h"
2127
#include "llvm/Support/RandomNumberGenerator.h"
2228
#include "llvm/Telemetry/Telemetry.h"
2329
#include <chrono>
@@ -35,15 +41,7 @@ static uint64_t ToNanosec(const SteadyTimePoint Point) {
3541
return std::chrono::nanoseconds(Point.time_since_epoch()).count();
3642
}
3743

38-
void LLDBBaseTelemetryInfo::serialize(Serializer &serializer) const {
39-
serializer.write("entry_kind", getKind());
40-
serializer.write("session_id", SessionId);
41-
serializer.write("start_time", ToNanosec(start_time));
42-
if (end_time.has_value())
43-
serializer.write("end_time", ToNanosec(end_time.value()));
44-
}
45-
46-
[[maybe_unused]] static std::string MakeUUID(Debugger *debugger) {
44+
static std::string MakeUUID(Debugger *debugger) {
4745
uint8_t random_bytes[16];
4846
if (auto ec = llvm::getRandomBytes(random_bytes, 16)) {
4947
LLDB_LOG(GetLog(LLDBLog::Object),
@@ -56,16 +54,91 @@ void LLDBBaseTelemetryInfo::serialize(Serializer &serializer) const {
5654
return UUID(random_bytes).GetAsString();
5755
}
5856

57+
void LLDBBaseTelemetryInfo::serialize(Serializer &serializer) const {
58+
serializer.write("entry_kind", getKind());
59+
serializer.write("session_id", SessionId);
60+
serializer.write("start_time", ToNanosec(start_time));
61+
if (end_time.has_value())
62+
serializer.write("end_time", ToNanosec(end_time.value()));
63+
}
64+
65+
void TargetInfo::serialize(Serializer &serializer) const {
66+
LLDBBaseTelemetryInfo::serialize(serializer);
67+
68+
serializer.write("username", username);
69+
serializer.write("lldb_git_sha", lldb_git_sha);
70+
serializer.write("lldb_path", lldb_path);
71+
serializer.write("cwd", cwd);
72+
if (exit_desc.has_value()) {
73+
serializer.write("exit_code", exit_desc->exit_code);
74+
serializer.write("exit_desc", exit_desc->description);
75+
}
76+
}
77+
78+
void MiscTelemetryInfo::serialize(Serializer &serializer) const {
79+
LLDBBaseTelemetryInfo::serialize(serializer);
80+
serializer.write("target_uuid", target_uuid);
81+
serializer.beginObject("meta_data");
82+
for (const auto &kv : meta_data)
83+
serializer.write(kv.first, kv.second);
84+
serializer.endObject();
85+
}
86+
5987
TelemetryManager::TelemetryManager(std::unique_ptr<Config> config)
6088
: m_config(std::move(config)) {}
6189

6290
llvm::Error TelemetryManager::preDispatch(TelemetryInfo *entry) {
63-
// Do nothing for now.
64-
// In up-coming patch, this would be where the manager
65-
// attach the session_uuid to the entry.
91+
LLDBBaseTelemetryInfo *lldb_entry =
92+
llvm::dyn_cast<LLDBBaseTelemetryInfo>(entry);
93+
std::string session_id = "";
94+
if (Debugger *debugger = lldb_entry->debugger) {
95+
auto session_id_pos = session_ids.find(debugger);
96+
if (session_id_pos != session_ids.end())
97+
session_id = session_id_pos->second;
98+
else
99+
session_id_pos->second = session_id = MakeUUID(debugger);
100+
}
101+
lldb_entry->SessionId = session_id;
102+
66103
return llvm::Error::success();
67104
}
68105

106+
const Config *getConfig() { return m_config.get(); }
107+
108+
void TelemetryManager::AtMainExecutableLoadStart(TargetInfo *entry) {
109+
UserIDResolver &resolver = lldb_private::HostInfo::GetUserIDResolver();
110+
std::optional<llvm::StringRef> opt_username =
111+
resolver.GetUserName(lldb_private::HostInfo::GetUserID());
112+
if (opt_username)
113+
entry->username = *opt_username;
114+
115+
entry->lldb_git_sha =
116+
lldb_private::GetVersion(); // TODO: find the real git sha?
117+
118+
entry->lldb_path = HostInfo::GetProgramFileSpec().GetPath();
119+
120+
llvm::SmallString<64> cwd;
121+
if (!llvm::sys::fs::current_path(cwd)) {
122+
entry->cwd = cwd.c_str();
123+
} else {
124+
MiscTelemetryInfo misc_info;
125+
misc_info.meta_data["internal_errors"] = "Cannot determine CWD";
126+
if (auto er = dispatch(&misc_info)) {
127+
LLDB_LOG(GetLog(LLDBLog::Object),
128+
"Failed to dispatch misc-info at startup");
129+
}
130+
}
131+
132+
if (auto er = dispatch(entry)) {
133+
LLDB_LOG(GetLog(LLDBLog::Object), "Failed to dispatch entry at startup");
134+
}
135+
}
136+
137+
void TelemetryManager::AtMainExecutableLoadEnd(TargetInfo *entry) {
138+
// ....
139+
dispatch(entry);
140+
}
141+
69142
std::unique_ptr<TelemetryManager> TelemetryManager::g_instance = nullptr;
70143
TelemetryManager *TelemetryManager::getInstance() { return g_instance.get(); }
71144

0 commit comments

Comments
 (0)