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