perf_provider_chromeos.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <string>
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/bind.h"
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/bind_helpers.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/callback.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/command_line.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/compiler_specific.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/metrics/histogram.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/rand_util.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/metrics/perf_provider_chromeos.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/browser_list_observer.h"
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/common/chrome_switches.h"
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/dbus/debug_daemon_client.h"
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Default time in seconds between invocations of perf.
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This period is roughly 6.5 hours.
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This is chosen to be relatively prime with the number of seconds in:
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// - one minute (60)
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// - one hour (3600)
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// - one day (86400)
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kPerfCommandIntervalDefaultSeconds = 23093;
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The first collection interval is different from the interval above. This is
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// because we want to collect the first profile quickly after Chrome is started.
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// If this period is too long, the user will log off and Chrome will be killed
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// before it is triggered. The following 2 variables determine the upper and
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// lower bound on the interval.
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The reason we do not always want to collect the initial profile after a fixed
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// period is to not over-represent task X in the profile where task X always
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// runs at a fixed period after start-up. By selecting a period randomly between
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// a lower and upper bound, we will hopefully collect a more fair profile.
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kPerfCommandStartIntervalLowerBoundMinutes = 10;
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kPerfCommandStartIntervalUpperBoundMinutes = 20;
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Default time in seconds perf is run for.
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kPerfCommandDurationDefaultSeconds = 2;
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Enumeration representing success and various failure modes for collecting and
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// sending perf data.
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)enum GetPerfDataOutcome {
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SUCCESS,
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  NOT_READY_TO_UPLOAD,
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  NOT_READY_TO_COLLECT,
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INCOGNITO_ACTIVE,
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INCOGNITO_LAUNCHED,
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PROTOBUF_NOT_PARSED,
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  NUM_OUTCOMES
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Name of the histogram that represents the success and various failure modes
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// for collecting and sending perf data.
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char kGetPerfDataOutcomeHistogram[] = "UMA.Perf.GetData";
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AddToPerfHistogram(GetPerfDataOutcome outcome) {
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(kGetPerfDataOutcomeHistogram,
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            outcome,
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                            NUM_OUTCOMES);
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace metrics {
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This class must be created and used on the UI thread. It watches for any
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// incognito window being opened from the time it is instantiated to the time it
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// is destroyed.
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class WindowedIncognitoObserver : public chrome::BrowserListObserver {
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public:
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WindowedIncognitoObserver() : incognito_launched_(false) {
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    BrowserList::AddObserver(this);
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual ~WindowedIncognitoObserver() {
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    BrowserList::RemoveObserver(this);
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // This method can be checked to see whether any incognito window has been
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // opened since the time this object was created.
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool incognito_launched() {
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return incognito_launched_;
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // chrome::BrowserListObserver implementation.
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (browser->profile()->IsOffTheRecord())
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      incognito_launched_ = true;
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool incognito_launched_;
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPerfProvider::PerfProvider()
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : state_(READY_TO_COLLECT),
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_factory_(this) {
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t collection_interval_minutes = base::RandInt(
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      kPerfCommandStartIntervalLowerBoundMinutes,
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      kPerfCommandStartIntervalUpperBoundMinutes);
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScheduleCollection(base::TimeDelta::FromMinutes(collection_interval_minutes));
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)PerfProvider::~PerfProvider() {}
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool PerfProvider::GetPerfData(PerfDataProto* perf_data_proto) {
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (state_ != READY_TO_UPLOAD) {
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_UPLOAD);
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *perf_data_proto = perf_data_proto_;
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  state_ = READY_TO_COLLECT;
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AddToPerfHistogram(SUCCESS);
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PerfProvider::ScheduleCollection(const base::TimeDelta& interval) {
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (timer_.IsRunning())
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  timer_.Start(FROM_HERE, interval, this,
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               &PerfProvider::CollectIfNecessaryAndReschedule);
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PerfProvider::CollectIfNecessary() {
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (state_ != READY_TO_COLLECT) {
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_COLLECT);
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // For privacy reasons, Chrome should only collect perf data if there is no
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // incognito session active (or gets spawned during the collection).
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (BrowserList::IsOffTheRecordSessionActive()) {
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AddToPerfHistogram(INCOGNITO_ACTIVE);
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<WindowedIncognitoObserver> incognito_observer(
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new WindowedIncognitoObserver);
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  chromeos::DebugDaemonClient* client =
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      kPerfCommandDurationDefaultSeconds);
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  client->GetPerfData(collection_duration.InSeconds(),
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      base::Bind(&PerfProvider::ParseProtoIfValid,
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 weak_factory_.GetWeakPtr(),
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 base::Passed(&incognito_observer)));
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PerfProvider::CollectIfNecessaryAndReschedule() {
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CollectIfNecessary();
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScheduleCollection(
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::TimeDelta::FromSeconds(kPerfCommandIntervalDefaultSeconds));
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PerfProvider::ParseProtoIfValid(
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<WindowedIncognitoObserver> incognito_observer,
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::vector<uint8>& data) {
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (incognito_observer->incognito_launched()) {
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddToPerfHistogram(INCOGNITO_LAUNCHED);
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!perf_data_proto_.ParseFromArray(data.data(), data.size())) {
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AddToPerfHistogram(PROTOBUF_NOT_PARSED);
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    perf_data_proto_.Clear();
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  state_ = READY_TO_UPLOAD;
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace metrics
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)