Skip to content

[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 99 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
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 Aug 7, 2024
6e43f67
add header
oontvoo Aug 7, 2024
e25f5fc
fixed typo
oontvoo Aug 7, 2024
ad3906c
Merge branch 'llvm:main' into llvm_telemetry
oontvoo Aug 9, 2024
24d07d6
Merge branch 'llvm:main' into llvm_telemetry
oontvoo Aug 22, 2024
0057bcf
add tests and addressed review comments
oontvoo Aug 29, 2024
750e4ac
formatting changes
oontvoo Aug 29, 2024
1378ed4
more formatting
oontvoo Aug 29, 2024
02e750e
more formatting changes
oontvoo Aug 29, 2024
63e99fc
Added header comment to describe the package
oontvoo Aug 29, 2024
fa88512
reformat header
oontvoo Aug 29, 2024
0866f64
addressed review comments and added separate docs in llvm/docs/
oontvoo Sep 3, 2024
a8523f7
updated field names in tests
oontvoo Sep 4, 2024
47e8b06
reformated doc and added additional details
oontvoo Sep 4, 2024
690c6ab
fix formatting
oontvoo Sep 4, 2024
db668f4
details
oontvoo Sep 4, 2024
0290a14
formatted TelemetryTest.cpp
oontvoo Sep 4, 2024
14b5234
fix formatting in docs
oontvoo Sep 4, 2024
6ca87e5
convert comments to doxygen style
oontvoo Sep 4, 2024
4155add
fix doc toc
oontvoo Sep 4, 2024
11ead4a
group all the testing-params into a Context struct
oontvoo Sep 5, 2024
48228ee
fix conversion warnings
oontvoo Sep 5, 2024
ed8a3f1
Merge branch 'llvm:main' into llvm_telemetry
oontvoo Sep 5, 2024
990e1ca
finish up todos
oontvoo Sep 5, 2024
479cd13
reformat docs
oontvoo Sep 20, 2024
6d8aee2
Merge branch 'llvm:main' into llvm_telemetry
oontvoo Sep 24, 2024
3a17dbb
Update llvm/docs/Telemetry.rst
oontvoo Sep 24, 2024
a6a6c7b
Update llvm/docs/Telemetry.rst
oontvoo Sep 24, 2024
f30dec6
Update llvm/docs/Telemetry.rst
oontvoo Sep 24, 2024
fd3da20
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Sep 24, 2024
60616ef
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo Sep 24, 2024
8c0ac5a
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Sep 24, 2024
c8be829
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Sep 24, 2024
1393c1f
Update llvm/docs/Telemetry.rst
oontvoo Sep 24, 2024
eb07577
Update llvm/docs/Telemetry.rst
oontvoo Sep 24, 2024
0376abc
fix comment
oontvoo Sep 24, 2024
e2f7c23
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Sep 24, 2024
17dfac7
Update llvm/docs/Telemetry.rst
oontvoo Sep 24, 2024
1ea0906
Update llvm/docs/Telemetry.rst
oontvoo Sep 24, 2024
39fd0e7
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Sep 24, 2024
67b7688
Addressed review comments: remove most of the member fields from Tele…
oontvoo Sep 24, 2024
efd25d8
use llvm::StringLiteral
oontvoo Sep 24, 2024
4a8276f
Addressed review comment:
oontvoo Sep 26, 2024
a16344b
pass test context as arg to ctor
oontvoo Sep 27, 2024
26ee5eb
construct expected json directly rather than parsing from strings
oontvoo Sep 30, 2024
b766e3c
remove unnecessary use of atomic seed
oontvoo Sep 30, 2024
c8cddab
addressed review comments
oontvoo Nov 21, 2024
5f8d65f
s/emitEntry/receiveEntry
oontvoo Nov 21, 2024
dffeacd
Addressed review comments:
oontvoo Nov 27, 2024
398ed3e
updated doc
oontvoo Nov 27, 2024
e462908
fix build warning
oontvoo Dec 4, 2024
df8a9af
more cleanup
oontvoo Dec 4, 2024
70f4742
spacing
oontvoo Dec 4, 2024
8eab77a
more docs
oontvoo Dec 4, 2024
f9e1a65
pass map arg as const ref
oontvoo Dec 9, 2024
2a1fbe5
Update llvm/docs/Telemetry.rst
oontvoo Dec 11, 2024
6e3a85d
Update llvm/docs/Telemetry.rst
oontvoo Dec 11, 2024
f9b1cce
addressed review comments
oontvoo Dec 11, 2024
0f38a74
Update llvm/docs/Telemetry.rst
oontvoo Dec 16, 2024
ad57099
Update llvm/docs/Telemetry.rst
oontvoo Dec 16, 2024
a2fcd4d
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Dec 16, 2024
628e7e9
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Dec 16, 2024
6ea4e92
Update llvm/docs/Telemetry.rst
oontvoo Dec 16, 2024
08cf32f
Update llvm/docs/Telemetry.rst
oontvoo Dec 16, 2024
3c52401
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Dec 16, 2024
07f06c0
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Dec 16, 2024
06e746e
addressed review comments:
oontvoo Dec 16, 2024
2476294
more styling fixe
oontvoo Dec 16, 2024
5ce406c
dest -> Dest
oontvoo Dec 16, 2024
fd57d06
fix caps
oontvoo Dec 16, 2024
a8a878b
Update llvm/docs/Telemetry.rst
oontvoo Dec 17, 2024
54eeaba
Update llvm/docs/Telemetry.rst
oontvoo Dec 17, 2024
32dfc6a
Update llvm/docs/Telemetry.rst
oontvoo Dec 17, 2024
0893c5b
Update llvm/docs/Telemetry.rst
oontvoo Dec 17, 2024
155f243
Update llvm/docs/Telemetry.rst
oontvoo Dec 17, 2024
b255e3a
Update llvm/docs/Telemetry.rst
oontvoo Dec 17, 2024
14d1c92
formatting
oontvoo Dec 17, 2024
bf2172d
update design chart
oontvoo Dec 17, 2024
c2dcb7d
replace write(std::map) with beginObject/endObject interface
oontvoo Dec 17, 2024
bbe9009
formatting
oontvoo Dec 17, 2024
e2036c6
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Dec 18, 2024
05947d5
Update llvm/docs/Telemetry.rst
oontvoo Dec 18, 2024
f1100bb
add helper write() that takes a map. also updated docs
oontvoo Dec 18, 2024
2f64b29
added additional overloads for int types
oontvoo Dec 18, 2024
a5df7a0
formatting
oontvoo Dec 18, 2024
585fee8
remove more unused headers
oontvoo Dec 18, 2024
3812cda
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo Dec 19, 2024
0cdc240
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo Dec 19, 2024
da8056f
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo Dec 19, 2024
c116074
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo Dec 19, 2024
a4e2799
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo Dec 19, 2024
2763d46
Update llvm/unittests/Telemetry/TelemetryTest.cpp
oontvoo Dec 19, 2024
75c1b4b
addressed review comments
oontvoo Dec 19, 2024
9780ec7
Addressed review comments:
oontvoo Dec 19, 2024
4715743
Update llvm/lib/Telemetry/Telemetry.cpp
oontvoo Dec 20, 2024
d231bf2
Update llvm/include/llvm/Telemetry/Telemetry.h
oontvoo Dec 20, 2024
1941b1f
addressed review comments:
oontvoo Dec 20, 2024
bd3df5e
Add simple assert to make sure the map's key is string compat
oontvoo Dec 20, 2024
4351b94
Merge branch 'llvm:main' into llvm_telemetry
oontvoo Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
257 changes: 257 additions & 0 deletions llvm/docs/Telemetry.rst
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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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 std::stack type here, since the data follows the "first in, last out" model.

Copy link
Member Author

Choose a reason for hiding this comment

The 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.
4 changes: 4 additions & 0 deletions llvm/docs/UserGuides.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ intermediate LLVM representation.
SupportLibrary
TableGen/index
TableGenFundamentals
Telemetry
Vectorizers
WritingAnLLVMPass
WritingAnLLVMNewPMPass
Expand Down Expand Up @@ -293,3 +294,6 @@ Additional Topics

:doc:`Sandbox IR <SandboxIR>`
This document describes the design and usage of Sandbox IR, a transactional layer over LLVM IR.

:doc:`Telemetry`
This document describes the Telemetry framework in LLVM.
Binary file added llvm/docs/llvm_telemetry_design.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading