LLDB mainline
Telemetry.h
Go to the documentation of this file.
1//===-- Telemetry.h -------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_CORE_TELEMETRY_H
10#define LLDB_CORE_TELEMETRY_H
11
16#include "lldb/Utility/UUID.h"
17#include "lldb/lldb-forward.h"
18#include "llvm/ADT/FunctionExtras.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/JSON.h"
22#include "llvm/Telemetry/Telemetry.h"
23#include <atomic>
24#include <chrono>
25#include <ctime>
26#include <functional>
27#include <memory>
28#include <optional>
29#include <string>
30#include <type_traits>
31#include <utility>
32
33namespace lldb_private {
34namespace telemetry {
35
37 // If true, we will collect full details about a debug command (eg., args and
38 // original command). Note: This may contain PII, hence can only be enabled by
39 // the vendor while creating the Manager.
41
42 // If true, we will collect telemetry from LLDB's clients (eg., lldb-dap) via
43 // the SB interface. Must also be enabled by the vendor while creating the
44 // manager.
46
52};
53
54// We expect each (direct) subclass of LLDBTelemetryInfo to
55// have an LLDBEntryKind in the form 0b11xxxxxxxx
56// Specifically:
57// - Length: 8 bits
58// - First two bits (MSB) must be 11 - the common prefix
59// - Last two bits (LSB) are reserved for grand-children of LLDBTelemetryInfo
60// If any of the subclass has descendents, those descendents
61// must have their LLDBEntryKind in the similar form (ie., share common prefix
62// and differ by the last two bits)
64 // clang-format off
65 static const llvm::telemetry::KindType BaseInfo = 0b11000000;
66 static const llvm::telemetry::KindType ClientInfo = 0b11100000;
67 static const llvm::telemetry::KindType CommandInfo = 0b11010000;
68 static const llvm::telemetry::KindType DebuggerInfo = 0b11001000;
69 static const llvm::telemetry::KindType ExecModuleInfo = 0b11000100;
70 static const llvm::telemetry::KindType ProcessExitInfo = 0b11001100;
71 // clang-format on
72};
73
74/// Defines a convenient type for timestamp of various events.
75using SteadyTimePoint = std::chrono::time_point<std::chrono::steady_clock,
76 std::chrono::nanoseconds>;
78 /// Start time of an event
80 /// End time of an event - may be empty if not meaningful.
81 std::optional<SteadyTimePoint> end_time;
82 // TBD: could add some memory stats here too?
83
85 Debugger *debugger = nullptr;
86
87 // For dyn_cast, isa, etc operations.
88 llvm::telemetry::KindType getKind() const override {
90 }
91
93 // Subclasses of this is also acceptable.
94 return (t->getKind() & LLDBEntryKind::BaseInfo) == LLDBEntryKind::BaseInfo;
95 }
96
97 void serialize(llvm::telemetry::Serializer &serializer) const override;
98};
99
101 std::string client_name;
102 std::string client_data;
103 std::optional<std::string> error_msg;
104
105 // For dyn_cast, isa, etc operations.
106 llvm::telemetry::KindType getKind() const override {
108 }
109
111 // Subclasses of this is also acceptable.
112 return (t->getKind() & LLDBEntryKind::ClientInfo) ==
114 }
115
116 void serialize(llvm::telemetry::Serializer &serializer) const override;
117};
118
120 /// If the command is/can be associated with a target entry this field
121 /// contains that target's UUID. <EMPTY> otherwise.
123 /// A unique ID for a command so the manager can match the start entry with
124 /// its end entry. These values only need to be unique within the same
125 /// session. Necessary because we'd send off an entry right before a command's
126 /// execution and another right after. This is to avoid losing telemetry if
127 /// the command does not execute successfully.
128 uint64_t command_id = 0;
129 /// The command name(eg., "breakpoint set")
130 std::string command_name;
131 /// These two fields are not collected by default due to PII risks.
132 /// Vendor may allow them by setting the
133 /// LLDBConfig::detailed_command_telemetry.
134 /// @{
135 std::optional<std::string> original_command;
136 std::optional<std::string> args;
137 /// @}
138 /// Return status of a command and any error description in case of error.
139 std::optional<lldb::ReturnStatus> ret_status;
140 std::optional<std::string> error_data;
141
142 CommandInfo() = default;
143
144 llvm::telemetry::KindType getKind() const override {
146 }
147
149 return (T->getKind() & LLDBEntryKind::CommandInfo) ==
151 }
152
153 void serialize(llvm::telemetry::Serializer &serializer) const override;
154
155 static uint64_t GetNextID();
156
157private:
158 // We assign each command (in the same session) a unique id so that their
159 // "start" and "end" entries can be matched up.
160 // These values don't need to be unique across runs (because they are
161 // secondary-key), hence a simple counter is sufficent.
162 static std::atomic<uint64_t> g_command_id_seed;
163};
164
166 std::string lldb_version;
167
168 bool is_exit_entry = false;
169
170 DebuggerInfo() = default;
171
172 llvm::telemetry::KindType getKind() const override {
174 }
175
177 // Subclasses of this is also acceptable
178 return (T->getKind() & LLDBEntryKind::DebuggerInfo) ==
180 }
181
182 void serialize(llvm::telemetry::Serializer &serializer) const override;
183};
184
187 /// The same as the executable-module's UUID.
189 /// PID of the process owned by this target.
191 /// The triple of this executable module.
192 std::string triple;
193
194 /// If true, this entry was emitted at the beginning of an event (eg., before
195 /// the executable is set). Otherwise, it was emitted at the end of an
196 /// event (eg., after the module and any dependency were loaded.)
197 bool is_start_entry = false;
198
200
201 llvm::telemetry::KindType getKind() const override {
203 }
204
205 static bool classof(const TelemetryInfo *T) {
206 // Subclasses of this is also acceptable
207 return (T->getKind() & LLDBEntryKind::ExecModuleInfo) ==
209 }
210 void serialize(llvm::telemetry::Serializer &serializer) const override;
211};
212
213/// Describes an exit status.
216 std::string description;
217};
218
220 // The executable-module's UUID.
223 bool is_start_entry = false;
224 std::optional<ExitDescription> exit_desc;
225
226 llvm::telemetry::KindType getKind() const override {
228 }
229
230 static bool classof(const TelemetryInfo *T) {
231 // Subclasses of this is also acceptable
232 return (T->getKind() & LLDBEntryKind::ProcessExitInfo) ==
234 }
235 void serialize(llvm::telemetry::Serializer &serializer) const override;
236};
237
238/// The base Telemetry manager instance in LLDB.
239/// This class declares additional instrumentation points
240/// applicable to LLDB.
242public:
243 llvm::Error preDispatch(llvm::telemetry::TelemetryInfo *entry) override;
244
245 const LLDBConfig *GetConfig() { return m_config.get(); }
246
247 virtual void
249 Debugger *debugger);
250 virtual llvm::StringRef GetInstanceName() const = 0;
251
253
254protected:
255 TelemetryManager(std::unique_ptr<LLDBConfig> config);
256
257 inline const std::string &GetSessionId() const { return m_id; }
258
259 static void SetInstance(std::unique_ptr<TelemetryManager> manger);
260
261private:
262 std::unique_ptr<LLDBConfig> m_config;
263 // Each instance of a TelemetryManager is assigned a unique ID.
264 const std::string m_id;
265 static std::unique_ptr<TelemetryManager> g_instance;
266};
267
268/// Helper RAII class for collecting telemetry.
269template <typename Info> struct ScopedDispatcher {
270 // The debugger pointer is optional because we may not have a debugger yet.
271 // In that case, caller must set the debugger later.
273 // Start the timer.
274 m_start_time = std::chrono::steady_clock::now();
275 this->debugger = debugger;
276 }
277 ScopedDispatcher(llvm::unique_function<void(Info *info)> final_callback,
278 Debugger *debugger = nullptr)
279 : m_final_callback(std::move(final_callback)) {
280 // Start the timer.
281 m_start_time = std::chrono::steady_clock::now();
282 this->debugger = debugger;
283 }
284
285 void SetDebugger(Debugger *debugger) { this->debugger = debugger; }
286
287 void DispatchOnExit(llvm::unique_function<void(Info *info)> final_callback) {
288 // We probably should not be overriding previously set cb.
289 assert(!m_final_callback);
290 m_final_callback = std::move(final_callback);
291 }
292
293 void DispatchNow(llvm::unique_function<void(Info *info)> populate_fields_cb) {
295 if (!manager->GetConfig()->EnableTelemetry)
296 return;
297 Info info;
298 // Populate the common fields we know about.
299 info.start_time = m_start_time;
300 info.end_time = std::chrono::steady_clock::now();
301 info.debugger = debugger;
302 // The callback will set the rest.
303 populate_fields_cb(&info);
304 // And then we dispatch.
305 if (llvm::Error er = manager->dispatch(&info)) {
306 LLDB_LOG_ERROR(GetLog(LLDBLog::Object), std::move(er),
307 "Failed to dispatch entry of type {1}: {0}",
308 info.getKind());
309 }
310 }
311
316
317private:
319 llvm::unique_function<void(Info *info)> m_final_callback;
321};
322
323} // namespace telemetry
324} // namespace lldb_private
325#endif // LLDB_CORE_TELEMETRY_H
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
A class to manage flag bits.
Definition Debugger.h:80
Represents UUID's of various sizes.
Definition UUID.h:27
The base Telemetry manager instance in LLDB.
Definition Telemetry.h:241
const std::string & GetSessionId() const
Definition Telemetry.h:257
virtual void DispatchClientTelemetry(const lldb_private::StructuredDataImpl &entry, Debugger *debugger)
static void SetInstance(std::unique_ptr< TelemetryManager > manger)
TelemetryManager(std::unique_ptr< LLDBConfig > config)
llvm::Error preDispatch(llvm::telemetry::TelemetryInfo *entry) override
virtual llvm::StringRef GetInstanceName() const =0
static TelemetryManager * GetInstance()
static std::unique_ptr< TelemetryManager > g_instance
Definition Telemetry.h:265
std::unique_ptr< LLDBConfig > m_config
Definition Telemetry.h:262
#define LLDB_INVALID_UID
#define LLDB_INVALID_PROCESS_ID
std::chrono::time_point< std::chrono::steady_clock, std::chrono::nanoseconds > SteadyTimePoint
Defines a convenient type for timestamp of various events.
Definition Telemetry.h:75
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
uint64_t pid_t
Definition lldb-types.h:83
uint64_t user_id_t
Definition lldb-types.h:82
std::shared_ptr< lldb_private::Module > ModuleSP
void serialize(llvm::telemetry::Serializer &serializer) const override
Definition Telemetry.cpp:55
static bool classof(const llvm::telemetry::TelemetryInfo *t)
Definition Telemetry.h:110
llvm::telemetry::KindType getKind() const override
Definition Telemetry.h:106
std::optional< std::string > error_msg
Definition Telemetry.h:103
void serialize(llvm::telemetry::Serializer &serializer) const override
Definition Telemetry.cpp:63
std::optional< std::string > original_command
These two fields are not collected by default due to PII risks.
Definition Telemetry.h:135
std::string command_name
The command name(eg., "breakpoint set")
Definition Telemetry.h:130
std::optional< lldb::ReturnStatus > ret_status
Return status of a command and any error description in case of error.
Definition Telemetry.h:139
UUID target_uuid
If the command is/can be associated with a target entry this field contains that target's UUID.
Definition Telemetry.h:122
std::optional< std::string > args
Definition Telemetry.h:136
uint64_t command_id
A unique ID for a command so the manager can match the start entry with its end entry.
Definition Telemetry.h:128
static std::atomic< uint64_t > g_command_id_seed
Definition Telemetry.h:162
static bool classof(const llvm::telemetry::TelemetryInfo *T)
Definition Telemetry.h:148
std::optional< std::string > error_data
Definition Telemetry.h:140
llvm::telemetry::KindType getKind() const override
Definition Telemetry.h:144
llvm::telemetry::KindType getKind() const override
Definition Telemetry.h:172
static bool classof(const llvm::telemetry::TelemetryInfo *T)
Definition Telemetry.h:176
void serialize(llvm::telemetry::Serializer &serializer) const override
Definition Telemetry.cpp:82
void serialize(llvm::telemetry::Serializer &serializer) const override
Definition Telemetry.cpp:89
llvm::telemetry::KindType getKind() const override
Definition Telemetry.h:201
std::string triple
The triple of this executable module.
Definition Telemetry.h:192
bool is_start_entry
If true, this entry was emitted at the beginning of an event (eg., before the executable is set).
Definition Telemetry.h:197
static bool classof(const TelemetryInfo *T)
Definition Telemetry.h:205
UUID uuid
The same as the executable-module's UUID.
Definition Telemetry.h:188
lldb::pid_t pid
PID of the process owned by this target.
Definition Telemetry.h:190
SteadyTimePoint start_time
Start time of an event.
Definition Telemetry.h:79
static bool classof(const llvm::telemetry::TelemetryInfo *t)
Definition Telemetry.h:92
void serialize(llvm::telemetry::Serializer &serializer) const override
Definition Telemetry.cpp:47
llvm::telemetry::KindType getKind() const override
Definition Telemetry.h:88
std::optional< SteadyTimePoint > end_time
End time of an event - may be empty if not meaningful.
Definition Telemetry.h:81
LLDBConfig(bool enable_telemetry, bool detailed_command_telemetry, bool enable_client_telemetry)
Definition Telemetry.h:47
static const llvm::telemetry::KindType BaseInfo
Definition Telemetry.h:65
static const llvm::telemetry::KindType DebuggerInfo
Definition Telemetry.h:68
static const llvm::telemetry::KindType ClientInfo
Definition Telemetry.h:66
static const llvm::telemetry::KindType CommandInfo
Definition Telemetry.h:67
static const llvm::telemetry::KindType ProcessExitInfo
Definition Telemetry.h:70
static const llvm::telemetry::KindType ExecModuleInfo
Definition Telemetry.h:69
std::optional< ExitDescription > exit_desc
Definition Telemetry.h:224
llvm::telemetry::KindType getKind() const override
Definition Telemetry.h:226
void serialize(llvm::telemetry::Serializer &serializer) const override
Definition Telemetry.cpp:98
static bool classof(const TelemetryInfo *T)
Definition Telemetry.h:230
ScopedDispatcher(llvm::unique_function< void(Info *info)> final_callback, Debugger *debugger=nullptr)
Definition Telemetry.h:277
void DispatchOnExit(llvm::unique_function< void(Info *info)> final_callback)
Definition Telemetry.h:287
void DispatchNow(llvm::unique_function< void(Info *info)> populate_fields_cb)
Definition Telemetry.h:293
llvm::unique_function< void(Info *info)> m_final_callback
Definition Telemetry.h:319
ScopedDispatcher(Debugger *debugger=nullptr)
Definition Telemetry.h:272
void SetDebugger(Debugger *debugger)
Definition Telemetry.h:285