1 // Copyright 2014 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
5 #include "components/metrics/serialization/metric_sample.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/stringprintf.h"
14
15 namespace metrics {
16
MetricSample(MetricSample::SampleType sample_type,const std::string & metric_name,int sample,int min,int max,int bucket_count)17 MetricSample::MetricSample(MetricSample::SampleType sample_type,
18 const std::string& metric_name,
19 int sample,
20 int min,
21 int max,
22 int bucket_count)
23 : type_(sample_type),
24 name_(metric_name),
25 sample_(sample),
26 min_(min),
27 max_(max),
28 bucket_count_(bucket_count) {
29 }
30
~MetricSample()31 MetricSample::~MetricSample() {
32 }
33
IsValid() const34 bool MetricSample::IsValid() const {
35 return name().find(' ') == std::string::npos &&
36 name().find('\0') == std::string::npos && !name().empty();
37 }
38
ToString() const39 std::string MetricSample::ToString() const {
40 if (type_ == CRASH) {
41 return base::StringPrintf("crash%c%s%c",
42 '\0',
43 name().c_str(),
44 '\0');
45 } else if (type_ == SPARSE_HISTOGRAM) {
46 return base::StringPrintf("sparsehistogram%c%s %d%c",
47 '\0',
48 name().c_str(),
49 sample_,
50 '\0');
51 } else if (type_ == LINEAR_HISTOGRAM) {
52 return base::StringPrintf("linearhistogram%c%s %d %d%c",
53 '\0',
54 name().c_str(),
55 sample_,
56 max_,
57 '\0');
58 } else if (type_ == HISTOGRAM) {
59 return base::StringPrintf("histogram%c%s %d %d %d %d%c",
60 '\0',
61 name().c_str(),
62 sample_,
63 min_,
64 max_,
65 bucket_count_,
66 '\0');
67 } else {
68 // The type can only be USER_ACTION.
69 CHECK_EQ(type_, USER_ACTION);
70 return base::StringPrintf("useraction%c%s%c",
71 '\0',
72 name().c_str(),
73 '\0');
74 }
75 }
76
sample() const77 const int MetricSample::sample() const {
78 CHECK_NE(type_, USER_ACTION);
79 CHECK_NE(type_, CRASH);
80 return sample_;
81 }
82
min() const83 const int MetricSample::min() const {
84 CHECK_EQ(type_, HISTOGRAM);
85 return min_;
86 }
87
max() const88 const int MetricSample::max() const {
89 CHECK_NE(type_, CRASH);
90 CHECK_NE(type_, USER_ACTION);
91 CHECK_NE(type_, SPARSE_HISTOGRAM);
92 return max_;
93 }
94
bucket_count() const95 const int MetricSample::bucket_count() const {
96 CHECK_EQ(type_, HISTOGRAM);
97 return bucket_count_;
98 }
99
100 // static
CrashSample(const std::string & crash_name)101 scoped_ptr<MetricSample> MetricSample::CrashSample(
102 const std::string& crash_name) {
103 return scoped_ptr<MetricSample>(
104 new MetricSample(CRASH, crash_name, 0, 0, 0, 0));
105 }
106
107 // static
HistogramSample(const std::string & histogram_name,int sample,int min,int max,int bucket_count)108 scoped_ptr<MetricSample> MetricSample::HistogramSample(
109 const std::string& histogram_name,
110 int sample,
111 int min,
112 int max,
113 int bucket_count) {
114 return scoped_ptr<MetricSample>(new MetricSample(
115 HISTOGRAM, histogram_name, sample, min, max, bucket_count));
116 }
117
118 // static
ParseHistogram(const std::string & serialized_histogram)119 scoped_ptr<MetricSample> MetricSample::ParseHistogram(
120 const std::string& serialized_histogram) {
121 std::vector<std::string> parts;
122 base::SplitString(serialized_histogram, ' ', &parts);
123
124 if (parts.size() != 5)
125 return scoped_ptr<MetricSample>();
126 int sample, min, max, bucket_count;
127 if (parts[0].empty() || !base::StringToInt(parts[1], &sample) ||
128 !base::StringToInt(parts[2], &min) ||
129 !base::StringToInt(parts[3], &max) ||
130 !base::StringToInt(parts[4], &bucket_count)) {
131 return scoped_ptr<MetricSample>();
132 }
133
134 return HistogramSample(parts[0], sample, min, max, bucket_count);
135 }
136
137 // static
SparseHistogramSample(const std::string & histogram_name,int sample)138 scoped_ptr<MetricSample> MetricSample::SparseHistogramSample(
139 const std::string& histogram_name,
140 int sample) {
141 return scoped_ptr<MetricSample>(
142 new MetricSample(SPARSE_HISTOGRAM, histogram_name, sample, 0, 0, 0));
143 }
144
145 // static
ParseSparseHistogram(const std::string & serialized_histogram)146 scoped_ptr<MetricSample> MetricSample::ParseSparseHistogram(
147 const std::string& serialized_histogram) {
148 std::vector<std::string> parts;
149 base::SplitString(serialized_histogram, ' ', &parts);
150 if (parts.size() != 2)
151 return scoped_ptr<MetricSample>();
152 int sample;
153 if (parts[0].empty() || !base::StringToInt(parts[1], &sample))
154 return scoped_ptr<MetricSample>();
155
156 return SparseHistogramSample(parts[0], sample);
157 }
158
159 // static
LinearHistogramSample(const std::string & histogram_name,int sample,int max)160 scoped_ptr<MetricSample> MetricSample::LinearHistogramSample(
161 const std::string& histogram_name,
162 int sample,
163 int max) {
164 return scoped_ptr<MetricSample>(
165 new MetricSample(LINEAR_HISTOGRAM, histogram_name, sample, 0, max, 0));
166 }
167
168 // static
ParseLinearHistogram(const std::string & serialized_histogram)169 scoped_ptr<MetricSample> MetricSample::ParseLinearHistogram(
170 const std::string& serialized_histogram) {
171 std::vector<std::string> parts;
172 int sample, max;
173 base::SplitString(serialized_histogram, ' ', &parts);
174 if (parts.size() != 3)
175 return scoped_ptr<MetricSample>();
176 if (parts[0].empty() || !base::StringToInt(parts[1], &sample) ||
177 !base::StringToInt(parts[2], &max)) {
178 return scoped_ptr<MetricSample>();
179 }
180
181 return LinearHistogramSample(parts[0], sample, max);
182 }
183
184 // static
UserActionSample(const std::string & action_name)185 scoped_ptr<MetricSample> MetricSample::UserActionSample(
186 const std::string& action_name) {
187 return scoped_ptr<MetricSample>(
188 new MetricSample(USER_ACTION, action_name, 0, 0, 0, 0));
189 }
190
IsEqual(const MetricSample & metric)191 bool MetricSample::IsEqual(const MetricSample& metric) {
192 return type_ == metric.type_ && name_ == metric.name_ &&
193 sample_ == metric.sample_ && min_ == metric.min_ &&
194 max_ == metric.max_ && bucket_count_ == metric.bucket_count_;
195 }
196
197 } // namespace metrics
198