-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[llvm]Add a simple Telemetry framework #102323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
dbb8b15
6e43f67
e25f5fc
ad3906c
24d07d6
0057bcf
750e4ac
1378ed4
02e750e
63e99fc
fa88512
0866f64
a8523f7
47e8b06
690c6ab
db668f4
0290a14
14b5234
6ca87e5
4155add
11ead4a
48228ee
ed8a3f1
990e1ca
479cd13
6d8aee2
3a17dbb
a6a6c7b
f30dec6
fd3da20
60616ef
8c0ac5a
c8be829
1393c1f
eb07577
0376abc
e2f7c23
17dfac7
1ea0906
39fd0e7
67b7688
efd25d8
4a8276f
a16344b
26ee5eb
b766e3c
c8cddab
5f8d65f
dffeacd
398ed3e
e462908
df8a9af
70f4742
8eab77a
f9e1a65
2a1fbe5
6e3a85d
f9b1cce
0f38a74
ad57099
a2fcd4d
628e7e9
6ea4e92
08cf32f
3c52401
07f06c0
06e746e
2476294
5ce406c
fd57d06
a8a878b
54eeaba
32dfc6a
0893c5b
155f243
b255e3a
14d1c92
bf2172d
c2dcb7d
bbe9009
e2036c6
05947d5
f1100bb
2f64b29
a5df7a0
585fee8
3812cda
0cdc240
da8056f
c116074
a4e2799
2763d46
75c1b4b
9780ec7
4715743
d231bf2
1941b1f
bd3df5e
4351b94
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,16 +8,12 @@ Telemetry framework in LLVM | |
| .. toctree:: | ||
| :hidden: | ||
|
|
||
| =========================== | ||
| Telemetry framework in LLVM | ||
| =========================== | ||
|
|
||
| Objective | ||
| ========= | ||
|
|
||
| Provides a common framework in LLVM for collecting various usage and performance | ||
| metrics. | ||
| It is located at ``llvm/Telemetry/Telemetry.h`` | ||
| It is located at ``llvm/Telemetry/Telemetry.h``. | ||
|
|
||
| Characteristics | ||
| --------------- | ||
|
|
@@ -93,13 +89,13 @@ To use Telemetry in your tool, you need to provide a concrete implementation of | |
|
|
||
| class JsonSerializer : public Serializer { | ||
| public: | ||
| json::Object *getOutputObject() { return object.get(); } | ||
| json::Object *getOutputObject() { return Out.get(); } | ||
|
|
||
| llvm::Error init() override { | ||
| if (started) | ||
| if (Started) | ||
| return createStringError("Serializer already in use"); | ||
| started = true; | ||
| object = std::make_unique<json::Object>(); | ||
| Out = std::make_unique<json::Object>(); | ||
| return Error::success(); | ||
| } | ||
|
|
||
|
|
@@ -112,71 +108,71 @@ To use Telemetry in your tool, you need to provide a concrete implementation of | |
| writeHelper(KeyName, Value); | ||
| } | ||
|
|
||
| void write(StringRef KeyName, size_t Value) override { | ||
| void write(StringRef KeyName, unsigned long long Value) override { | ||
| writeHelper(KeyName, Value); | ||
| } | ||
| void write(StringRef KeyName, StringRef Value) override { | ||
| writeHelper(KeyName, Value); | ||
| } | ||
|
|
||
| void write(StringRef KeyName, | ||
|
||
| const std::map<std::string, std::string>& Value) override { | ||
| const std::map<std::string, std::string> &Value) override { | ||
| json::Object Inner; | ||
| for (auto kv : Value) { | ||
| Inner.try_emplace(kv.first, kv.second); | ||
| for (auto KV : Value) { | ||
| Inner.try_emplace(KV.first, KV.second); | ||
| } | ||
| writeHelper(KeyName, json::Value(std::move(Inner))); | ||
| } | ||
|
|
||
| Error finalize() override { | ||
| if (!started) | ||
| if (!Started) | ||
| return createStringError("Serializer not currently in use"); | ||
| started = false; | ||
| Started = false; | ||
| return Error::success(); | ||
| } | ||
|
|
||
| private: | ||
| template <typename T> void writeHelper(StringRef Name, T Value) { | ||
| assert(started && "serializer not started"); | ||
| object->try_emplace(Name, Value); | ||
| Out->try_emplace(Name, Value); | ||
| } | ||
| bool started = false; | ||
| std::unique_ptr<json::Object> object; | ||
| bool Started = false; | ||
| std::unique_ptr<json::Object> Out; | ||
| }; | ||
|
|
||
| class MyManager : public telemery::Manager { | ||
| public: | ||
| static std::unique_ptr<MyManager> createInstatnce(telemetry::Config* config) { | ||
| static std::unique_ptr<MyManager> createInstatnce(telemetry::Config *config) { | ||
oontvoo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // If Telemetry is not enabled, then just return null; | ||
| if (!config->EnableTelemetry) return nullptr; | ||
oontvoo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| return std::make_unique<MyManager>(); | ||
| } | ||
| MyManager() = default; | ||
|
|
||
| Error dispatch(TelemetryInfo* Entry) const override { | ||
| Error dispatch(TelemetryInfo *Entry) const override { | ||
| Entry->SessionId = SessionId; | ||
| emitToAllDestinations(Entry); | ||
| } | ||
|
|
||
| void addDestination(std::unique_ptr<Destination> dest) override { | ||
| destinations.push_back(std::move(dest)); | ||
| void addDestination(std::unique_ptr<Destination> Dest) override { | ||
| destinations.push_back(std::move(Dest)); | ||
| } | ||
|
|
||
| // You can also define additional instrumentation points. | ||
| void logStartup(TelemetryInfo* Entry) { | ||
| void logStartup(TelemetryInfo *Entry) { | ||
| // Add some additional data to entry. | ||
| Entry->Msg = "Some message"; | ||
| dispatch(Entry); | ||
| } | ||
|
|
||
| void logAdditionalPoint(TelemetryInfo* Entry) { | ||
| void logAdditionalPoint(TelemetryInfo Entry) { | ||
oontvoo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // .... code here | ||
| } | ||
|
|
||
| private: | ||
| void emitToAllDestinations(const TelemetryInfo* Entry) { | ||
| for (Destination* Dest : Destinations) { | ||
| void emitToAllDestinations(const TelemetryInfo *Entry) { | ||
| for (Destination *Dest : Destinations) { | ||
| Dest->receiveEntry(Entry); | ||
| } | ||
| } | ||
|
|
@@ -187,31 +183,31 @@ To use Telemetry in your tool, you need to provide a concrete implementation of | |
|
|
||
| class MyDestination : public telemetry::Destination { | ||
| public: | ||
| Error receiveEntry(const TelemetryInfo* Entry) override { | ||
| if (Error err = serializer.init()) { | ||
| return err; | ||
| Error receiveEntry(const TelemetryInfo *Entry) override { | ||
| if (Error Err = Serializer.init()) { | ||
oontvoo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return Err; | ||
| } | ||
| Entry->serialize(serializer); | ||
| if (Error err = serializer.finalize()) { | ||
| return err; | ||
| Entry->serialize(Serializer); | ||
| if (Error Err = Serializer.finalize()) { | ||
| return Err; | ||
| } | ||
|
|
||
| json::Object copied = *serializer.getOutputObject(); | ||
| // Send the `copied` object to wherever. | ||
| json::Object Copied = *Serializer.getOutputObject(); | ||
| // Send the `Copied` object to wherever. | ||
| return Error::success(); | ||
| } | ||
|
|
||
| private: | ||
| JsonSerializer serializer; | ||
| JsonSerializer Serializer; | ||
| }; | ||
|
|
||
| // This defines a custom TelemetryInfo that has an additional Msg field. | ||
| struct MyTelemetryInfo : public telemetry::TelemetryInfo { | ||
| std::string Msg; | ||
|
|
||
| Error serialize(Serializer& serializer) const override { | ||
| Error serialize(Serializer& Serializer) const override { | ||
oontvoo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| TelemetryInfo::serialize(serializer); | ||
| serializer.writeString("MyMsg", Msg); | ||
| Serializer.writeString("MyMsg", Msg); | ||
| } | ||
|
|
||
| // Note: implement getKind() and classof() to support dyn_cast operations. | ||
|
|
@@ -230,11 +226,11 @@ Logging the tool init-process: | |
| auto Manager = MyManager::createInstance(&MyConfig); | ||
|
|
||
|
|
||
| // Any other tool's init code can go here | ||
| // Any other tool's init code can go here. | ||
| // ... | ||
|
|
||
| // Finally, take a snapshot of the time now so we know how long it took the | ||
| // init process to finish | ||
| // init process to finish. | ||
| auto EndTime = std::chrono::time_point<std::chrono::steady_clock>::now(); | ||
| MyTelemetryInfo Entry; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| //===- llvm/Telemetry/Telemetry.h - Telemetry -------------------*- C++ -*-===// | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
|
|
@@ -7,7 +7,7 @@ | |
| //===----------------------------------------------------------------------===// | ||
| /// | ||
| /// \file | ||
| /// This file provides the basic framework for Telemetry | ||
| /// This file provides the basic framework for Telemetry. | ||
| /// Refer to its documentation at llvm/docs/Telemetry.rst for more details. | ||
| //===---------------------------------------------------------------------===// | ||
|
|
||
|
|
@@ -27,14 +27,14 @@ namespace telemetry { | |
|
|
||
| class Serializer { | ||
| public: | ||
| virtual llvm::Error init() = 0; | ||
| virtual Error init() = 0; | ||
| virtual void write(StringRef KeyName, bool Value) = 0; | ||
| virtual void write(StringRef KeyName, int Value) = 0; | ||
| virtual void write(StringRef KeyName, size_t Value) = 0; | ||
| virtual void write(StringRef KeyName, unsigned long long Value) = 0; | ||
|
||
| virtual void write(StringRef KeyName, StringRef Value) = 0; | ||
| virtual void write(StringRef KeyName, | ||
| const std::map<std::string, std::string> &Value) = 0; | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| virtual llvm::Error finalize() = 0; | ||
| virtual Error finalize() = 0; | ||
| }; | ||
|
|
||
| /// Configuration for the Manager class. | ||
|
|
@@ -79,7 +79,7 @@ struct TelemetryInfo { | |
| // | ||
| // Note: a tool could have multiple sessions running at once, in which | ||
| // case, these shall be multiple sets of TelemetryInfo with multiple unique | ||
| // ids. | ||
| // IDs. | ||
| // | ||
| // Different usages can assign different types of IDs to this field. | ||
| std::string SessionId; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,13 +49,13 @@ struct TestContext { | |
|
|
||
| class JsonSerializer : public Serializer { | ||
| public: | ||
| json::Object *getOutputObject() { return object.get(); } | ||
| json::Object *getOutputObject() { return Out.get(); } | ||
|
|
||
| llvm::Error init() override { | ||
|
||
| if (started) | ||
| if (Started) | ||
| return createStringError("Serializer already in use"); | ||
| started = true; | ||
| object = std::make_unique<json::Object>(); | ||
| Started = true; | ||
| Out = std::make_unique<json::Object>(); | ||
| return Error::success(); | ||
| } | ||
|
|
||
|
|
@@ -67,7 +67,7 @@ class JsonSerializer : public Serializer { | |
| writeHelper(KeyName, Value); | ||
| } | ||
|
|
||
| void write(StringRef KeyName, size_t Value) override { | ||
| void write(StringRef KeyName, unsigned long long Value) override { | ||
| writeHelper(KeyName, Value); | ||
| } | ||
| void write(StringRef KeyName, StringRef Value) override { | ||
|
|
@@ -77,36 +77,36 @@ class JsonSerializer : public Serializer { | |
| void write(StringRef KeyName, | ||
| const std::map<std::string, std::string> &Value) override { | ||
| json::Object Inner; | ||
| for (auto kv : Value) { | ||
| Inner.try_emplace(kv.first, kv.second); | ||
| for (auto KV : Value) { | ||
| Inner.try_emplace(KV.first, KV.second); | ||
| } | ||
| writeHelper(KeyName, json::Value(std::move(Inner))); | ||
| } | ||
|
|
||
| llvm::Error finalize() override { | ||
| if (!started) | ||
| if (!Started) | ||
| return createStringError("Serializer not currently in use"); | ||
| started = false; | ||
| Started = false; | ||
| return Error::success(); | ||
| } | ||
|
|
||
| private: | ||
| template <typename T> void writeHelper(StringRef Name, T Value) { | ||
| assert(started && "serializer not started"); | ||
| object->try_emplace(Name, Value); | ||
| assert(Started && "serializer not started"); | ||
| Out->try_emplace(Name, Value); | ||
| } | ||
| bool started = false; | ||
| std::unique_ptr<json::Object> object; | ||
| bool Started = false; | ||
| std::unique_ptr<json::Object> Out; | ||
| }; | ||
|
|
||
| class StringSerializer : public Serializer { | ||
| public: | ||
| const std::string &getString() { return Buffer; } | ||
|
|
||
| llvm::Error init() override { | ||
| if (started) | ||
| if (Started) | ||
| return createStringError("Serializer already in use"); | ||
| started = true; | ||
| Started = true; | ||
| Buffer.clear(); | ||
| return Error::success(); | ||
| } | ||
|
|
@@ -119,41 +119,41 @@ class StringSerializer : public Serializer { | |
| writeHelper(KeyName, Value); | ||
| } | ||
|
|
||
| void write(StringRef KeyName, size_t Value) override { | ||
| void write(StringRef KeyName, unsigned long long Value) override { | ||
| writeHelper(KeyName, Value); | ||
| } | ||
| void write(StringRef KeyName, StringRef Value) override { | ||
| assert(started && "serializer not started"); | ||
| writeHelper(KeyName, Value); | ||
| } | ||
|
|
||
| void write(StringRef KeyName, | ||
| const std::map<std::string, std::string> &Value) override { | ||
| std::string Inner; | ||
| for (auto kv : Value) { | ||
| writeHelper(StringRef(kv.first), StringRef(kv.second), &Inner); | ||
| for (auto KV : Value) { | ||
| writeHelper(StringRef(KV.first), StringRef(KV.second), &Inner); | ||
| } | ||
| writeHelper(KeyName, StringRef(Inner)); | ||
| } | ||
|
|
||
| llvm::Error finalize() override { | ||
| if (!started) | ||
| if (!Started) | ||
| return createStringError("Serializer not currently in use"); | ||
| started = false; | ||
| Started = false; | ||
| return Error::success(); | ||
| } | ||
|
|
||
| private: | ||
| template <typename T> | ||
| void writeHelper(StringRef Name, T Value, std::string *Buff) { | ||
| assert(started && "serializer not started"); | ||
| assert(Started && "serializer not started"); | ||
| Buff->append((Name + ":" + llvm::Twine(Value) + "\n").str()); | ||
| } | ||
|
|
||
| template <typename T> void writeHelper(StringRef Name, T Value) { | ||
| writeHelper(Name, Value, &Buffer); | ||
| } | ||
|
|
||
| bool started = false; | ||
| bool Started = false; | ||
| std::string Buffer; | ||
| }; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.