15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/external_metrics.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/files/file_path.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/field_trial.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/metrics/sparse_histogram.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/statistics_recorder.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/timer/elapsed_timer.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/chromeos_metrics_provider.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/metrics_service.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/metrics/serialization/metric_sample.h"
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/metrics/serialization/serialization_utils.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckValues(const std::string& name,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 int minimum,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 int maximum,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t bucket_count) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::Histogram::InspectConstructionArguments(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name, &minimum, &maximum, &bucket_count))
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::HistogramBase* histogram =
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StatisticsRecorder::FindHistogram(name);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!histogram)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return histogram->HasConstructionArguments(minimum, maximum, bucket_count);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckLinearValues(const std::string& name, int maximum) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CheckValues(name, 1, maximum, maximum + 1);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Establishes field trial for wifi scanning in chromeos.  crbug.com/242733.
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SetupProgressiveScanFieldTrial() {
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char name_of_experiment[] = "ProgressiveScan";
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const base::FilePath group_file_path(
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      "/home/chronos/.progressive_scan_variation");
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const base::FieldTrial::Probability kDivisor = 1000;
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<base::FieldTrial> trial =
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      base::FieldTrialList::FactoryGetFieldTrial(
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          name_of_experiment, kDivisor, "Default", 2013, 12, 31,
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          base::FieldTrial::SESSION_RANDOMIZED, NULL);
62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Announce the groups with 0 percentage; the actual percentages come from
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the server configuration.
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::map<int, std::string> group_to_char;
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  group_to_char[trial->AppendGroup("FullScan", 0)] = "c";
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  group_to_char[trial->AppendGroup("33Percent_4MinMax", 0)] = "1";
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  group_to_char[trial->AppendGroup("50Percent_4MinMax", 0)] = "2";
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  group_to_char[trial->AppendGroup("50Percent_8MinMax", 0)] = "3";
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  group_to_char[trial->AppendGroup("100Percent_8MinMax", 0)] = "4";
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  group_to_char[trial->AppendGroup("100Percent_1MinSeen_A", 0)] = "5";
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  group_to_char[trial->AppendGroup("100Percent_1MinSeen_B", 0)] = "6";
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  group_to_char[trial->AppendGroup("100Percent_1Min_4Max", 0)] = "7";
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Announce the experiment to any listeners (especially important is the UMA
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // software, which will append the group names to UMA statistics).
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int group_num = trial->group();
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string group_char = "x";
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (ContainsKey(group_to_char, group_num))
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    group_char = group_to_char[group_num];
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Write the group to the file to be read by ChromeOS.
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int size = static_cast<int>(group_char.length());
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (base::WriteFile(group_file_path, group_char.c_str(), size) == size) {
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VLOG(1) << "Configured in group '" << trial->group_name()
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << "' ('" << group_char << "') for "
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << name_of_experiment << " field trial";
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VLOG(1) << "Couldn't write to " << group_file_path.value();
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The interval between external metrics collections in seconds
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kExternalMetricsCollectionIntervalSeconds = 30;
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kEventsFilePath[] = "/var/run/metrics/uma-events";
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ExternalMetrics::ExternalMetrics() : uma_events_file_(kEventsFilePath) {
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExternalMetrics::~ExternalMetrics() {}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalMetrics::Start() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register user actions external to the browser.
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // tools/metrics/actions/extract_actions.py won't understand these lines, so
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // all of these are explicitly added in that script.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(derat): We shouldn't need to verify actions before reporting them;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // remove all of this once http://crosbug.com/11125 is fixed.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_user_actions_.insert("Cryptohome.PKCS11InitFail");
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_user_actions_.insert("Updater.ServerCertificateChanged");
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_user_actions_.insert("Updater.ServerCertificateFailed");
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Initialize here field trials that don't need to read from files.
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // (None for the moment.)
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Initialize any chromeos field trials that need to read from a file (e.g.,
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // those that have an upstart script determine their experimental group for
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // them) then schedule the data collection.  All of this is done on the file
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // thread.
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool task_posted = BrowserThread::PostTask(
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      BrowserThread::FILE,
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FROM_HERE,
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&chromeos::ExternalMetrics::SetupFieldTrialsOnFileThread,
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 this));
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(task_posted);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_refptr<ExternalMetrics> ExternalMetrics::CreateForTesting(
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& filename) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<ExternalMetrics> external_metrics(new ExternalMetrics());
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  external_metrics->uma_events_file_ = filename;
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return external_metrics;
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalMetrics::RecordActionUI(std::string action_string) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (valid_user_actions_.count(action_string)) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RecordComputedAction(action_string);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DLOG(ERROR) << "undefined UMA action: " << action_string;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExternalMetrics::RecordAction(const std::string& action) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      BrowserThread::UI,
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&ExternalMetrics::RecordActionUI, this, action));
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalMetrics::RecordCrashUI(const std::string& crash_kind) {
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ChromeOSMetricsProvider::LogCrash(crash_kind);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalMetrics::RecordCrash(const std::string& crash_kind) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ExternalMetrics::RecordCrashUI, this, crash_kind));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExternalMetrics::RecordHistogram(const metrics::MetricSample& sample) {
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_EQ(metrics::MetricSample::HISTOGRAM, sample.type());
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!CheckValues(
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          sample.name(), sample.min(), sample.max(), sample.bucket_count())) {
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DLOG(ERROR) << "Invalid histogram: " << sample.name();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::HistogramBase* counter =
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Histogram::FactoryGet(sample.name(),
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  sample.min(),
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  sample.max(),
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  sample.bucket_count(),
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  base::Histogram::kUmaTargetedHistogramFlag);
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  counter->Add(sample.sample());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExternalMetrics::RecordLinearHistogram(
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const metrics::MetricSample& sample) {
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_EQ(metrics::MetricSample::LINEAR_HISTOGRAM, sample.type());
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!CheckLinearValues(sample.name(), sample.max())) {
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DLOG(ERROR) << "Invalid linear histogram: " << sample.name();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sample.name(),
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      1,
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sample.max(),
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sample.max() + 1,
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  counter->Add(sample.sample());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExternalMetrics::RecordSparseHistogram(
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const metrics::MetricSample& sample) {
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_EQ(metrics::MetricSample::SPARSE_HISTOGRAM, sample.type());
198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::HistogramBase* counter = base::SparseHistogram::FactoryGet(
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sample.name(), base::HistogramBase::kUmaTargetedHistogramFlag);
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  counter->Add(sample.sample());
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int ExternalMetrics::CollectEvents() {
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedVector<metrics::MetricSample> samples;
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics::SerializationUtils::ReadAndTruncateMetricsFromFile(uma_events_file_,
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                              &samples);
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (ScopedVector<metrics::MetricSample>::iterator it = samples.begin();
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != samples.end();
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++it) {
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const metrics::MetricSample& sample = **it;
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Do not use the UMA_HISTOGRAM_... macros here.  They cache the Histogram
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // instance and thus only work if |sample.name()| is constant.
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switch (sample.type()) {
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case metrics::MetricSample::CRASH:
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        RecordCrash(sample.name());
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case metrics::MetricSample::USER_ACTION:
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        RecordAction(sample.name());
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case metrics::MetricSample::HISTOGRAM:
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        RecordHistogram(sample);
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case metrics::MetricSample::LINEAR_HISTOGRAM:
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        RecordLinearHistogram(sample);
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case metrics::MetricSample::SPARSE_HISTOGRAM:
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        RecordSparseHistogram(sample);
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return samples.size();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalMetrics::CollectEventsAndReschedule() {
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::ElapsedTimer timer;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CollectEvents();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("UMA.CollectExternalEventsTime", timer.Elapsed());
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCollector();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalMetrics::ScheduleCollector() {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = BrowserThread::PostDelayedTask(
247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&chromeos::ExternalMetrics::CollectEventsAndReschedule, this),
249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::TimeDelta::FromSeconds(kExternalMetricsCollectionIntervalSeconds));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExternalMetrics::SetupFieldTrialsOnFileThread() {
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Field trials that do not read from files can be initialized in
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // ExternalMetrics::Start() above.
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SetupProgressiveScanFieldTrial();
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScheduleCollector();
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
263