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/nacl/renderer/histogram.h"
6
7#include "base/metrics/histogram.h"
8
9namespace nacl {
10
11void HistogramCustomCounts(const std::string& name,
12                           int32_t sample,
13                           int32_t min,
14                           int32_t max,
15                           uint32_t bucket_count) {
16  base::HistogramBase* counter =
17      base::Histogram::FactoryGet(
18          name,
19          min,
20          max,
21          bucket_count,
22          base::HistogramBase::kUmaTargetedHistogramFlag);
23  // The histogram can be NULL if it is constructed with bad arguments.  Ignore
24  // that data for this API.  An error message will be logged.
25  if (counter)
26    counter->Add(sample);
27}
28
29void HistogramEnumerate(const std::string& name,
30                        int32_t sample,
31                        int32_t boundary_value) {
32  base::HistogramBase* counter =
33      base::LinearHistogram::FactoryGet(
34          name,
35          1,
36          boundary_value,
37          boundary_value + 1,
38          base::HistogramBase::kUmaTargetedHistogramFlag);
39  counter->Add(sample);
40}
41
42void HistogramEnumerateLoadStatus(PP_NaClError error_code,
43                                  bool is_installed) {
44  HistogramEnumerate("NaCl.LoadStatus.Plugin", error_code, PP_NACL_ERROR_MAX);
45
46  // Gather data to see if being installed changes load outcomes.
47  const char* name = is_installed ?
48      "NaCl.LoadStatus.Plugin.InstalledApp" :
49      "NaCl.LoadStatus.Plugin.NotInstalledApp";
50  HistogramEnumerate(name, error_code, PP_NACL_ERROR_MAX);
51}
52
53void HistogramEnumerateOsArch(const std::string& sandbox_isa) {
54  enum NaClOSArch {
55    kNaClLinux32 = 0,
56    kNaClLinux64,
57    kNaClLinuxArm,
58    kNaClMac32,
59    kNaClMac64,
60    kNaClMacArm,
61    kNaClWin32,
62    kNaClWin64,
63    kNaClWinArm,
64    kNaClLinuxMips,
65    kNaClOSArchMax
66  };
67
68  NaClOSArch os_arch = kNaClOSArchMax;
69#if OS_LINUX
70  os_arch = kNaClLinux32;
71#elif OS_MACOSX
72  os_arch = kNaClMac32;
73#elif OS_WIN
74  os_arch = kNaClWin32;
75#endif
76
77  if (sandbox_isa == "x86-64")
78    os_arch = static_cast<NaClOSArch>(os_arch + 1);
79  if (sandbox_isa == "arm")
80    os_arch = static_cast<NaClOSArch>(os_arch + 2);
81  if (sandbox_isa == "mips32")
82    os_arch = kNaClLinuxMips;
83
84  HistogramEnumerate("NaCl.Client.OSArch", os_arch, kNaClOSArchMax);
85}
86
87// Records values up to 20 seconds.
88// These constants MUST match those in
89// ppapi/native_client/src/trusted/plugin/plugin.cc
90void HistogramTimeSmall(const std::string& name, int64_t sample) {
91  if (sample < 0)
92    sample = 0;
93  base::HistogramBase* counter = base::Histogram::FactoryTimeGet(
94      name,
95      base::TimeDelta::FromMilliseconds(1),
96      base::TimeDelta::FromMilliseconds(20000),
97      100,
98      base::HistogramBase::kUmaTargetedHistogramFlag);
99  if (counter)
100    counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
101}
102
103// Records values up to 3 minutes, 20 seconds.
104// These constants MUST match those in
105// ppapi/native_client/src/trusted/plugin/plugin.cc
106void HistogramTimeMedium(const std::string& name, int64_t sample) {
107  if (sample < 0)
108    sample = 0;
109  base::HistogramBase* counter = base::Histogram::FactoryTimeGet(
110      name,
111      base::TimeDelta::FromMilliseconds(10),
112      base::TimeDelta::FromMilliseconds(200000),
113      100,
114      base::HistogramBase::kUmaTargetedHistogramFlag);
115  if (counter)
116    counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
117}
118
119// Records values up to 33 minutes.
120// These constants MUST match those in
121// ppapi/native_client/src/trusted/plugin/plugin.cc
122void HistogramTimeLarge(const std::string& name, int64_t sample) {
123  if (sample < 0)
124    sample = 0;
125  base::HistogramBase* counter = base::Histogram::FactoryTimeGet(
126      name,
127      base::TimeDelta::FromMilliseconds(100),
128      base::TimeDelta::FromMilliseconds(2000000),
129      100,
130      base::HistogramBase::kUmaTargetedHistogramFlag);
131  if (counter)
132    counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
133}
134
135// Records values up to 12 minutes.
136void HistogramTimeTranslation(const std::string& name, int64_t sample_ms) {
137  if (sample_ms < 0)
138    sample_ms = 0;
139  base::HistogramBase* counter = base::Histogram::FactoryTimeGet(
140      name,
141      base::TimeDelta::FromMilliseconds(10),
142      base::TimeDelta::FromMilliseconds(720000),
143      100,
144      base::HistogramBase::kUmaTargetedHistogramFlag);
145  if (counter)
146    counter->AddTime(base::TimeDelta::FromMilliseconds(sample_ms));
147}
148
149void HistogramStartupTimeSmall(const std::string& name,
150                               base::TimeDelta td,
151                               int64_t nexe_size) {
152  HistogramTimeSmall(name, static_cast<int64_t>(td.InMilliseconds()));
153  if (nexe_size > 0) {
154    float size_in_MB = static_cast<float>(nexe_size) / (1024.f * 1024.f);
155    HistogramTimeSmall(name + "PerMB",
156                       static_cast<int64_t>(td.InMilliseconds() / size_in_MB));
157  }
158}
159
160void HistogramStartupTimeMedium(const std::string& name,
161                                base::TimeDelta td,
162                                int64_t nexe_size) {
163  HistogramTimeMedium(name, static_cast<int64_t>(td.InMilliseconds()));
164  if (nexe_size > 0) {
165    float size_in_MB = static_cast<float>(nexe_size) / (1024.f * 1024.f);
166    HistogramTimeMedium(name + "PerMB",
167                        static_cast<int64_t>(td.InMilliseconds() / size_in_MB));
168  }
169}
170
171void HistogramSizeKB(const std::string& name, int32_t sample) {
172  if (sample < 0) return;
173  HistogramCustomCounts(name,
174                        sample,
175                        1,
176                        512 * 1024,  // A very large .nexe.
177                        100);
178}
179
180void HistogramHTTPStatusCode(const std::string& name,
181                             int32_t status) {
182  // Log the status codes in rough buckets - 1XX, 2XX, etc.
183  int sample = status / 100;
184  // HTTP status codes only go up to 5XX, using "6" to indicate an internal
185  // error.
186  // Note: installed files may have "0" for a status code.
187  if (status < 0 || status >= 600)
188    sample = 6;
189  HistogramEnumerate(name, sample, 7);
190}
191
192void HistogramEnumerateManifestIsDataURI(bool is_data_uri) {
193  HistogramEnumerate("NaCl.Manifest.IsDataURI", is_data_uri, 2);
194}
195
196void HistogramKBPerSec(const std::string& name, int64_t kb, int64_t us) {
197  if (kb < 0 || us <= 0) return;
198  static const double kMaxRate = 30 * 1000.0;  // max of 30MB/sec.
199  int32_t rate = std::min(kb / (us / 1000000.0), kMaxRate);
200  HistogramCustomCounts(name,
201                        rate,
202                        1,
203                        30 * 1000,  // max of 30 MB/sec.
204                        100);
205}
206
207}  // namespace nacl
208