telemetry.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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 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, const T& value)
  47. : name(std::move(name)), type(type), value(value) {}
  48. Field(FieldType type, std::string name, T&& value)
  49. : name(std::move(name)), type(type), value(std::move(value)) {}
  50. Field(const Field& other) : Field(other.type, other.name, other.value) {}
  51. Field& operator=(const Field& other) {
  52. type = other.type;
  53. name = other.name;
  54. value = other.value;
  55. return *this;
  56. }
  57. Field& operator=(Field&& other) {
  58. type = other.type;
  59. name = std::move(other.name);
  60. value = std::move(other.value);
  61. return *this;
  62. }
  63. void Accept(VisitorInterface& visitor) const override;
  64. const std::string& GetName() const override {
  65. return name;
  66. }
  67. /**
  68. * Returns the type of the field.
  69. */
  70. FieldType GetType() const {
  71. return type;
  72. }
  73. /**
  74. * Returns the value of the field.
  75. */
  76. const T& GetValue() const {
  77. return value;
  78. }
  79. inline bool operator==(const Field<T>& other) {
  80. return (type == other.type) && (name == other.name) && (value == other.value);
  81. }
  82. inline bool operator!=(const Field<T>& other) {
  83. return !(*this == other);
  84. }
  85. private:
  86. std::string name; ///< Field name, must be unique
  87. FieldType type{}; ///< Field type, used for grouping fields together
  88. T value; ///< Field value
  89. };
  90. /**
  91. * Collection of data fields that have been logged.
  92. */
  93. class FieldCollection final : NonCopyable {
  94. public:
  95. FieldCollection() = default;
  96. /**
  97. * Accept method for the visitor pattern, visits each field in the collection.
  98. * @param visitor Reference to the visitor that will visit each field.
  99. */
  100. void Accept(VisitorInterface& visitor) const;
  101. /**
  102. * Creates a new field and adds it to the field collection.
  103. * @param type Type of the field to add.
  104. * @param name Name of the field to add.
  105. * @param value Value for the field to add.
  106. */
  107. template <typename T>
  108. void AddField(FieldType type, const char* name, T value) {
  109. return AddField(std::make_unique<Field<T>>(type, name, std::move(value)));
  110. }
  111. /**
  112. * Adds a new field to the field collection.
  113. * @param field Field to add to the field collection.
  114. */
  115. void AddField(std::unique_ptr<FieldInterface> field);
  116. private:
  117. std::map<std::string, std::unique_ptr<FieldInterface>> fields;
  118. };
  119. /**
  120. * Telemetry fields visitor interface class. A backend to log to a web service should implement
  121. * this interface.
  122. */
  123. struct VisitorInterface : NonCopyable {
  124. virtual ~VisitorInterface() = default;
  125. virtual void Visit(const Field<bool>& field) = 0;
  126. virtual void Visit(const Field<double>& field) = 0;
  127. virtual void Visit(const Field<float>& field) = 0;
  128. virtual void Visit(const Field<u8>& field) = 0;
  129. virtual void Visit(const Field<u16>& field) = 0;
  130. virtual void Visit(const Field<u32>& field) = 0;
  131. virtual void Visit(const Field<u64>& field) = 0;
  132. virtual void Visit(const Field<s8>& field) = 0;
  133. virtual void Visit(const Field<s16>& field) = 0;
  134. virtual void Visit(const Field<s32>& field) = 0;
  135. virtual void Visit(const Field<s64>& field) = 0;
  136. virtual void Visit(const Field<std::string>& field) = 0;
  137. virtual void Visit(const Field<const char*>& field) = 0;
  138. virtual void Visit(const Field<std::chrono::microseconds>& field) = 0;
  139. /// Completion method, called once all fields have been visited
  140. virtual void Complete() = 0;
  141. };
  142. /**
  143. * Empty implementation of VisitorInterface that drops all fields. Used when a functional
  144. * backend implementation is not available.
  145. */
  146. struct NullVisitor : public VisitorInterface {
  147. ~NullVisitor() = default;
  148. void Visit(const Field<bool>& /*field*/) override {}
  149. void Visit(const Field<double>& /*field*/) override {}
  150. void Visit(const Field<float>& /*field*/) override {}
  151. void Visit(const Field<u8>& /*field*/) override {}
  152. void Visit(const Field<u16>& /*field*/) override {}
  153. void Visit(const Field<u32>& /*field*/) override {}
  154. void Visit(const Field<u64>& /*field*/) override {}
  155. void Visit(const Field<s8>& /*field*/) override {}
  156. void Visit(const Field<s16>& /*field*/) override {}
  157. void Visit(const Field<s32>& /*field*/) override {}
  158. void Visit(const Field<s64>& /*field*/) override {}
  159. void Visit(const Field<std::string>& /*field*/) override {}
  160. void Visit(const Field<const char*>& /*field*/) override {}
  161. void Visit(const Field<std::chrono::microseconds>& /*field*/) override {}
  162. void Complete() override {}
  163. };
  164. } // namespace Telemetry