Skip to content

Commit 990e1ca

Browse files
committed
finish up todos
1 parent ed8a3f1 commit 990e1ca

File tree

3 files changed

+136
-14
lines changed

3 files changed

+136
-14
lines changed

llvm/docs/Telemetry.rst

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,128 @@ The framework is consisted of four important classes:
8686
How to implement and interact with the API
8787
------------------------------------------
8888

89-
// TODO: walk through a simple usage here.
89+
To use Telemetry in your tool, you need to provide a concrete implementation of the `Telemeter` class and `Destination`.
90+
91+
1) Define a custom `Telemeter` and `Destination`
92+
93+
.. code-block:: c++
94+
// This destiantion just prints the given entry to a stdout.
95+
// In "real life", this would be where you forward the data to your
96+
// custom data storage.
97+
class MyStdoutDestination : public llvm::telemetry::Destiantion {
98+
public:
99+
Error emitEntry(const TelemetryInfo* Entry) override {
100+
return sendToBlackBox(Entry);
101+
102+
}
103+
104+
private:
105+
Error sendToBlackBox(const TelemetryInfo* Entry) {
106+
// This could send the data anywhere.
107+
// But we're simply sending it to stdout for the example.
108+
llvm::outs() << entryToString(Entry) << "\n";
109+
return llvm::success();
110+
}
111+
112+
std::string entryToString(const TelemetryInfo* Entry) {
113+
// make a string-representation of the given entry.
114+
}
115+
};
116+
117+
// This defines a custom TelemetryInfo that has an addition Msg field.
118+
struct MyTelemetryInfo : public llvm::telemetry::TelemetryInfo {
119+
std::string Msg;
120+
121+
json::Object serializeToJson() const {
122+
json::Object Ret = TelemeteryInfo::serializeToJson();
123+
Ret.emplace_back("MyMsg", Msg);
124+
return std::move(Ret);
125+
}
126+
127+
// TODO: implement getKind() and classof() to support dyn_cast operations.
128+
};
129+
130+
class MyTelemeter : public llvm::telemery::Telemeter {
131+
public:
132+
static std::unique_ptr<MyTelemeter> createInstatnce(llvm::telemetry::Config* config) {
133+
// If Telemetry is not enabled, then just return null;
134+
if (!config->EnableTelemetry) return nullptr;
135+
136+
std::make_unique<MyTelemeter>();
137+
}
138+
MyTelemeter() = default;
139+
140+
void logStartup(llvm::StringRef ToolName, TelemetryInfo* Entry) override {
141+
if (MyTelemetryInfo* M = dyn_cast<MyTelemetryInfo>(Entry)) {
142+
M->Msg = "Starting up tool with name: " + ToolName;
143+
emitToAllDestinations(M);
144+
} else {
145+
emitToAllDestinations(Entry);
146+
}
147+
}
148+
149+
void logExit(llvm::StringRef ToolName, TelemetryInfo* Entry) override {
150+
if (MyTelemetryInfo* M = dyn_cast<MyTelemetryInfo>(Entry)) {
151+
M->Msg = "Exitting tool with name: " + ToolName;
152+
emitToAllDestinations(M);
153+
} else {
154+
emitToAllDestinations(Entry);
155+
}
156+
}
157+
158+
void addDestination(Destination* dest) override {
159+
destinations.push_back(dest);
160+
}
161+
162+
// You can also define additional instrumentation points.)
163+
void logAdditionalPoint(TelemetryInfo* Entry) {
164+
// .... code here
165+
}
166+
private:
167+
void emitToAllDestinations(const TelemetryInfo* Entry) {
168+
// Note: could do this in paralle, if needed.
169+
for (Destination* Dest : Destinations)
170+
Dest->emitEntry(Entry);
171+
}
172+
std::vector<Destination> Destinations;
173+
};
174+
175+
2) Use the library in your tool.
176+
177+
Logging the tool init-process:
178+
179+
.. code-block:: c++
180+
181+
// At tool's init code
182+
auto StartTime = std::chrono::time_point<std::chrono::steady_clock>::now();
183+
llvm::telemetry::Config MyConfig = makeConfig(); // build up the appropriate Config struct here.
184+
auto Telemeter = MyTelemeter::createInstance(&MyConfig);
185+
std::string CurrentSessionId = ...; // Make some unique ID corresponding to the current session here.
186+
187+
// Any other tool's init code can go here
188+
// ...
189+
190+
// Finally, take a snapshot of the time now so we know how long it took the
191+
// init process to finish
192+
auto EndTime = std::chrono::time_point<std::chrono::steady_clock>::now();
193+
MyTelemetryInfo Entry;
194+
Entry.SessionId = CurrentSessionId ; // Assign some unique ID here.
195+
Entry.Stats = {StartTime, EndTime};
196+
Telemeter->logStartup("MyTool", &Entry);
197+
198+
Similar code can be used for logging the tool's exit.
199+
200+
Additionall, at any other point in the tool's lifetime, it can also log telemetry:
201+
202+
.. code-block:: c++
203+
204+
// At some execution point:
205+
auto StartTime = std::chrono::time_point<std::chrono::steady_clock>::now();
206+
207+
// ... other events happening here
208+
209+
auto EndTime = std::chrono::time_point<std::chrono::steady_clock>::now();
210+
MyTelemetryInfo Entry;
211+
Entry.SessionId = CurrentSessionId ; // Assign some unique ID here.
212+
Entry.Stats = {StartTime, EndTime};
213+
Telemeter->logAdditionalPoint(&Entry);

llvm/include/llvm/Telemetry/Telemetry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ struct EntryKind {
9393
};
9494

9595
/// TelemetryInfo is the data courier, used to move instrumented data
96-
/// the tool being monitored to the Telemery framework.
96+
/// from the tool being monitored to the Telemery framework.
9797
///
9898
/// This base class contains only the basic set of telemetry data.
9999
/// Downstream implementations can add more fields as needed to describe

llvm/unittests/Telemetry/TelemetryTest.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,6 @@ class TestTelemeter : public Telemeter {
318318
TestTelemeter(std::string SessionId) : Uuid(SessionId), Counter(0) {}
319319

320320
static std::unique_ptr<TestTelemeter> createInstance(Config *config) {
321-
llvm::errs() << "============================== createInstance is called"
322-
<< "\n";
323321
if (!config->EnableTelemetry)
324322
return nullptr;
325323
CurrentContext->ExpectedUuid = nextUuid();
@@ -348,7 +346,7 @@ class TestTelemeter : public Telemeter {
348346

349347
// The vendor can add additional stuff to the entry before logging.
350348
if (auto *S = dyn_cast<StartupEvent>(Entry)) {
351-
S->MagicStartupMsg = llvm::Twine("One_", ToolPath).str();
349+
S->MagicStartupMsg = llvm::Twine("Startup_", ToolPath).str();
352350
}
353351
emitToDestinations(Entry);
354352
}
@@ -364,7 +362,7 @@ class TestTelemeter : public Telemeter {
364362

365363
// The vendor can add additional stuff to the entry before logging.
366364
if (auto *E = dyn_cast<ExitEvent>(Entry)) {
367-
E->MagicExitMsg = llvm::Twine("Three_", ToolPath).str();
365+
E->MagicExitMsg = llvm::Twine("Exit_", ToolPath).str();
368366
}
369367

370368
emitToDestinations(Entry);
@@ -549,11 +547,11 @@ TEST(TelemetryTest, TelemetryEnabled) {
549547
{
550548
std::string ExpectedBuffer =
551549
("SessionId:" + llvm::Twine(CurrentContext->ExpectedUuid) + "\n" +
552-
"MagicStartupMsg:One_" + llvm::Twine(ToolName) + "\n" +
550+
"MagicStartupMsg:Startup_" + llvm::Twine(ToolName) + "\n" +
553551
"SessionId:" + llvm::Twine(CurrentContext->ExpectedUuid) + "\n" +
554552
"MSG_0:Two\n" + "MSG_1:Deux\n" + "MSG_2:Zwei\n" +
555553
"SessionId:" + llvm::Twine(CurrentContext->ExpectedUuid) + "\n" +
556-
"MagicExitMsg:Three_" + llvm::Twine(ToolName) + "\n")
554+
"MagicExitMsg:Exit_" + llvm::Twine(ToolName) + "\n")
557555
.str();
558556

559557
EXPECT_STREQ(ExpectedBuffer.c_str(), CurrentContext->Buffer.c_str());
@@ -570,7 +568,7 @@ TEST(TelemetryTest, TelemetryEnabled) {
570568
ASSERT_NE(StartupEntry, nullptr);
571569
EXPECT_STREQ(
572570
("[[\"SessionId\",\"" + llvm::Twine(CurrentContext->ExpectedUuid) +
573-
"\"],[\"MagicStartupMsg\",\"One_" + llvm::Twine(ToolName) + "\"]]")
571+
"\"],[\"MagicStartupMsg\",\"Startup_" + llvm::Twine(ToolName) + "\"]]")
574572
.str()
575573
.c_str(),
576574
ValueToString(StartupEntry).c_str());
@@ -592,7 +590,7 @@ TEST(TelemetryTest, TelemetryEnabled) {
592590
ASSERT_NE(ExitEntry, nullptr);
593591
EXPECT_STREQ(
594592
("[[\"SessionId\",\"" + llvm::Twine(CurrentContext->ExpectedUuid) +
595-
"\"],[\"MagicExitMsg\",\"Three_" + llvm::Twine(ToolName) + "\"]]")
593+
"\"],[\"MagicExitMsg\",\"Exit_" + llvm::Twine(ToolName) + "\"]]")
596594
.str()
597595
.c_str(),
598596
ValueToString(ExitEntry).c_str());
@@ -629,12 +627,12 @@ TEST(TelemetryTest, TelemetryEnabledSanitizeData) {
629627
// The StringDestination should have removed the odd-positioned msgs.
630628
std::string ExpectedBuffer =
631629
("SessionId:" + llvm::Twine(CurrentContext->ExpectedUuid) + "\n" +
632-
"MagicStartupMsg:One_" + llvm::Twine(ToolName) + "\n" +
630+
"MagicStartupMsg:Startup_" + llvm::Twine(ToolName) + "\n" +
633631
"SessionId:" + llvm::Twine(CurrentContext->ExpectedUuid) + "\n" +
634632
"MSG_0:Two\n" + "MSG_1:\n" + // <<< was sanitized away.
635633
"MSG_2:Zwei\n" +
636634
"SessionId:" + llvm::Twine(CurrentContext->ExpectedUuid) + "\n" +
637-
"MagicExitMsg:Three_" + llvm::Twine(ToolName) + "\n")
635+
"MagicExitMsg:Exit_" + llvm::Twine(ToolName) + "\n")
638636
.str();
639637
EXPECT_STREQ(ExpectedBuffer.c_str(), CurrentContext->Buffer.c_str());
640638
}
@@ -650,7 +648,7 @@ TEST(TelemetryTest, TelemetryEnabledSanitizeData) {
650648
ASSERT_NE(StartupEntry, nullptr);
651649
EXPECT_STREQ(
652650
("[[\"SessionId\",\"" + llvm::Twine(CurrentContext->ExpectedUuid) +
653-
"\"],[\"MagicStartupMsg\",\"One_" + llvm::Twine(ToolName) + "\"]]")
651+
"\"],[\"MagicStartupMsg\",\"Startup_" + llvm::Twine(ToolName) + "\"]]")
654652
.str()
655653
.c_str(),
656654
ValueToString(StartupEntry).c_str());
@@ -670,7 +668,7 @@ TEST(TelemetryTest, TelemetryEnabledSanitizeData) {
670668
ASSERT_NE(ExitEntry, nullptr);
671669
EXPECT_STREQ(
672670
("[[\"SessionId\",\"" + llvm::Twine(CurrentContext->ExpectedUuid) +
673-
"\"],[\"MagicExitMsg\",\"Three_" + llvm::Twine(ToolName) + "\"]]")
671+
"\"],[\"MagicExitMsg\",\"Exit_" + llvm::Twine(ToolName) + "\"]]")
674672
.str()
675673
.c_str(),
676674
ValueToString(ExitEntry).c_str());

0 commit comments

Comments
 (0)