telemetry.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Copyright 2017 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <chrono>
  6. #include <map>
  7. #include <memory>
  8. #include <string>
  9. #include "common/common_types.h"
  10. namespace Common::Telemetry {
  11. /// Field type, used for grouping fields together in the final submitted telemetry log
  12. enum class FieldType : u8 {
  13. None = 0, ///< No specified field group
  14. App, ///< yuzu application fields (e.g. version, branch, etc.)
  15. Session, ///< Emulated session fields (e.g. title ID, log, etc.)
  16. Performance, ///< Emulated performance (e.g. fps, emulated CPU speed, etc.)
  17. UserFeedback, ///< User submitted feedback (e.g. star rating, user notes, etc.)
  18. UserConfig, ///< User configuration fields (e.g. emulated CPU core, renderer, etc.)
  19. UserSystem, ///< User system information (e.g. host CPU type, RAM, etc.)
  20. };
  21. struct VisitorInterface;
  22. /**
  23. * Interface class for telemetry data fields.
  24. */
  25. class FieldInterface : NonCopyable {
  26. public:
  27. virtual ~FieldInterface() = default;
  28. /**
  29. * Accept method for the visitor pattern.
  30. * @param visitor Reference to the visitor that will visit this field.
  31. */
  32. virtual void Accept(VisitorInterface& visitor) const = 0;
  33. /**
  34. * Gets the name of this field.
  35. * @returns Name of this field as a string.
  36. */
  37. virtual const std::string& GetName() const = 0;
  38. };
  39. /**
  40. * Represents a telemetry data field, i.e. a unit of data that gets logged and submitted to our
  41. * telemetry web service.
  42. */
  43. template <typename T>
  44. class Field : public FieldInterface {
  45. public:
  46. Field(FieldType type_, std::string name_, T value_)
  47. : name(std::move(name_)), type(type_), value(std::move(value_)) {}
  48. Field(const Field&) = default;
  49. Field& operator=(const Field&) = default;
  50. Field(Field&&) = default;
  51. Field& operator=(Field&& other) = default;
  52. void Accept(VisitorInterface& visitor) const override;
  53. [[nodiscard]] const std::string& GetName() const override {
  54. return name;
  55. }
  56. /**
  57. * Returns the type of the field.
  58. */
  59. [[nodiscard]] FieldType GetType() const {
  60. return type;
  61. }
  62. /**
  63. * Returns the value of the field.
  64. */
  65. [[nodiscard]] const T& GetValue() const {
  66. return value;
  67. }
  68. [[nodiscard]] bool operator==(const Field& other) const {
  69. return (type == other.type) && (name == other.name) && (value == other.value);
  70. }
  71. [[nodiscard]] bool operator!=(const Field& other) const {
  72. return !operator==(other);
  73. }
  74. private:
  75. std::string name; ///< Field name, must be unique
  76. FieldType type{}; ///< Field type, used for grouping fields together
  77. T value; ///< Field value
  78. };
  79. /**
  80. * Collection of data fields that have been logged.
  81. */
  82. class FieldCollection final : NonCopyable {
  83. public:
  84. FieldCollection() = default;
  85. /**
  86. * Accept method for the visitor pattern, visits each field in the collection.
  87. * @param visitor Reference to the visitor that will visit each field.
  88. */
  89. void Accept(VisitorInterface& visitor) const;
  90. /**
  91. * Creates a new field and adds it to the field collection.
  92. * @param type Type of the field to add.
  93. * @param name Name of the field to add.
  94. * @param value Value for the field to add.
  95. */
  96. template <typename T>
  97. void AddField(FieldType type, const char* name, T value) {
  98. return AddField(std::make_unique<Field<T>>(type, name, std::move(value)));
  99. }
  100. /**
  101. * Adds a new field to the field collection.
  102. * @param field Field to add to the field collection.
  103. */
  104. void AddField(std::unique_ptr<FieldInterface> field);
  105. private:
  106. std::map<std::string, std::unique_ptr<FieldInterface>> fields;
  107. };
  108. /**
  109. * Telemetry fields visitor interface class. A backend to log to a web service should implement
  110. * this interface.
  111. */
  112. struct VisitorInterface : NonCopyable {
  113. virtual ~VisitorInterface() = default;
  114. virtual void Visit(const Field<bool>& field) = 0;
  115. virtual void Visit(const Field<double>& field) = 0;
  116. virtual void Visit(const Field<float>& field) = 0;
  117. virtual void Visit(const Field<u8>& field) = 0;
  118. virtual void Visit(const Field<u16>& field) = 0;
  119. virtual void Visit(const Field<u32>& field) = 0;
  120. virtual void Visit(const Field<u64>& field) = 0;
  121. virtual void Visit(const Field<s8>& field) = 0;
  122. virtual void Visit(const Field<s16>& field) = 0;
  123. virtual void Visit(const Field<s32>& field) = 0;
  124. virtual void Visit(const Field<s64>& field) = 0;
  125. virtual void Visit(const Field<std::string>& field) = 0;
  126. virtual void Visit(const Field<const char*>& field) = 0;
  127. virtual void Visit(const Field<std::chrono::microseconds>& field) = 0;
  128. /// Completion method, called once all fields have been visited
  129. virtual void Complete() = 0;
  130. virtual bool SubmitTestcase() = 0;
  131. };
  132. /**
  133. * Empty implementation of VisitorInterface that drops all fields. Used when a functional
  134. * backend implementation is not available.
  135. */
  136. struct NullVisitor : public VisitorInterface {
  137. ~NullVisitor() = default;
  138. void Visit(const Field<bool>& /*field*/) override {}
  139. void Visit(const Field<double>& /*field*/) override {}
  140. void Visit(const Field<float>& /*field*/) override {}
  141. void Visit(const Field<u8>& /*field*/) override {}
  142. void Visit(const Field<u16>& /*field*/) override {}
  143. void Visit(const Field<u32>& /*field*/) override {}
  144. void Visit(const Field<u64>& /*field*/) override {}
  145. void Visit(const Field<s8>& /*field*/) override {}
  146. void Visit(const Field<s16>& /*field*/) override {}
  147. void Visit(const Field<s32>& /*field*/) override {}
  148. void Visit(const Field<s64>& /*field*/) override {}
  149. void Visit(const Field<std::string>& /*field*/) override {}
  150. void Visit(const Field<const char*>& /*field*/) override {}
  151. void Visit(const Field<std::chrono::microseconds>& /*field*/) override {}
  152. void Complete() override {}
  153. bool SubmitTestcase() override {
  154. return false;
  155. }
  156. };
  157. /// Appends build-specific information to the given FieldCollection,
  158. /// such as branch name, revision hash, etc.
  159. void AppendBuildInfo(FieldCollection& fc);
  160. /// Appends CPU-specific information to the given FieldCollection,
  161. /// such as instruction set extensions, etc.
  162. void AppendCPUInfo(FieldCollection& fc);
  163. /// Appends OS-specific information to the given FieldCollection,
  164. /// such as platform name, etc.
  165. void AppendOSInfo(FieldCollection& fc);
  166. } // namespace Common::Telemetry