xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Telemetry/Telemetry.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file provides the basic framework for Telemetry.
11 /// Refer to its documentation at llvm/docs/Telemetry.rst for more details.
12 //===---------------------------------------------------------------------===//
13 
14 #ifndef LLVM_TELEMETRY_TELEMETRY_H
15 #define LLVM_TELEMETRY_TELEMETRY_H
16 
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/Error.h"
22 #include <map>
23 #include <memory>
24 #include <optional>
25 #include <string>
26 #include <type_traits>
27 #include <vector>
28 
29 namespace llvm {
30 namespace telemetry {
31 
32 class Serializer {
33 public:
34   virtual ~Serializer() = default;
35 
36   virtual Error init() = 0;
37   virtual void write(StringRef KeyName, bool Value) = 0;
38   virtual void write(StringRef KeyName, StringRef Value) = 0;
39   virtual void write(StringRef KeyName, int Value) = 0;
40   virtual void write(StringRef KeyName, long Value) = 0;
41   virtual void write(StringRef KeyName, long long Value) = 0;
42   virtual void write(StringRef KeyName, unsigned int Value) = 0;
43   virtual void write(StringRef KeyName, unsigned long Value) = 0;
44   virtual void write(StringRef KeyName, unsigned long long Value) = 0;
45   virtual void beginObject(StringRef KeyName) = 0;
46   virtual void endObject() = 0;
47   virtual Error finalize() = 0;
48 
49   template <typename T, typename = typename T::mapped_type>
write(StringRef KeyName,const T & Map)50   void write(StringRef KeyName, const T &Map) {
51     static_assert(std::is_convertible_v<typename T::key_type, StringRef>,
52                   "KeyType must be convertible to string");
53     beginObject(KeyName);
54     for (const auto &KeyVal : Map)
55       write(KeyVal.first, KeyVal.second);
56     endObject();
57   }
58 };
59 
60 /// Configuration for the Manager class.
61 /// This stores configurations from both users and vendors and is passed
62 /// to the Manager upon construction. (Any changes to the config after
63 /// the Manager's construction will not have any effect on it).
64 ///
65 /// This struct can be extended as needed to add additional configuration
66 /// points specific to a vendor's implementation.
67 struct Config {
68   static constexpr bool BuildTimeEnableTelemetry = LLVM_ENABLE_TELEMETRY;
69 
70   // If true, telemetry will be enabled.
71   const bool EnableTelemetry;
72 
ConfigConfig73   explicit Config() : EnableTelemetry(BuildTimeEnableTelemetry) {}
74 
75   virtual ~Config() = default;
76 
77   // Telemetry can only be enabled if both the runtime and buildtime flag
78   // are set.
ConfigConfig79   explicit Config(bool E) : EnableTelemetry(E && BuildTimeEnableTelemetry) {}
80 
makeSessionIdConfig81   virtual std::optional<std::string> makeSessionId() { return std::nullopt; }
82 };
83 
84 /// For isa, dyn_cast, etc operations on TelemetryInfo.
85 typedef unsigned KindType;
86 /// This struct is used by TelemetryInfo to support isa<>, dyn_cast<>
87 /// operations.
88 /// It is defined as a struct (rather than an enum) because it is
89 /// expected to be extended by subclasses which may have
90 /// additional TelemetryInfo types defined to describe different events.
91 struct EntryKind {
92   static const KindType Base = 0;
93 };
94 
95 /// TelemetryInfo is the data courier, used to move instrumented data
96 /// from the tool being monitored to the Telemetry framework.
97 ///
98 /// This base class contains only the basic set of telemetry data.
99 /// Downstream implementations can define more subclasses with
100 /// additional fields to describe different events and concepts.
101 ///
102 /// For example, The LLDB debugger can define a DebugCommandInfo subclass
103 /// which has additional fields about the debug-command being instrumented,
104 /// such as `CommandArguments` or `CommandName`.
105 struct LLVM_ABI TelemetryInfo {
106   // This represents a unique-id, conventionally corresponding to
107   // a tool's session - i.e., every time the tool starts until it exits.
108   //
109   // Note: a tool could have multiple sessions running at once, in which
110   // case, these shall be multiple sets of TelemetryInfo with multiple unique
111   // IDs.
112   //
113   // Different usages can assign different types of IDs to this field.
114   std::string SessionId;
115 
116   TelemetryInfo() = default;
117   virtual ~TelemetryInfo() = default;
118 
119   virtual void serialize(Serializer &serializer) const;
120 
121   // For isa, dyn_cast, etc, operations.
getKindTelemetryInfo122   virtual KindType getKind() const { return EntryKind::Base; }
classofTelemetryInfo123   static bool classof(const TelemetryInfo *T) {
124     return T->getKind() == EntryKind::Base;
125   }
126 };
127 
128 /// This class presents a data sink to which the Telemetry framework
129 /// sends data.
130 ///
131 /// Its implementation is transparent to the framework.
132 /// It is up to the vendor to decide which pieces of data to forward
133 /// and where to forward them.
134 class Destination {
135 public:
136   virtual ~Destination() = default;
137   virtual Error receiveEntry(const TelemetryInfo *Entry) = 0;
138   virtual StringLiteral name() const = 0;
139 };
140 
141 /// This class is the main interaction point between any LLVM tool
142 /// and this framework.
143 /// It is responsible for collecting telemetry data from the tool being
144 /// monitored and transmitting the data elsewhere.
145 class LLVM_ABI Manager {
146 public:
147   Manager() = default;
148   virtual ~Manager() = default;
149 
150   // Explicitly non-copyable.
151   Manager(Manager const &) = delete;
152   Manager &operator=(Manager const &) = delete;
153 
154   // Dispatch Telemetry data to the Destination(s).
155   // The argument is non-const because the Manager may add or remove
156   // data from the entry.
157   virtual Error dispatch(TelemetryInfo *Entry);
158 
159   // Register a Destination.
160   void addDestination(std::unique_ptr<Destination> Destination);
161 
162 protected:
163   // Optional callback for subclasses to perform additional tasks before
164   // dispatching to Destinations.
165   virtual Error preDispatch(TelemetryInfo *Entry);
166 
167 private:
168   std::vector<std::unique_ptr<Destination>> Destinations;
169 };
170 
171 } // namespace telemetry
172 } // namespace llvm
173 
174 #endif // LLVM_TELEMETRY_TELEMETRY_H
175