|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "components/nacl/renderer/histogram.h" | 
|  |  | 
|  | #include <algorithm> | 
|  |  | 
|  | #include "base/metrics/histogram.h" | 
|  |  | 
|  | namespace nacl { | 
|  |  | 
|  | void HistogramCustomCounts(const std::string& name, | 
|  | int32_t sample, | 
|  | int32_t min, | 
|  | int32_t max, | 
|  | uint32_t bucket_count) { | 
|  | base::HistogramBase* counter = | 
|  | base::Histogram::FactoryGet( | 
|  | name, | 
|  | min, | 
|  | max, | 
|  | bucket_count, | 
|  | base::HistogramBase::kUmaTargetedHistogramFlag); | 
|  | // The histogram can be NULL if it is constructed with bad arguments.  Ignore | 
|  | // that data for this API.  An error message will be logged. | 
|  | if (counter) | 
|  | counter->Add(sample); | 
|  | } | 
|  |  | 
|  | void HistogramEnumerate(const std::string& name, | 
|  | int32_t sample, | 
|  | int32_t boundary_value) { | 
|  | base::HistogramBase* counter = | 
|  | base::LinearHistogram::FactoryGet( | 
|  | name, | 
|  | 1, | 
|  | boundary_value, | 
|  | boundary_value + 1, | 
|  | base::HistogramBase::kUmaTargetedHistogramFlag); | 
|  | counter->Add(sample); | 
|  | } | 
|  |  | 
|  | void HistogramEnumerateLoadStatus(PP_NaClError error_code, | 
|  | bool is_installed) { | 
|  | HistogramEnumerate("NaCl.LoadStatus.Plugin", error_code, PP_NACL_ERROR_MAX); | 
|  |  | 
|  | // Gather data to see if being installed changes load outcomes. | 
|  | const char* name = is_installed ? | 
|  | "NaCl.LoadStatus.Plugin.InstalledApp" : | 
|  | "NaCl.LoadStatus.Plugin.NotInstalledApp"; | 
|  | HistogramEnumerate(name, error_code, PP_NACL_ERROR_MAX); | 
|  | } | 
|  |  | 
|  | void HistogramEnumerateOsArch(const std::string& sandbox_isa) { | 
|  | enum NaClOSArch { | 
|  | kNaClLinux32 = 0, | 
|  | kNaClLinux64, | 
|  | kNaClLinuxArm, | 
|  | kNaClMac32, | 
|  | kNaClMac64, | 
|  | kNaClMacArm, | 
|  | kNaClWin32, | 
|  | kNaClWin64, | 
|  | kNaClWinArm, | 
|  | kNaClLinuxMips, | 
|  | kNaClOSArchMax | 
|  | }; | 
|  |  | 
|  | NaClOSArch os_arch = kNaClOSArchMax; | 
|  | #if OS_LINUX | 
|  | os_arch = kNaClLinux32; | 
|  | #elif OS_MACOSX | 
|  | os_arch = kNaClMac32; | 
|  | #elif OS_WIN | 
|  | os_arch = kNaClWin32; | 
|  | #endif | 
|  |  | 
|  | if (sandbox_isa == "x86-64") | 
|  | os_arch = static_cast<NaClOSArch>(os_arch + 1); | 
|  | if (sandbox_isa == "arm") | 
|  | os_arch = static_cast<NaClOSArch>(os_arch + 2); | 
|  | if (sandbox_isa == "mips32") | 
|  | os_arch = kNaClLinuxMips; | 
|  |  | 
|  | HistogramEnumerate("NaCl.Client.OSArch", os_arch, kNaClOSArchMax); | 
|  | } | 
|  |  | 
|  | // Records values up to 20 seconds. | 
|  | void HistogramTimeSmall(const std::string& name, int64_t sample) { | 
|  | if (sample < 0) | 
|  | sample = 0; | 
|  | base::HistogramBase* counter = base::Histogram::FactoryTimeGet( | 
|  | name, | 
|  | base::TimeDelta::FromMilliseconds(1), | 
|  | base::TimeDelta::FromMilliseconds(20000), | 
|  | 100, | 
|  | base::HistogramBase::kUmaTargetedHistogramFlag); | 
|  | if (counter) | 
|  | counter->AddTime(base::TimeDelta::FromMilliseconds(sample)); | 
|  | } | 
|  |  | 
|  | // Records values up to 3 minutes, 20 seconds. | 
|  | void HistogramTimeMedium(const std::string& name, int64_t sample) { | 
|  | if (sample < 0) | 
|  | sample = 0; | 
|  | base::HistogramBase* counter = base::Histogram::FactoryTimeGet( | 
|  | name, | 
|  | base::TimeDelta::FromMilliseconds(10), | 
|  | base::TimeDelta::FromMilliseconds(200000), | 
|  | 100, | 
|  | base::HistogramBase::kUmaTargetedHistogramFlag); | 
|  | if (counter) | 
|  | counter->AddTime(base::TimeDelta::FromMilliseconds(sample)); | 
|  | } | 
|  |  | 
|  | // Records values up to 33 minutes. | 
|  | void HistogramTimeLarge(const std::string& name, int64_t sample) { | 
|  | if (sample < 0) | 
|  | sample = 0; | 
|  | base::HistogramBase* counter = base::Histogram::FactoryTimeGet( | 
|  | name, | 
|  | base::TimeDelta::FromMilliseconds(100), | 
|  | base::TimeDelta::FromMilliseconds(2000000), | 
|  | 100, | 
|  | base::HistogramBase::kUmaTargetedHistogramFlag); | 
|  | if (counter) | 
|  | counter->AddTime(base::TimeDelta::FromMilliseconds(sample)); | 
|  | } | 
|  |  | 
|  | // Records values up to 12 minutes. | 
|  | void HistogramTimeTranslation(const std::string& name, int64_t sample_ms) { | 
|  | if (sample_ms < 0) | 
|  | sample_ms = 0; | 
|  | base::HistogramBase* counter = base::Histogram::FactoryTimeGet( | 
|  | name, | 
|  | base::TimeDelta::FromMilliseconds(10), | 
|  | base::TimeDelta::FromMilliseconds(720000), | 
|  | 100, | 
|  | base::HistogramBase::kUmaTargetedHistogramFlag); | 
|  | if (counter) | 
|  | counter->AddTime(base::TimeDelta::FromMilliseconds(sample_ms)); | 
|  | } | 
|  |  | 
|  | void HistogramStartupTimeSmall(const std::string& name, | 
|  | base::TimeDelta td, | 
|  | int64_t nexe_size) { | 
|  | HistogramTimeSmall(name, static_cast<int64_t>(td.InMilliseconds())); | 
|  | if (nexe_size > 0) { | 
|  | float size_in_MB = static_cast<float>(nexe_size) / (1024.f * 1024.f); | 
|  | HistogramTimeSmall(name + "PerMB", | 
|  | static_cast<int64_t>(td.InMilliseconds() / size_in_MB)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void HistogramStartupTimeMedium(const std::string& name, | 
|  | base::TimeDelta td, | 
|  | int64_t nexe_size) { | 
|  | HistogramTimeMedium(name, static_cast<int64_t>(td.InMilliseconds())); | 
|  | if (nexe_size > 0) { | 
|  | float size_in_MB = static_cast<float>(nexe_size) / (1024.f * 1024.f); | 
|  | HistogramTimeMedium(name + "PerMB", | 
|  | static_cast<int64_t>(td.InMilliseconds() / size_in_MB)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void HistogramSizeKB(const std::string& name, int32_t sample) { | 
|  | if (sample < 0) return; | 
|  | HistogramCustomCounts(name, | 
|  | sample, | 
|  | 1, | 
|  | 512 * 1024,  // A very large .nexe. | 
|  | 100); | 
|  | } | 
|  |  | 
|  | void HistogramHTTPStatusCode(const std::string& name, | 
|  | int32_t status) { | 
|  | // Log the status codes in rough buckets - 1XX, 2XX, etc. | 
|  | int sample = status / 100; | 
|  | // HTTP status codes only go up to 5XX, using "6" to indicate an internal | 
|  | // error. | 
|  | // Note: installed files may have "0" for a status code. | 
|  | if (status < 0 || status >= 600) | 
|  | sample = 6; | 
|  | HistogramEnumerate(name, sample, 7); | 
|  | } | 
|  |  | 
|  | void HistogramEnumerateManifestIsDataURI(bool is_data_uri) { | 
|  | HistogramEnumerate("NaCl.Manifest.IsDataURI", is_data_uri, 2); | 
|  | } | 
|  |  | 
|  | void HistogramKBPerSec(const std::string& name, int64_t kb, int64_t us) { | 
|  | if (kb < 0 || us <= 0) return; | 
|  | static const double kMaxRate = 30 * 1000.0;  // max of 30MB/sec. | 
|  | int32_t rate = std::min(kb / (us / 1000000.0), kMaxRate); | 
|  | HistogramCustomCounts(name, | 
|  | rate, | 
|  | 1, | 
|  | 30 * 1000,  // max of 30 MB/sec. | 
|  | 100); | 
|  | } | 
|  |  | 
|  | void HistogramRatio(const std::string& name, | 
|  | int64_t numerator, | 
|  | int64_t denominator) { | 
|  | static const int32_t kRatioMin = 10; | 
|  | static const int32_t kRatioMax = 10 * 100;  // max of 10x difference. | 
|  | static const uint32_t kRatioBuckets = 100; | 
|  | if (numerator < 0 || denominator <= 0) | 
|  | return; | 
|  | HistogramCustomCounts(name, | 
|  | static_cast<int32_t>(100 * numerator / denominator), | 
|  | kRatioMin, kRatioMax, kRatioBuckets); | 
|  | } | 
|  |  | 
|  | }  // namespace nacl |