metrics_recorder.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chromecast/metrics/metrics_recorder.h"
  5. #include <stdint.h>
  6. #include <map>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/bind.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/check.h"
  13. #include "base/containers/flat_map.h"
  14. #include "base/logging.h"
  15. #include "base/memory/ptr_util.h"
  16. #include "base/memory/ref_counted.h"
  17. #include "base/notreached.h"
  18. #include "base/observer_list.h"
  19. #include "base/synchronization/lock.h"
  20. #include "base/task/single_thread_task_runner.h"
  21. #include "base/threading/thread_task_runner_handle.h"
  22. #include "base/time/time.h"
  23. #include "chromecast/metrics/cast_event_builder.h"
  24. #include "net/base/ip_address.h"
  25. namespace chromecast {
  26. namespace {
  27. bool IsLogOn(int verbose_log_level) {
  28. // TODO(b/135640848): Determine a better way to log metrics for
  29. // Fuchsia, without producing logspam during development.
  30. return -verbose_log_level >= logging::GetMinLogLevel() ||
  31. (DCHECK_IS_ON() && VLOG_IS_ON(verbose_log_level));
  32. }
  33. // A no-op dummy event builder, used when MetricsRecorder is nullptr.
  34. class DummyEventBuilder : public CastEventBuilder {
  35. public:
  36. // receiver::CastEventBuilder implementation
  37. std::string GetName() override { return ""; }
  38. CastEventBuilder& SetName(const std::string& name) override { return *this; }
  39. CastEventBuilder& SetTime(const base::TimeTicks& time) override {
  40. return *this;
  41. }
  42. CastEventBuilder& SetTimezoneId(const std::string& timezone_id) override {
  43. return *this;
  44. }
  45. CastEventBuilder& SetAppId(const std::string& app_id) override {
  46. return *this;
  47. }
  48. CastEventBuilder& SetRemoteAppId(const std::string& remote_app_id) override {
  49. return *this;
  50. }
  51. CastEventBuilder& SetSessionId(const std::string& session_id) override {
  52. return *this;
  53. }
  54. CastEventBuilder& SetSdkVersion(const std::string& sdk_version) override {
  55. return *this;
  56. }
  57. CastEventBuilder& SetMplVersion(const std::string& mpl_version) override {
  58. return *this;
  59. }
  60. CastEventBuilder& SetConnectionInfo(
  61. const std::string& transport_connection_id,
  62. const std::string& virtual_connection_id) override {
  63. return *this;
  64. }
  65. CastEventBuilder& SetGroupUuid(const std::string& group_uuid) override {
  66. return *this;
  67. }
  68. CastEventBuilder& SetExtraValue(int64_t extra_value) override {
  69. return *this;
  70. }
  71. CastEventBuilder& SetConversationKey(
  72. const std::string& conversation_key) override {
  73. return *this;
  74. }
  75. CastEventBuilder& SetRequestId(int32_t request_id) override { return *this; }
  76. CastEventBuilder& SetEventId(const std::string& event_id) override {
  77. return *this;
  78. }
  79. CastEventBuilder& SetAoghRequestId(const std::string& request_id) override {
  80. return *this;
  81. }
  82. CastEventBuilder& SetAoghLocalDeviceId(int64_t local_id) override {
  83. return *this;
  84. }
  85. CastEventBuilder& SetAoghAgentId(const std::string& agent_id) override {
  86. return *this;
  87. }
  88. CastEventBuilder& SetUiVersion(const std::string& ui_version) override {
  89. return *this;
  90. }
  91. CastEventBuilder& SetAuditReport(const std::string& audit_report) override {
  92. return *this;
  93. }
  94. CastEventBuilder& SetDuoCoreVersion(int64_t version) override {
  95. return *this;
  96. }
  97. CastEventBuilder& SetHotwordModelId(const std::string& model_id) override {
  98. return *this;
  99. }
  100. CastEventBuilder& SetDiscoveryAppSubtype(const std::string& app_id) override {
  101. return *this;
  102. }
  103. CastEventBuilder& SetDiscoveryNamespaceSubtype(
  104. const std::string& namespace_hash) override {
  105. return *this;
  106. }
  107. CastEventBuilder& SetDiscoverySender(
  108. const net::IPAddressBytes& sender_ip) override {
  109. return *this;
  110. }
  111. CastEventBuilder& SetDiscoveryUnicastFlag(bool uses_unicast) override {
  112. return *this;
  113. }
  114. CastEventBuilder& SetFeatureVector(
  115. const std::vector<float>& features) override {
  116. return *this;
  117. }
  118. CastEventBuilder& AddMetadata(const std::string& name,
  119. int64_t value) override {
  120. return *this;
  121. }
  122. CastEventBuilder& SetLaunchFrom(LaunchFrom launch_from) override {
  123. return *this;
  124. }
  125. CastEventBuilder& MergeFrom(
  126. const ::metrics::CastLogsProto_CastEventProto* event_proto) override {
  127. return *this;
  128. }
  129. ::metrics::CastLogsProto_CastEventProto* Build() override {
  130. NOTREACHED();
  131. return nullptr;
  132. }
  133. };
  134. MetricsRecorder* g_instance = nullptr;
  135. } // namespace
  136. void RecordEventWithLogPrefix(const std::string& action,
  137. std::unique_ptr<CastEventBuilder> event_builder,
  138. int verbose_log_level,
  139. const std::string& log_prefix) {
  140. MetricsRecorder* recorder = MetricsRecorder::GetInstance();
  141. if (recorder && event_builder) {
  142. recorder->RecordCastEvent(std::move(event_builder));
  143. }
  144. if (IsLogOn(verbose_log_level)) {
  145. VLOG_STREAM(verbose_log_level) << log_prefix << action;
  146. }
  147. }
  148. std::unique_ptr<CastEventBuilder> CreateCastEvent(const std::string& name) {
  149. MetricsRecorder* recorder = MetricsRecorder::GetInstance();
  150. if (recorder) {
  151. return recorder->CreateEventBuilder(name);
  152. }
  153. return std::make_unique<DummyEventBuilder>();
  154. }
  155. void RecordCastEvent(const std::string& log_name,
  156. std::unique_ptr<CastEventBuilder> event_builder,
  157. int verbose_log_level) {
  158. RecordEventWithLogPrefix(log_name, std::move(event_builder),
  159. verbose_log_level, "cast event: ");
  160. }
  161. void RecordAction(const std::string& action, int verbose_log_level) {
  162. RecordEventWithLogPrefix(action, CreateCastEvent(action), verbose_log_level,
  163. "Record action: ");
  164. }
  165. void LogAction(const std::string& action, int verbose_log_level) {
  166. RecordEventWithLogPrefix(action, std::unique_ptr<CastEventBuilder>(),
  167. verbose_log_level, "Log action: ");
  168. }
  169. void RecordHistogramTime(const std::string& name,
  170. int sample,
  171. int min,
  172. int max,
  173. int num_buckets,
  174. int verbose_log_level) {
  175. MetricsRecorder* recorder = MetricsRecorder::GetInstance();
  176. if (recorder) {
  177. recorder->RecordHistogramTime(name, sample, min, max, num_buckets);
  178. }
  179. if (IsLogOn(verbose_log_level)) {
  180. VLOG_STREAM(verbose_log_level)
  181. << "Time histogram: " << name << ", sample=" << sample
  182. << ", max=" << max << ", min=" << min
  183. << ", num_buckets=" << num_buckets;
  184. }
  185. }
  186. void RecordHistogramCount(const std::string& name,
  187. int sample,
  188. int min,
  189. int max,
  190. int num_buckets,
  191. int verbose_log_level) {
  192. MetricsRecorder* recorder = MetricsRecorder::GetInstance();
  193. if (recorder) {
  194. recorder->RecordHistogramCount(name, sample, min, max, num_buckets);
  195. }
  196. if (IsLogOn(verbose_log_level)) {
  197. VLOG_STREAM(verbose_log_level)
  198. << "Count histogram: " << name << ", sample=" << sample
  199. << ", max=" << max << ", min=" << min
  200. << ", num_buckets=" << num_buckets;
  201. }
  202. }
  203. void RecordHistogramEnum(const std::string& name,
  204. int sample,
  205. int boundary,
  206. int verbose_log_level) {
  207. MetricsRecorder* recorder = MetricsRecorder::GetInstance();
  208. if (recorder) {
  209. recorder->RecordHistogramEnum(name, sample, boundary);
  210. }
  211. if (IsLogOn(verbose_log_level)) {
  212. VLOG_STREAM(verbose_log_level)
  213. << "Count histogram: " << name << ", sample=" << sample
  214. << ", boundary=" << boundary;
  215. }
  216. }
  217. struct MetricsRecorder::ObserverList {
  218. base::ObserverList<Observer>::Unchecked list;
  219. };
  220. // static
  221. void MetricsRecorder::SetInstance(MetricsRecorder* recorder) {
  222. g_instance = recorder;
  223. }
  224. // static
  225. MetricsRecorder* MetricsRecorder::GetInstance() {
  226. return g_instance;
  227. }
  228. MetricsRecorder::MetricsRecorder()
  229. : observer_list_(std::make_unique<ObserverList>()) {}
  230. MetricsRecorder::~MetricsRecorder() = default;
  231. void MetricsRecorder::NotifyOnPreUpload() {
  232. for (auto& o : observer_list_->list)
  233. o.OnPreUpload();
  234. }
  235. void MetricsRecorder::AddObserver(Observer* o) {
  236. DCHECK(o);
  237. observer_list_->list.AddObserver(o);
  238. }
  239. void MetricsRecorder::RemoveObserver(Observer* o) {
  240. DCHECK(o);
  241. observer_list_->list.RemoveObserver(o);
  242. }
  243. void RecordCastEvent(const std::string& event,
  244. bool has_extra_value,
  245. int64_t value,
  246. MetricsRecorder* metrics_recorder) {
  247. DCHECK(metrics_recorder);
  248. auto event_builder = metrics_recorder->CreateEventBuilder(event);
  249. if (has_extra_value) {
  250. event_builder->SetExtraValue(value);
  251. }
  252. metrics_recorder->RecordCastEvent(std::move(event_builder));
  253. }
  254. void RecordCastEventWithMetadata(
  255. const std::string& event,
  256. const base::flat_map<std::string, int64_t>& settings_map,
  257. MetricsRecorder* metrics_recorder) {
  258. DCHECK(metrics_recorder);
  259. auto event_builder = metrics_recorder->CreateEventBuilder(event);
  260. for (const auto& kv_pair : settings_map) {
  261. event_builder->AddMetadata(kv_pair.first, kv_pair.second);
  262. }
  263. metrics_recorder->RecordCastEvent(std::move(event_builder));
  264. }
  265. } // namespace chromecast