11
11
12
12
#include " lldb/Core/StructuredDataImpl.h"
13
13
#include " lldb/Interpreter/CommandReturnObject.h"
14
+ #include " lldb/Utility/LLDBLog.h"
14
15
#include " lldb/Utility/StructuredData.h"
15
16
#include " lldb/lldb-forward.h"
17
+ #include " llvm/ADT/FunctionExtras.h"
16
18
#include " llvm/ADT/StringExtras.h"
17
19
#include " llvm/ADT/StringRef.h"
18
20
#include " llvm/Support/JSON.h"
22
24
#include < memory>
23
25
#include < optional>
24
26
#include < string>
25
- #include < unordered_map>
26
27
27
28
namespace lldb_private {
28
29
namespace telemetry {
29
30
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)
30
38
struct 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 ;
32
41
};
33
42
34
43
// / Defines a convenient type for timestamp of various events.
@@ -41,6 +50,7 @@ struct LLDBBaseTelemetryInfo : public llvm::telemetry::TelemetryInfo {
41
50
std::optional<SteadyTimePoint> end_time;
42
51
// TBD: could add some memory stats here too?
43
52
53
+ lldb::user_id_t debugger_id = LLDB_INVALID_UID;
44
54
Debugger *debugger;
45
55
46
56
// For dyn_cast, isa, etc operations.
@@ -56,26 +66,93 @@ struct LLDBBaseTelemetryInfo : public llvm::telemetry::TelemetryInfo {
56
66
void serialize (llvm::telemetry::Serializer &serializer) const override ;
57
67
};
58
68
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
+
59
89
// / The base Telemetry manager instance in LLDB.
60
90
// / This class declares additional instrumentation points
61
91
// / applicable to LLDB.
62
92
class TelemetryManager : public llvm ::telemetry::Manager {
63
93
public:
64
94
llvm::Error preDispatch (llvm::telemetry::TelemetryInfo *entry) override ;
65
95
96
+ const llvm::telemetry::Config *GetConfig ();
97
+
66
98
virtual llvm::StringRef GetInstanceName () const = 0;
99
+
67
100
static TelemetryManager *GetInstance ();
68
101
102
+ static TelemetryManager *GetInstanceIfEnabled ();
103
+
69
104
protected:
70
105
TelemetryManager (std::unique_ptr<llvm::telemetry::Config> config);
71
106
72
107
static void SetInstance (std::unique_ptr<TelemetryManager> manger);
73
108
74
109
private:
75
110
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
+
76
114
static std::unique_ptr<TelemetryManager> g_instance;
77
115
};
78
116
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
+
79
156
} // namespace telemetry
80
157
} // namespace lldb_private
81
158
#endif // LLDB_CORE_TELEMETRY_H
0 commit comments