telemetry.h 5.9 KB

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