xref: /aosp_15_r20/external/cronet/components/metrics/serialization/metric_sample.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "components/metrics/serialization/metric_sample.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <string>
8*6777b538SAndroid Build Coastguard Worker #include <vector>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace metrics {
17*6777b538SAndroid Build Coastguard Worker 
MetricSample(MetricSample::SampleType sample_type,const std::string & metric_name,int sample,int min,int max,int bucket_count,int num_samples)18*6777b538SAndroid Build Coastguard Worker MetricSample::MetricSample(MetricSample::SampleType sample_type,
19*6777b538SAndroid Build Coastguard Worker                            const std::string& metric_name,
20*6777b538SAndroid Build Coastguard Worker                            int sample,
21*6777b538SAndroid Build Coastguard Worker                            int min,
22*6777b538SAndroid Build Coastguard Worker                            int max,
23*6777b538SAndroid Build Coastguard Worker                            int bucket_count,
24*6777b538SAndroid Build Coastguard Worker                            int num_samples)
25*6777b538SAndroid Build Coastguard Worker     : type_(sample_type),
26*6777b538SAndroid Build Coastguard Worker       name_(metric_name),
27*6777b538SAndroid Build Coastguard Worker       sample_(sample),
28*6777b538SAndroid Build Coastguard Worker       min_(min),
29*6777b538SAndroid Build Coastguard Worker       max_(max),
30*6777b538SAndroid Build Coastguard Worker       bucket_count_(bucket_count),
31*6777b538SAndroid Build Coastguard Worker       num_samples_(num_samples) {}
32*6777b538SAndroid Build Coastguard Worker 
~MetricSample()33*6777b538SAndroid Build Coastguard Worker MetricSample::~MetricSample() {
34*6777b538SAndroid Build Coastguard Worker }
35*6777b538SAndroid Build Coastguard Worker 
IsValid() const36*6777b538SAndroid Build Coastguard Worker bool MetricSample::IsValid() const {
37*6777b538SAndroid Build Coastguard Worker   return name().find(' ') == std::string::npos &&
38*6777b538SAndroid Build Coastguard Worker          name().find('\0') == std::string::npos && !name().empty();
39*6777b538SAndroid Build Coastguard Worker }
40*6777b538SAndroid Build Coastguard Worker 
ToString() const41*6777b538SAndroid Build Coastguard Worker std::string MetricSample::ToString() const {
42*6777b538SAndroid Build Coastguard Worker   std::string samples =
43*6777b538SAndroid Build Coastguard Worker       (num_samples_ == 1) ? "" : base::StringPrintf(" %d", num_samples_);
44*6777b538SAndroid Build Coastguard Worker   if (type_ == CRASH) {
45*6777b538SAndroid Build Coastguard Worker     return base::StringPrintf("crash%c%s%s%c", '\0', name().c_str(),
46*6777b538SAndroid Build Coastguard Worker                               samples.c_str(), '\0');
47*6777b538SAndroid Build Coastguard Worker   }
48*6777b538SAndroid Build Coastguard Worker   if (type_ == SPARSE_HISTOGRAM) {
49*6777b538SAndroid Build Coastguard Worker     return base::StringPrintf("sparsehistogram%c%s %d%s%c", '\0',
50*6777b538SAndroid Build Coastguard Worker                               name().c_str(), sample_, samples.c_str(), '\0');
51*6777b538SAndroid Build Coastguard Worker   }
52*6777b538SAndroid Build Coastguard Worker   if (type_ == LINEAR_HISTOGRAM) {
53*6777b538SAndroid Build Coastguard Worker     return base::StringPrintf("linearhistogram%c%s %d %d%s%c", '\0',
54*6777b538SAndroid Build Coastguard Worker                               name().c_str(), sample_, max_, samples.c_str(),
55*6777b538SAndroid Build Coastguard Worker                               '\0');
56*6777b538SAndroid Build Coastguard Worker   }
57*6777b538SAndroid Build Coastguard Worker   if (type_ == HISTOGRAM) {
58*6777b538SAndroid Build Coastguard Worker     return base::StringPrintf("histogram%c%s %d %d %d %d%s%c", '\0',
59*6777b538SAndroid Build Coastguard Worker                               name().c_str(), sample_, min_, max_,
60*6777b538SAndroid Build Coastguard Worker                               bucket_count_, samples.c_str(), '\0');
61*6777b538SAndroid Build Coastguard Worker   }
62*6777b538SAndroid Build Coastguard Worker   // The type can only be USER_ACTION.
63*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(type_, USER_ACTION);
64*6777b538SAndroid Build Coastguard Worker   return base::StringPrintf("useraction%c%s%s%c", '\0', name().c_str(),
65*6777b538SAndroid Build Coastguard Worker                             samples.c_str(), '\0');
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker 
sample() const68*6777b538SAndroid Build Coastguard Worker int MetricSample::sample() const {
69*6777b538SAndroid Build Coastguard Worker   CHECK_NE(type_, USER_ACTION);
70*6777b538SAndroid Build Coastguard Worker   CHECK_NE(type_, CRASH);
71*6777b538SAndroid Build Coastguard Worker   return sample_;
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker 
min() const74*6777b538SAndroid Build Coastguard Worker int MetricSample::min() const {
75*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(type_, HISTOGRAM);
76*6777b538SAndroid Build Coastguard Worker   return min_;
77*6777b538SAndroid Build Coastguard Worker }
78*6777b538SAndroid Build Coastguard Worker 
max() const79*6777b538SAndroid Build Coastguard Worker int MetricSample::max() const {
80*6777b538SAndroid Build Coastguard Worker   CHECK_NE(type_, CRASH);
81*6777b538SAndroid Build Coastguard Worker   CHECK_NE(type_, USER_ACTION);
82*6777b538SAndroid Build Coastguard Worker   CHECK_NE(type_, SPARSE_HISTOGRAM);
83*6777b538SAndroid Build Coastguard Worker   return max_;
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker 
bucket_count() const86*6777b538SAndroid Build Coastguard Worker int MetricSample::bucket_count() const {
87*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(type_, HISTOGRAM);
88*6777b538SAndroid Build Coastguard Worker   return bucket_count_;
89*6777b538SAndroid Build Coastguard Worker }
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker // static
CrashSample(const std::string & crash_name,int num_samples)92*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::CrashSample(
93*6777b538SAndroid Build Coastguard Worker     const std::string& crash_name,
94*6777b538SAndroid Build Coastguard Worker     int num_samples) {
95*6777b538SAndroid Build Coastguard Worker   return std::make_unique<MetricSample>(CRASH, crash_name, 0, 0, 0, 0,
96*6777b538SAndroid Build Coastguard Worker                                         num_samples);
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker // static
ParseCrash(const std::string & serialized)100*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::ParseCrash(
101*6777b538SAndroid Build Coastguard Worker     const std::string& serialized) {
102*6777b538SAndroid Build Coastguard Worker   std::vector<base::StringPiece> parts = base::SplitStringPiece(
103*6777b538SAndroid Build Coastguard Worker       serialized, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker   if (parts.size() != 1 && parts.size() != 2) {
106*6777b538SAndroid Build Coastguard Worker     return nullptr;
107*6777b538SAndroid Build Coastguard Worker   }
108*6777b538SAndroid Build Coastguard Worker   if (parts[0].empty()) {
109*6777b538SAndroid Build Coastguard Worker     return nullptr;
110*6777b538SAndroid Build Coastguard Worker   }
111*6777b538SAndroid Build Coastguard Worker   int num_samples = 1;
112*6777b538SAndroid Build Coastguard Worker   if (parts.size() == 2) {
113*6777b538SAndroid Build Coastguard Worker     if (!base::StringToInt(parts[1], &num_samples) || num_samples <= 0) {
114*6777b538SAndroid Build Coastguard Worker       return nullptr;
115*6777b538SAndroid Build Coastguard Worker     }
116*6777b538SAndroid Build Coastguard Worker   }
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   return CrashSample(std::string(parts[0]), num_samples);
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker // static
HistogramSample(const std::string & histogram_name,int sample,int min,int max,int bucket_count,int num_samples)122*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::HistogramSample(
123*6777b538SAndroid Build Coastguard Worker     const std::string& histogram_name,
124*6777b538SAndroid Build Coastguard Worker     int sample,
125*6777b538SAndroid Build Coastguard Worker     int min,
126*6777b538SAndroid Build Coastguard Worker     int max,
127*6777b538SAndroid Build Coastguard Worker     int bucket_count,
128*6777b538SAndroid Build Coastguard Worker     int num_samples) {
129*6777b538SAndroid Build Coastguard Worker   return std::make_unique<MetricSample>(HISTOGRAM, histogram_name, sample, min,
130*6777b538SAndroid Build Coastguard Worker                                         max, bucket_count, num_samples);
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker // static
ParseHistogram(const std::string & serialized_histogram)134*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::ParseHistogram(
135*6777b538SAndroid Build Coastguard Worker     const std::string& serialized_histogram) {
136*6777b538SAndroid Build Coastguard Worker   std::vector<base::StringPiece> parts = base::SplitStringPiece(
137*6777b538SAndroid Build Coastguard Worker       serialized_histogram, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
138*6777b538SAndroid Build Coastguard Worker 
139*6777b538SAndroid Build Coastguard Worker   if (parts.size() != 5 && parts.size() != 6) {
140*6777b538SAndroid Build Coastguard Worker     return nullptr;
141*6777b538SAndroid Build Coastguard Worker   }
142*6777b538SAndroid Build Coastguard Worker   int sample, min, max, bucket_count;
143*6777b538SAndroid Build Coastguard Worker   if (parts[0].empty() || !base::StringToInt(parts[1], &sample) ||
144*6777b538SAndroid Build Coastguard Worker       !base::StringToInt(parts[2], &min) ||
145*6777b538SAndroid Build Coastguard Worker       !base::StringToInt(parts[3], &max) ||
146*6777b538SAndroid Build Coastguard Worker       !base::StringToInt(parts[4], &bucket_count)) {
147*6777b538SAndroid Build Coastguard Worker     return nullptr;
148*6777b538SAndroid Build Coastguard Worker   }
149*6777b538SAndroid Build Coastguard Worker   int num_samples = 1;
150*6777b538SAndroid Build Coastguard Worker   if (parts.size() == 6) {
151*6777b538SAndroid Build Coastguard Worker     if (!base::StringToInt(parts[5], &num_samples) || num_samples <= 0) {
152*6777b538SAndroid Build Coastguard Worker       return nullptr;
153*6777b538SAndroid Build Coastguard Worker     }
154*6777b538SAndroid Build Coastguard Worker   }
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker   return HistogramSample(std::string(parts[0]), sample, min, max, bucket_count,
157*6777b538SAndroid Build Coastguard Worker                          num_samples);
158*6777b538SAndroid Build Coastguard Worker }
159*6777b538SAndroid Build Coastguard Worker 
160*6777b538SAndroid Build Coastguard Worker // static
SparseHistogramSample(const std::string & histogram_name,int sample,int num_samples)161*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::SparseHistogramSample(
162*6777b538SAndroid Build Coastguard Worker     const std::string& histogram_name,
163*6777b538SAndroid Build Coastguard Worker     int sample,
164*6777b538SAndroid Build Coastguard Worker     int num_samples) {
165*6777b538SAndroid Build Coastguard Worker   return std::make_unique<MetricSample>(SPARSE_HISTOGRAM, histogram_name,
166*6777b538SAndroid Build Coastguard Worker                                         sample, 0, 0, 0, num_samples);
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker // static
ParseSparseHistogram(const std::string & serialized_histogram)170*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::ParseSparseHistogram(
171*6777b538SAndroid Build Coastguard Worker     const std::string& serialized_histogram) {
172*6777b538SAndroid Build Coastguard Worker   std::vector<base::StringPiece> parts = base::SplitStringPiece(
173*6777b538SAndroid Build Coastguard Worker       serialized_histogram, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
174*6777b538SAndroid Build Coastguard Worker   if (parts.size() != 2 && parts.size() != 3) {
175*6777b538SAndroid Build Coastguard Worker     return nullptr;
176*6777b538SAndroid Build Coastguard Worker   }
177*6777b538SAndroid Build Coastguard Worker   int sample;
178*6777b538SAndroid Build Coastguard Worker   if (parts[0].empty() || !base::StringToInt(parts[1], &sample))
179*6777b538SAndroid Build Coastguard Worker     return nullptr;
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker   int num_samples = 1;
182*6777b538SAndroid Build Coastguard Worker   if (parts.size() == 3) {
183*6777b538SAndroid Build Coastguard Worker     if (!base::StringToInt(parts[2], &num_samples) || num_samples <= 0) {
184*6777b538SAndroid Build Coastguard Worker       return nullptr;
185*6777b538SAndroid Build Coastguard Worker     }
186*6777b538SAndroid Build Coastguard Worker   }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   return SparseHistogramSample(std::string(parts[0]), sample, num_samples);
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker 
191*6777b538SAndroid Build Coastguard Worker // static
LinearHistogramSample(const std::string & histogram_name,int sample,int max,int num_samples)192*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::LinearHistogramSample(
193*6777b538SAndroid Build Coastguard Worker     const std::string& histogram_name,
194*6777b538SAndroid Build Coastguard Worker     int sample,
195*6777b538SAndroid Build Coastguard Worker     int max,
196*6777b538SAndroid Build Coastguard Worker     int num_samples) {
197*6777b538SAndroid Build Coastguard Worker   return std::make_unique<MetricSample>(LINEAR_HISTOGRAM, histogram_name,
198*6777b538SAndroid Build Coastguard Worker                                         sample, 0, max, 0, num_samples);
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker // static
ParseLinearHistogram(const std::string & serialized_histogram)202*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::ParseLinearHistogram(
203*6777b538SAndroid Build Coastguard Worker     const std::string& serialized_histogram) {
204*6777b538SAndroid Build Coastguard Worker   std::vector<base::StringPiece> parts = base::SplitStringPiece(
205*6777b538SAndroid Build Coastguard Worker       serialized_histogram, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
206*6777b538SAndroid Build Coastguard Worker   int sample, max;
207*6777b538SAndroid Build Coastguard Worker   if (parts.size() != 3 && parts.size() != 4) {
208*6777b538SAndroid Build Coastguard Worker     return nullptr;
209*6777b538SAndroid Build Coastguard Worker   }
210*6777b538SAndroid Build Coastguard Worker   if (parts[0].empty() || !base::StringToInt(parts[1], &sample) ||
211*6777b538SAndroid Build Coastguard Worker       !base::StringToInt(parts[2], &max)) {
212*6777b538SAndroid Build Coastguard Worker     return nullptr;
213*6777b538SAndroid Build Coastguard Worker   }
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker   int num_samples = 1;
216*6777b538SAndroid Build Coastguard Worker   if (parts.size() == 4) {
217*6777b538SAndroid Build Coastguard Worker     if (!base::StringToInt(parts[3], &num_samples) || num_samples <= 0) {
218*6777b538SAndroid Build Coastguard Worker       return nullptr;
219*6777b538SAndroid Build Coastguard Worker     }
220*6777b538SAndroid Build Coastguard Worker   }
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker   return LinearHistogramSample(std::string(parts[0]), sample, max, num_samples);
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker // static
UserActionSample(const std::string & action_name,int num_samples)226*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::UserActionSample(
227*6777b538SAndroid Build Coastguard Worker     const std::string& action_name,
228*6777b538SAndroid Build Coastguard Worker     int num_samples) {
229*6777b538SAndroid Build Coastguard Worker   return std::make_unique<MetricSample>(USER_ACTION, action_name, 0, 0, 0, 0,
230*6777b538SAndroid Build Coastguard Worker                                         num_samples);
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker 
233*6777b538SAndroid Build Coastguard Worker // static
ParseUserAction(const std::string & serialized)234*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MetricSample> MetricSample::ParseUserAction(
235*6777b538SAndroid Build Coastguard Worker     const std::string& serialized) {
236*6777b538SAndroid Build Coastguard Worker   std::vector<base::StringPiece> parts = base::SplitStringPiece(
237*6777b538SAndroid Build Coastguard Worker       serialized, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker   if (parts.size() != 1 && parts.size() != 2) {
240*6777b538SAndroid Build Coastguard Worker     return nullptr;
241*6777b538SAndroid Build Coastguard Worker   }
242*6777b538SAndroid Build Coastguard Worker   if (parts[0].empty()) {
243*6777b538SAndroid Build Coastguard Worker     return nullptr;
244*6777b538SAndroid Build Coastguard Worker   }
245*6777b538SAndroid Build Coastguard Worker   int num_samples = 1;
246*6777b538SAndroid Build Coastguard Worker   if (parts.size() == 2) {
247*6777b538SAndroid Build Coastguard Worker     if (!base::StringToInt(parts[1], &num_samples) || num_samples <= 0) {
248*6777b538SAndroid Build Coastguard Worker       return nullptr;
249*6777b538SAndroid Build Coastguard Worker     }
250*6777b538SAndroid Build Coastguard Worker   }
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker   return UserActionSample(std::string(parts[0]), num_samples);
253*6777b538SAndroid Build Coastguard Worker }
254*6777b538SAndroid Build Coastguard Worker 
IsEqual(const MetricSample & metric)255*6777b538SAndroid Build Coastguard Worker bool MetricSample::IsEqual(const MetricSample& metric) {
256*6777b538SAndroid Build Coastguard Worker   return type_ == metric.type_ && name_ == metric.name_ &&
257*6777b538SAndroid Build Coastguard Worker          sample_ == metric.sample_ && min_ == metric.min_ &&
258*6777b538SAndroid Build Coastguard Worker          max_ == metric.max_ && bucket_count_ == metric.bucket_count_ &&
259*6777b538SAndroid Build Coastguard Worker          num_samples_ == metric.num_samples_;
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker 
262*6777b538SAndroid Build Coastguard Worker }  // namespace metrics
263