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