Skip to content

Commit f152b3b

Browse files
committed
introduce helper
1 parent 19c6181 commit f152b3b

File tree

4 files changed

+110
-102
lines changed

4 files changed

+110
-102
lines changed

lldb/include/lldb/Core/Telemetry.h

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@
2424
#include <optional>
2525
#include <string>
2626
#include <unordered_map>
27+
#include <type_traits>
28+
#include <utility>
29+
#include <functional>
30+
#include <stack>
2731

2832
namespace lldb_private {
2933
namespace telemetry {
3034

3135
struct LLDBEntryKind : public ::llvm::telemetry::EntryKind {
3236
static const llvm::telemetry::KindType BaseInfo = 0b11000;
33-
static const KindType TargetInfo = 0b11010;
37+
static const llvm::telemetry::KindType TargetInfo = 0b11010;
3438
// There are other entries in between (added in separate PRs)
3539
static const llvm::telemetry::KindType MiscInfo = 0b11110;
3640
};
3741

42+
3843
/// Defines a convenient type for timestamp of various events.
3944
using SteadyTimePoint = std::chrono::time_point<std::chrono::steady_clock,
4045
std::chrono::nanoseconds>;
@@ -66,64 +71,26 @@ struct ExitDescription {
6671
std::string description;
6772
};
6873

69-
struct TargetTelemetryInfo : public LldbBaseTelemetryInfo {
74+
75+
struct TargetInfo : public LLDBBaseTelemetryInfo {
7076
lldb::ModuleSP exec_mod;
7177
Target *target_ptr;
7278

7379
// The same as the executable-module's UUID.
7480
std::string target_uuid;
75-
std::string file_format;
76-
77-
std::string binary_path;
78-
size_t binary_size;
81+
std::string executable_path;
82+
size_t executable_size;
83+
std::string arch_name;
7984

8085
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-
}
86+
TargetInfo() = default;
9187

92-
KindType getKind() const override { return LldbEntryKind::TargetInfo; }
88+
llvm::telemetry::KindType getKind() const override { return LLDBEntryKind::TargetInfo; }
9389

9490
static bool classof(const TelemetryInfo *T) {
9591
if (T == nullptr)
9692
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;
93+
return T->getKind() == LLDBEntryKind::TargetInfo;
12794
}
12895

12996
void serialize(llvm::telemetry::Serializer &serializer) const override;
@@ -132,32 +99,68 @@ struct MiscTelemetryInfo : public LLDBBaseTelemetryInfo {
13299
/// The base Telemetry manager instance in LLDB.
133100
/// This class declares additional instrumentation points
134101
/// applicable to LLDB.
135-
class TelemetryMager : public llvm::telemetry::Manager {
102+
class TelemetryManager : public llvm::telemetry::Manager {
136103
public:
137104
llvm::Error preDispatch(llvm::telemetry::TelemetryInfo *entry) override;
138105

139-
const llvm::telemetry::Config *getConfig();
106+
const llvm::telemetry::Config *GetConfig();
140107

108+
/// The following methods are for reporting the load of an executable.
109+
/// One is invoked at the beginning of the process and the other at
110+
/// the end.
111+
/// This is done in two passes to avoid losing date in case of any error/crash
112+
/// during the action.
113+
///
114+
/// Invoked at the begining of the load of the main-executable.
141115
virtual void AtMainExecutableLoadStart(TargetInfo * entry);
116+
/// Invoked at the end of the load.
142117
virtual void AtMainExecutableLoadEnd(TargetInfo *entry);
143118

144-
virtual llvm::StringRef GetInstanceName() const = 0;
145-
static TelemetryManager *getInstance();
119+
virtual llvm::StringRef GetInstanceName() const = 0;
120+
121+
static TelemetryManager *GetInstance();
146122

147123
protected:
148124
TelemetryManager(std::unique_ptr<llvm::telemetry::Config> config);
149125

150-
static void setInstance(std::unique_ptr<TelemetryManager> manger);
126+
static void SetInstance(std::unique_ptr<TelemetryManager> manger);
151127

152128
private:
153129
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;
130+
158131
static std::unique_ptr<TelemetryManager> g_instance;
159132
};
160133

134+
class Helper {
135+
public:
136+
Helper () : m_start(std::chrono::steady_clock::now()) {}
137+
~Helper() {
138+
while(! m_exit_funcs.empty()) {
139+
(m_exit_funcs.top())();
140+
m_exit_funcs.pop();
141+
}
142+
}
143+
144+
bool TelemetryEnabled() {
145+
TelemetryManager* instance = TelemetryManager::GetInstance();
146+
return instance != nullptr && instance->GetConfig()->EnableTelemetry;
147+
}
148+
149+
150+
SteadyTimePoint GetStartTime() {return m_start;}
151+
SteadyTimePoint GetCurrentTime() { return std::chrono::steady_clock::now(); }
152+
153+
template <typename Fp>
154+
void RunAtScopeExit(Fp&& F){
155+
m_exit_funcs.push(std::forward<Fp>(F));
156+
}
157+
158+
private:
159+
const SteadyTimePoint m_start;
160+
std::stack<std::function<void()>> m_exit_funcs;
161+
162+
};
163+
161164
} // namespace telemetry
162165
} // namespace lldb_private
163166
#endif // LLDB_CORE_TELEMETRY_H

lldb/source/Core/Telemetry.cpp

Lines changed: 32 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ void LLDBBaseTelemetryInfo::serialize(Serializer &serializer) const {
6565
void TargetInfo::serialize(Serializer &serializer) const {
6666
LLDBBaseTelemetryInfo::serialize(serializer);
6767

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);
68+
serializer.write("target_uuid", target_uuid);
69+
serializer.write("executable_path", executable_path);
70+
serializer.write("executable_size", executable_size);
71+
serializer.write("arch_name", arch_name);
7272
if (exit_desc.has_value()) {
7373
serializer.write("exit_code", exit_desc->exit_code);
7474
serializer.write("exit_desc", exit_desc->description);
@@ -88,61 +88,50 @@ TelemetryManager::TelemetryManager(std::unique_ptr<Config> config)
8888
: m_config(std::move(config)) {}
8989

9090
llvm::Error TelemetryManager::preDispatch(TelemetryInfo *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-
91+
// Do nothing for now.
92+
// In up-coming patch, this would be where the manager
93+
// attach the session_uuid to the entry.
10394
return llvm::Error::success();
10495
}
10596

106-
const Config *getConfig() { return m_config.get(); }
97+
const Config * TelemetryManager::GetConfig() { return m_config.get(); }
98+
10799

108100
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");
101+
if (entry->exec_mod != nullptr) {
102+
entry->target_uuid = entry->exec_mod->GetUUID().GetAsString();
103+
entry->executalbe_path = entry->exec_mod->GetFileSpec().GetPathAsConstString().GetCString();
104+
if (auto err = llvm::sys::fs::file_size(
105+
entry->exec_mod->GetFileSpec().GetPath(), entry->binary_size)) {
106+
// If there was error obtaining it, just reset the size to 0.
107+
// Maybe log the error too?
108+
entry->binary_size = 0;
129109
}
110+
entry->arch_name = entry->exec_mod->GetArchitecture().GetArchitectureName();
130111
}
131112

132-
if (auto er = dispatch(entry)) {
133-
LLDB_LOG(GetLog(LLDBLog::Object), "Failed to dispatch entry at startup");
113+
if (llvm::Error er = dispatch(entry)) {
114+
LLDB_LOG_ERROR(GetLog(LLDBLog::Object), std::move(er),
115+
"Failed to dispatch entry at main executable load start: {0}");
134116
}
135117
}
136118

137119
void TelemetryManager::AtMainExecutableLoadEnd(TargetInfo *entry) {
138-
// ....
139-
dispatch(entry);
120+
if (entry->exec_mod != nullptr) {
121+
entry->target_uuid = entry->exec_mod->GetUUID().GetAsString();
122+
// We don't need the rest of the data since they are already in the start entry.
123+
124+
if (llvm::Error er = dispatch(entry)) {
125+
LLDB_LOG_ERROR(GetLog(LLDBLog::Object), std::move(er),
126+
"Failed to dispatch entry at main executable load start: {0}");
127+
}
128+
}
140129
}
141130

142131
std::unique_ptr<TelemetryManager> TelemetryManager::g_instance = nullptr;
143-
TelemetryManager *TelemetryManager::getInstance() { return g_instance.get(); }
132+
TelemetryManager *TelemetryManager::GetInstance() { return g_instance.get(); }
144133

145-
void TelemetryManager::setInstance(std::unique_ptr<TelemetryManager> manager) {
134+
void TelemetryManager::SetInstance(std::unique_ptr<TelemetryManager> manager) {
146135
g_instance = std::move(manager);
147136
}
148137

lldb/source/Target/Target.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "lldb/Core/Module.h"
2121
#include "lldb/Core/ModuleSpec.h"
2222
#include "lldb/Core/PluginManager.h"
23+
#include "lldb/Core/Telemetry.h"
2324
#include "lldb/Core/SearchFilter.h"
2425
#include "lldb/Core/Section.h"
2526
#include "lldb/Core/SourceManager.h"
@@ -1558,10 +1559,25 @@ void Target::DidExec() {
15581559

15591560
void Target::SetExecutableModule(ModuleSP &executable_sp,
15601561
LoadDependentFiles load_dependent_files) {
1562+
telemetry::Helper helper;
15611563
Log *log = GetLog(LLDBLog::Target);
15621564
ClearModules(false);
15631565

15641566
if (executable_sp) {
1567+
if (helper.TelemetryEnabled()) {
1568+
telemetry::TargetInfo start_entry;
1569+
start_entry.start_time = helper.GetStartTime();
1570+
start_entry.exec_mod = executable_sp;
1571+
telemetry::TelemetryManager::GetInstance()->AtMainExecutableLoadStart(&start_entry);
1572+
1573+
helper.RunAtScopeExit([&]() {
1574+
telemetry::TargetInfo end_entry;
1575+
end_entry.start_time = helper.GetStartTime();
1576+
end_entry.end_time = helper.GetCurrentTime();
1577+
end_entry.exec_mod = executable_sp;
1578+
telemetry::TelemetryManager::GetInstance()->AtMainExecutableLoadEnd(&end_entry);
1579+
});
1580+
}
15651581
ElapsedTime elapsed(m_stats.GetCreateTime());
15661582
LLDB_SCOPED_TIMERF("Target::SetExecutableModule (executable = '%s')",
15671583
executable_sp->GetFileSpec().GetPath().c_str());

lldb/unittests/Core/TelemetryTest.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ class FakePlugin : public telemetry::TelemetryManager {
6363
}
6464

6565
static void Initialize() {
66-
telemetry::TelemetryManager::setInstance(std::make_unique<FakePlugin>());
66+
telemetry::TelemetryManager::SetInstance(std::make_unique<FakePlugin>());
6767
}
6868

69-
static void Terminate() { telemetry::TelemetryManager::setInstance(nullptr); }
69+
static void Terminate() { telemetry::TelemetryManager::SetInstance(nullptr); }
7070
};
7171

7272
} // namespace lldb_private
@@ -76,7 +76,7 @@ TEST(TelemetryTest, PluginTest) {
7676
// For tests, we just call it directly.
7777
lldb_private::FakePlugin::Initialize();
7878

79-
auto *ins = lldb_private::telemetry::TelemetryManager::getInstance();
79+
auto *ins = lldb_private::telemetry::TelemetryManager::GetInstance();
8080
ASSERT_NE(ins, nullptr);
8181

8282
std::vector<const ::llvm::telemetry::TelemetryInfo *> expected_entries;

0 commit comments

Comments
 (0)