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