-
Notifications
You must be signed in to change notification settings - Fork 14.1k
[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
Merged
Merged
Changes from all commits
Commits
Show all changes
99 commits
Select commit
Hold shift + click to select a range
dbb8b15
[llvm][lib]Propose a simple Telemetry framework.
oontvoo 6e43f67
add header
oontvoo e25f5fc
fixed typo
oontvoo ad3906c
Merge branch 'llvm:main' into llvm_telemetry
oontvoo 24d07d6
Merge branch 'llvm:main' into llvm_telemetry
oontvoo 0057bcf
add tests and addressed review comments
oontvoo 750e4ac
formatting changes
oontvoo 1378ed4
more formatting
oontvoo 02e750e
more formatting changes
oontvoo 63e99fc
Added header comment to describe the package
oontvoo fa88512
reformat header
oontvoo 0866f64
addressed review comments and added separate docs in llvm/docs/
oontvoo a8523f7
updated field names in tests
oontvoo 47e8b06
reformated doc and added additional details
oontvoo 690c6ab
fix formatting
oontvoo db668f4
details
oontvoo 0290a14
formatted TelemetryTest.cpp
oontvoo 14b5234
fix formatting in docs
oontvoo 6ca87e5
convert comments to doxygen style
oontvoo 4155add
fix doc toc
oontvoo 11ead4a
group all the testing-params into a Context struct
oontvoo 48228ee
fix conversion warnings
oontvoo ed8a3f1
Merge branch 'llvm:main' into llvm_telemetry
oontvoo 990e1ca
finish up todos
oontvoo 479cd13
reformat docs
oontvoo 6d8aee2
Merge branch 'llvm:main' into llvm_telemetry
oontvoo 3a17dbb
Update llvm/docs/Telemetry.rst
oontvoo a6a6c7b
Update llvm/docs/Telemetry.rst
oontvoo f30dec6
Update llvm/docs/Telemetry.rst
oontvoo fd3da20
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 60616ef
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo 8c0ac5a
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo c8be829
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 1393c1f
Update llvm/docs/Telemetry.rst
oontvoo eb07577
Update llvm/docs/Telemetry.rst
oontvoo 0376abc
fix comment
oontvoo e2f7c23
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 17dfac7
Update llvm/docs/Telemetry.rst
oontvoo 1ea0906
Update llvm/docs/Telemetry.rst
oontvoo 39fd0e7
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 67b7688
Addressed review comments: remove most of the member fields from Tele…
oontvoo efd25d8
use llvm::StringLiteral
oontvoo 4a8276f
Addressed review comment:
oontvoo a16344b
pass test context as arg to ctor
oontvoo 26ee5eb
construct expected json directly rather than parsing from strings
oontvoo b766e3c
remove unnecessary use of atomic seed
oontvoo c8cddab
addressed review comments
oontvoo 5f8d65f
s/emitEntry/receiveEntry
oontvoo dffeacd
Addressed review comments:
oontvoo 398ed3e
updated doc
oontvoo e462908
fix build warning
oontvoo df8a9af
more cleanup
oontvoo 70f4742
spacing
oontvoo 8eab77a
more docs
oontvoo f9e1a65
pass map arg as const ref
oontvoo 2a1fbe5
Update llvm/docs/Telemetry.rst
oontvoo 6e3a85d
Update llvm/docs/Telemetry.rst
oontvoo f9b1cce
addressed review comments
oontvoo 0f38a74
Update llvm/docs/Telemetry.rst
oontvoo ad57099
Update llvm/docs/Telemetry.rst
oontvoo a2fcd4d
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 628e7e9
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 6ea4e92
Update llvm/docs/Telemetry.rst
oontvoo 08cf32f
Update llvm/docs/Telemetry.rst
oontvoo 3c52401
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 07f06c0
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 06e746e
addressed review comments:
oontvoo 2476294
more styling fixe
oontvoo 5ce406c
dest -> Dest
oontvoo fd57d06
fix caps
oontvoo a8a878b
Update llvm/docs/Telemetry.rst
oontvoo 54eeaba
Update llvm/docs/Telemetry.rst
oontvoo 32dfc6a
Update llvm/docs/Telemetry.rst
oontvoo 0893c5b
Update llvm/docs/Telemetry.rst
oontvoo 155f243
Update llvm/docs/Telemetry.rst
oontvoo b255e3a
Update llvm/docs/Telemetry.rst
oontvoo 14d1c92
formatting
oontvoo bf2172d
update design chart
oontvoo c2dcb7d
replace write(std::map) with beginObject/endObject interface
oontvoo bbe9009
formatting
oontvoo e2036c6
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 05947d5
Update llvm/docs/Telemetry.rst
oontvoo f1100bb
add helper write() that takes a map. also updated docs
oontvoo 2f64b29
added additional overloads for int types
oontvoo a5df7a0
formatting
oontvoo 585fee8
remove more unused headers
oontvoo 3812cda
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo 0cdc240
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo da8056f
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo c116074
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo a4e2799
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo 2763d46
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo 75c1b4b
addressed review comments
oontvoo 9780ec7
Addressed review comments:
oontvoo 4715743
Update llvm/lib/Telemetry/Telemetry.cpp
oontvoo d231bf2
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo 1941b1f
addressed review comments:
oontvoo bd3df5e
Add simple assert to make sure the map's key is string compat
oontvoo 4351b94
Merge branch 'llvm:main' into llvm_telemetry
oontvoo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
=========================== | ||
Telemetry framework in LLVM | ||
=========================== | ||
|
||
.. contents:: | ||
:local: | ||
|
||
.. toctree:: | ||
:hidden: | ||
|
||
Objective | ||
========= | ||
|
||
Provides a common framework in LLVM for collecting various usage and performance | ||
metrics. | ||
It is located at ``llvm/Telemetry/Telemetry.h``. | ||
|
||
Characteristics | ||
--------------- | ||
* Configurable and extensible by: | ||
|
||
* Tools: any tool that wants to use Telemetry can extend and customize it. | ||
* Vendors: Toolchain vendors can also provide custom implementation of the | ||
library, which could either override or extend the given tool's upstream | ||
implementation, to best fit their organization's usage and privacy models. | ||
* End users of such tool can also configure Telemetry (as allowed by their | ||
vendor). | ||
|
||
Important notes | ||
--------------- | ||
|
||
* There is no concrete implementation of a Telemetry library in upstream LLVM. | ||
We only provide the abstract API here. Any tool that wants telemetry will | ||
implement one. | ||
|
||
The rationale for this is that all the tools in LLVM are very different in | ||
what they care about (what/where/when to instrument data). Hence, it might not | ||
be practical to have a single implementation. | ||
However, in the future, if we see enough common pattern, we can extract them | ||
into a shared place. This is TBD - contributions are welcome. | ||
|
||
* No implementation of Telemetry in upstream LLVM shall store any of the | ||
collected data due to privacy and security reasons: | ||
|
||
* Different organizations have different privacy models: | ||
|
||
* Which data is sensitive, which is not? | ||
* Whether it is acceptable for instrumented data to be stored anywhere? | ||
(to a local file, what not?) | ||
|
||
* Data ownership and data collection consents are hard to accommodate from | ||
LLVM developers' point of view: | ||
|
||
* E.g., data collected by Telemetry is not necessarily owned by the user | ||
of an LLVM tool with Telemetry enabled, hence the user's consent to data | ||
collection is not meaningful. On the other hand, LLVM developers have no | ||
reasonable ways to request consent from the "real" owners. | ||
|
||
|
||
High-level design | ||
================= | ||
|
||
Key components | ||
-------------- | ||
|
||
The framework consists of four important classes: | ||
|
||
* ``llvm::telemetry::Manager``: The class responsible for collecting and | ||
transmitting telemetry data. This is the main point of interaction between the | ||
framework and any tool that wants to enable telemetry. | ||
* ``llvm::telemetry::TelemetryInfo``: Data courier | ||
* ``llvm::telemetry::Destination``: Data sink to which the Telemetry framework | ||
sends data. | ||
Its implementation is transparent to the framework. | ||
It is up to the vendor to decide which pieces of data to forward and where | ||
to forward them to for their final storage. | ||
* ``llvm::telemetry::Config``: Configurations for the ``Manager``. | ||
|
||
.. image:: llvm_telemetry_design.png | ||
|
||
How to implement and interact with the API | ||
------------------------------------------ | ||
|
||
To use Telemetry in your tool, you need to provide a concrete implementation of the ``Manager`` class and ``Destination``. | ||
|
||
1) Define a custom ``Serializer``, ``Manager``, ``Destination`` and optionally a subclass of ``TelemetryInfo`` | ||
|
||
.. code-block:: c++ | ||
|
||
class JsonSerializer : public Serializer { | ||
public: | ||
json::Object *getOutputObject() { return Out.get(); } | ||
|
||
Error init() override { | ||
if (Started) | ||
return createStringError("Serializer already in use"); | ||
started = true; | ||
Out = std::make_unique<json::Object>(); | ||
return Error::success(); | ||
} | ||
|
||
// Serialize the given value. | ||
void write(StringRef KeyName, bool Value) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void write(StringRef KeyName, int Value) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void write(StringRef KeyName, unsigned int Value) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void write(StringRef KeyName, unsigned long Value) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void write(StringRef KeyName, long Value) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void write(StringRef KeyName, long long Value ) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void write(StringRef KeyName, unsigned long long Value) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void write(StringRef KeyName, StringRef Value) override { | ||
writeHelper(KeyName, Value); | ||
} | ||
|
||
void beginObject(StringRef KeyName) override { | ||
Children.push_back(json::Object()); | ||
ChildrenNames.push_back(KeyName.str()); | ||
} | ||
|
||
void endObject() override { | ||
assert(!Children.empty() && !ChildrenNames.empty()); | ||
json::Value Val = json::Value(std::move(Children.back())); | ||
std::string Name = ChildrenNames.back(); | ||
|
||
Children.pop_back(); | ||
ChildrenNames.pop_back(); | ||
writeHelper(Name, std::move(Val)); | ||
} | ||
|
||
Error finalize() override { | ||
if (!Started) | ||
return createStringError("Serializer not currently in use"); | ||
Started = false; | ||
return Error::success(); | ||
} | ||
|
||
private: | ||
template <typename T> void writeHelper(StringRef Name, T Value) { | ||
assert(Started && "serializer not started"); | ||
if (Children.empty()) | ||
Out->try_emplace(Name, Value); | ||
else | ||
Children.back().try_emplace(Name, Value); | ||
} | ||
bool Started = false; | ||
std::unique_ptr<json::Object> Out; | ||
std::vector<json::Object> Children; | ||
std::vector<std::string> ChildrenNames; | ||
Comment on lines
+167
to
+168
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No specific need to change this, as it works, but I'd use a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ack |
||
}; | ||
|
||
class MyManager : public telemery::Manager { | ||
public: | ||
static std::unique_ptr<MyManager> createInstatnce(telemetry::Config *Config) { | ||
// If Telemetry is not enabled, then just return null; | ||
if (!Config->EnableTelemetry) | ||
return nullptr; | ||
return std::make_unique<MyManager>(); | ||
} | ||
MyManager() = default; | ||
|
||
Error preDispatch(TelemetryInfo *Entry) override { | ||
Entry->SessionId = SessionId; | ||
return Error::success(); | ||
} | ||
|
||
// You can also define additional instrumentation points. | ||
void logStartup(TelemetryInfo *Entry) { | ||
// Add some additional data to entry. | ||
Entry->Msg = "Some message"; | ||
dispatch(Entry); | ||
} | ||
|
||
void logAdditionalPoint(TelemetryInfo *Entry) { | ||
// .... code here | ||
} | ||
|
||
private: | ||
const std::string SessionId; | ||
}; | ||
|
||
class MyDestination : public telemetry::Destination { | ||
public: | ||
Error receiveEntry(const TelemetryInfo *Entry) override { | ||
if (Error Err = Serializer.init()) | ||
return Err; | ||
|
||
Entry->serialize(Serializer); | ||
if (Error Err = Serializer.finalize()) | ||
return Err; | ||
|
||
json::Object Copied = *Serializer.getOutputObject(); | ||
// Send the `Copied` object to wherever. | ||
return Error::success(); | ||
} | ||
|
||
private: | ||
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 { | ||
TelemetryInfo::serialize(serializer); | ||
Serializer.writeString("MyMsg", Msg); | ||
} | ||
|
||
// Note: implement getKind() and classof() to support dyn_cast operations. | ||
}; | ||
|
||
|
||
2) Use the library in your tool. | ||
|
||
Logging the tool init-process: | ||
|
||
.. code-block:: c++ | ||
|
||
// In tool's initialization code. | ||
auto StartTime = std::chrono::time_point<std::chrono::steady_clock>::now(); | ||
telemetry::Config MyConfig = makeConfig(); // Build up the appropriate Config struct here. | ||
auto Manager = MyManager::createInstance(&MyConfig); | ||
|
||
|
||
// 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. | ||
auto EndTime = std::chrono::time_point<std::chrono::steady_clock>::now(); | ||
MyTelemetryInfo Entry; | ||
|
||
Entry.Start = StartTime; | ||
Entry.End = EndTime; | ||
Manager->logStartup(&Entry); | ||
|
||
Similar code can be used for logging the tool's exit. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.