1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/metrics/structured/event.h"
6 
7 #include <map>
8 #include <memory>
9 #include <string>
10 
11 #include "base/system/sys_info.h"
12 #include "base/uuid.h"
13 #include "base/values.h"
14 #include "components/metrics/structured/structured_metrics_client.h"
15 
16 namespace metrics::structured {
17 
MetricValue(MetricType type,base::Value value)18 Event::MetricValue::MetricValue(MetricType type, base::Value value)
19     : type(type), value(std::move(value)) {}
20 
21 Event::MetricValue::MetricValue(Event::MetricValue&& other) = default;
22 Event::MetricValue& Event::MetricValue::operator=(Event::MetricValue&& other) =
23     default;
24 
operator ==(const Event::MetricValue & rhs) const25 bool Event::MetricValue::operator==(const Event::MetricValue& rhs) const {
26   return type == rhs.type && value == rhs.value;
27 }
28 
29 Event::MetricValue::~MetricValue() = default;
30 
EventSequenceMetadata(int reset_counter)31 Event::EventSequenceMetadata::EventSequenceMetadata(int reset_counter)
32     : reset_counter(reset_counter),
33       event_unique_id(base::Uuid::GenerateRandomV4().AsLowercaseString()) {}
34 
35 Event::EventSequenceMetadata::EventSequenceMetadata(
36     const Event::EventSequenceMetadata& other) = default;
37 Event::EventSequenceMetadata& Event::EventSequenceMetadata::operator=(
38     const Event::EventSequenceMetadata& other) = default;
39 
40 Event::EventSequenceMetadata::~EventSequenceMetadata() = default;
41 
42 Event::Event() = default;
Event(const std::string & project_name,const std::string & event_name)43 Event::Event(const std::string& project_name, const std::string& event_name)
44     : project_name_(project_name), event_name_(event_name) {}
Event(const std::string & project_name,const std::string & event_name,bool is_event_sequence)45 Event::Event(const std::string& project_name,
46              const std::string& event_name,
47              bool is_event_sequence)
48     : project_name_(project_name),
49       event_name_(event_name),
50       is_event_sequence_(is_event_sequence) {}
51 
52 Event::~Event() = default;
53 
Event(Event && other)54 Event::Event(Event&& other)
55     : project_name_(std::move(other.project_name_)),
56       event_name_(std::move(other.event_name_)),
57       metric_values_(std::move(other.metric_values_)),
58       recorded_time_since_boot_(std::move(other.recorded_time_since_boot_)),
59       event_sequence_metadata_(std::move(other.event_sequence_metadata_)),
60       is_event_sequence_(other.is_event_sequence_) {}
61 
operator =(Event && other)62 Event& Event::operator=(Event&& other) {
63   project_name_ = std::move(other.project_name_);
64   event_name_ = std::move(other.event_name_);
65   metric_values_ = std::move(other.metric_values_);
66   recorded_time_since_boot_ = std::move(other.recorded_time_since_boot_);
67   event_sequence_metadata_ = std::move(other.event_sequence_metadata_);
68   is_event_sequence_ = other.is_event_sequence_;
69   return *this;
70 }
71 
IsEventSequenceType() const72 bool Event::IsEventSequenceType() const {
73   return is_event_sequence_;
74 }
75 
Clone() const76 Event Event::Clone() const {
77   auto clone = Event(project_name_, event_name_, is_event_sequence_);
78   for (const auto& metric : metric_values()) {
79     const Event::MetricValue& metric_value = metric.second;
80     clone.AddMetric(metric.first, metric_value.type,
81                     metric_value.value.Clone());
82   }
83 
84   if (recorded_time_since_boot_.has_value())
85     clone.SetRecordedTimeSinceBoot(recorded_time_since_boot_.value());
86 
87   if (IsEventSequenceType() && event_sequence_metadata_.has_value()) {
88     clone.SetEventSequenceMetadata(event_sequence_metadata_.value());
89   }
90 
91   return clone;
92 }
93 
Record()94 void Event::Record() {
95   // Records uptime if event sequence type and it has not been explicitly set.
96   if (IsEventSequenceType() && !recorded_time_since_boot_.has_value())
97     recorded_time_since_boot_ = base::SysInfo::Uptime();
98 
99   StructuredMetricsClient::Get()->Record(std::move(*this));
100 }
101 
project_name() const102 const std::string& Event::project_name() const {
103   return project_name_;
104 }
105 
event_name() const106 const std::string& Event::event_name() const {
107   return event_name_;
108 }
109 
is_event_sequence() const110 bool Event::is_event_sequence() const {
111   return is_event_sequence_;
112 }
113 
metric_values() const114 const std::map<std::string, Event::MetricValue>& Event::metric_values() const {
115   return metric_values_;
116 }
117 
event_sequence_metadata() const118 const Event::EventSequenceMetadata& Event::event_sequence_metadata() const {
119   DCHECK(event_sequence_metadata_.has_value());
120   return event_sequence_metadata_.value();
121 }
122 
recorded_time_since_boot() const123 const base::TimeDelta Event::recorded_time_since_boot() const {
124   DCHECK(recorded_time_since_boot_.has_value());
125   return recorded_time_since_boot_.value();
126 }
127 
AddMetric(const std::string & metric_name,Event::MetricType type,base::Value && value)128 bool Event::AddMetric(const std::string& metric_name,
129                       Event::MetricType type,
130                       base::Value&& value) {
131   bool valid = true;
132   switch (type) {
133     case MetricType::kHmac:
134       valid = value.is_string();
135       break;
136     // no base::LongValue so int64_t is encoded in a string.
137     case MetricType::kLong:
138       valid = value.is_string();
139       break;
140     case MetricType::kInt:
141       valid = value.is_int();
142       break;
143     case MetricType::kDouble:
144       valid = value.is_double();
145       break;
146     case MetricType::kRawString:
147       valid = value.is_string();
148       break;
149     case MetricType::kBoolean:
150       valid = value.is_bool();
151       break;
152   }
153   if (!valid)
154     return false;
155 
156   auto pair =
157       metric_values_.emplace(metric_name, MetricValue(type, std::move(value)));
158   return pair.second;
159 }
160 
SetEventSequenceMetadata(const Event::EventSequenceMetadata & event_sequence_metadata)161 void Event::SetEventSequenceMetadata(
162     const Event::EventSequenceMetadata& event_sequence_metadata) {
163   event_sequence_metadata_ = event_sequence_metadata;
164 }
165 
SetRecordedTimeSinceBoot(base::TimeDelta recorded_time_since_boot)166 void Event::SetRecordedTimeSinceBoot(base::TimeDelta recorded_time_since_boot) {
167   recorded_time_since_boot_ = recorded_time_since_boot;
168 }
169 
170 }  // namespace metrics::structured
171