1111
1212#include " lldb/Core/StructuredDataImpl.h"
1313#include " lldb/Interpreter/CommandReturnObject.h"
14+ #include " lldb/Utility/LLDBLog.h"
1415#include " lldb/Utility/StructuredData.h"
1516#include " lldb/lldb-forward.h"
17+ #include " llvm/ADT/FunctionExtras.h"
1618#include " llvm/ADT/StringExtras.h"
1719#include " llvm/ADT/StringRef.h"
1820#include " llvm/Support/JSON.h"
2224#include < memory>
2325#include < optional>
2426#include < string>
25- #include < unordered_map>
2627
2728namespace lldb_private {
2829namespace telemetry {
2930
31+ // We expect each (direct) subclass of LLDBTelemetryInfo to
32+ // have an LLDBEntryKind in the form 0b11xxxxxxxx
33+ // Specifically:
34+ // - Length: 8 bits
35+ // - First two bits (MSB) must be 11 - the common prefix
36+ // If any of the subclass has descendents, those descendents
37+ // must have their LLDBEntryKind in the similar form (ie., share common prefix)
3038struct LLDBEntryKind : public ::llvm::telemetry::EntryKind {
31- static const llvm::telemetry::KindType BaseInfo = 0b11000 ;
39+ static const llvm::telemetry::KindType BaseInfo = 0b11000000 ;
40+ static const llvm::telemetry::KindType DebuggerInfo = 0b11000100 ;
3241};
3342
3443// / Defines a convenient type for timestamp of various events.
@@ -41,6 +50,7 @@ struct LLDBBaseTelemetryInfo : public llvm::telemetry::TelemetryInfo {
4150 std::optional<SteadyTimePoint> end_time;
4251 // TBD: could add some memory stats here too?
4352
53+ lldb::user_id_t debugger_id = LLDB_INVALID_UID;
4454 Debugger *debugger;
4555
4656 // For dyn_cast, isa, etc operations.
@@ -56,26 +66,93 @@ struct LLDBBaseTelemetryInfo : public llvm::telemetry::TelemetryInfo {
5666 void serialize (llvm::telemetry::Serializer &serializer) const override ;
5767};
5868
69+ struct DebuggerInfo : public LLDBBaseTelemetryInfo {
70+ std::string lldb_version;
71+
72+ bool is_exit_entry = false ;
73+
74+ DebuggerInfo () = default ;
75+
76+ llvm::telemetry::KindType getKind () const override {
77+ return LLDBEntryKind::DebuggerInfo;
78+ }
79+
80+ static bool classof (const llvm::telemetry::TelemetryInfo *T) {
81+ // Subclasses of this is also acceptable
82+ return (T->getKind () & LLDBEntryKind::DebuggerInfo) ==
83+ LLDBEntryKind::DebuggerInfo;
84+ }
85+
86+ void serialize (llvm::telemetry::Serializer &serializer) const override ;
87+ };
88+
5989// / The base Telemetry manager instance in LLDB.
6090// / This class declares additional instrumentation points
6191// / applicable to LLDB.
6292class TelemetryManager : public llvm ::telemetry::Manager {
6393public:
6494 llvm::Error preDispatch (llvm::telemetry::TelemetryInfo *entry) override ;
6595
96+ const llvm::telemetry::Config *GetConfig ();
97+
6698 virtual llvm::StringRef GetInstanceName () const = 0;
99+
67100 static TelemetryManager *GetInstance ();
68101
102+ static TelemetryManager *GetInstanceIfEnabled ();
103+
69104protected:
70105 TelemetryManager (std::unique_ptr<llvm::telemetry::Config> config);
71106
72107 static void SetInstance (std::unique_ptr<TelemetryManager> manger);
73108
74109private:
75110 std::unique_ptr<llvm::telemetry::Config> m_config;
111+ // Each instance of a TelemetryManager is assigned a unique ID.
112+ const std::string m_id;
113+
76114 static std::unique_ptr<TelemetryManager> g_instance;
77115};
78116
117+ // / Helper RAII class for collecting telemetry.
118+ template <typename Info> struct ScopedDispatcher {
119+ // The debugger pointer is optional because we may not have a debugger yet.
120+ // In that case, caller must set the debugger later.
121+ ScopedDispatcher (llvm::unique_function<void (Info *info)> callback,
122+ Debugger *debugger = nullptr )
123+ : m_callback(std::move(callback)) {
124+ // Start the timer.
125+ m_start_time = std::chrono::steady_clock::now ();
126+ m_info.debugger = debugger;
127+ }
128+
129+ void SetDebugger (Debugger *debugger) { m_info.debugger = debugger; }
130+
131+ ~ScopedDispatcher () {
132+ // If Telemetry is disabled (either at buildtime or runtime),
133+ // then don't do anything.
134+ TelemetryManager *manager = TelemetryManager::GetInstanceIfEnabled ();
135+ if (!manager)
136+ return ;
137+
138+ m_info.start_time = m_start_time;
139+ // Populate common fields that we can only set now.
140+ m_info.end_time = std::chrono::steady_clock::now ();
141+ // The callback will set the remaining fields.
142+ m_callback (&m_info);
143+ // And then we dispatch.
144+ if (llvm::Error er = manager->dispatch (&m_info)) {
145+ LLDB_LOG_ERROR (GetLog (LLDBLog::Object), std::move (er),
146+ " Failed to dispatch entry of type: {0}" , m_info.getKind ());
147+ }
148+ }
149+
150+ private:
151+ SteadyTimePoint m_start_time;
152+ llvm::unique_function<void (Info *info)> m_callback;
153+ Info m_info;
154+ };
155+
79156} // namespace telemetry
80157} // namespace lldb_private
81158#endif // LLDB_CORE_TELEMETRY_H
0 commit comments