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)