| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/metrics/perf_provider_chromeos.h" |
| 6 |
| 5 #include <string> | 7 #include <string> |
| 6 | 8 |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "base/callback.h" | 10 #include "base/callback.h" |
| 10 #include "base/command_line.h" | |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | |
| 15 #include "base/threading/sequenced_worker_pool.h" | 14 #include "base/threading/sequenced_worker_pool.h" |
| 16 #include "chrome/browser/chrome_notification_types.h" | 15 #include "chrome/browser/metrics/windowed_incognito_observer.h" |
| 17 #include "chrome/browser/metrics/perf_provider_chromeos.h" | |
| 18 #include "chrome/browser/profiles/profile.h" | |
| 19 #include "chrome/browser/ui/browser.h" | |
| 20 #include "chrome/browser/ui/browser_list.h" | 16 #include "chrome/browser/ui/browser_list.h" |
| 21 #include "chrome/browser/ui/browser_list_observer.h" | |
| 22 #include "chrome/common/chrome_switches.h" | |
| 23 #include "chromeos/dbus/dbus_thread_manager.h" | 17 #include "chromeos/dbus/dbus_thread_manager.h" |
| 24 #include "chromeos/dbus/debug_daemon_client.h" | 18 #include "chromeos/dbus/debug_daemon_client.h" |
| 25 #include "content/public/browser/notification_service.h" | |
| 26 | 19 |
| 27 namespace { | 20 namespace { |
| 28 | 21 |
| 29 // Partition time since login into successive intervals of this size. In each | 22 // Partition time since login into successive intervals of this size. In each |
| 30 // interval, pick a random time to collect a profile. | 23 // interval, pick a random time to collect a profile. |
| 31 const size_t kPerfProfilingIntervalMs = 3 * 60 * 60 * 1000; | 24 const size_t kPerfProfilingIntervalMs = 3 * 60 * 60 * 1000; |
| 32 | 25 |
| 33 // Default time in seconds perf is run for. | 26 // Default time in seconds perf is run for. |
| 34 const size_t kPerfCommandDurationDefaultSeconds = 2; | 27 const size_t kPerfCommandDurationDefaultSeconds = 2; |
| 35 | 28 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 65 | 58 |
| 66 // Enumeration representing success and various failure modes for collecting and | 59 // Enumeration representing success and various failure modes for collecting and |
| 67 // sending perf data. | 60 // sending perf data. |
| 68 enum GetPerfDataOutcome { | 61 enum GetPerfDataOutcome { |
| 69 SUCCESS, | 62 SUCCESS, |
| 70 NOT_READY_TO_UPLOAD, | 63 NOT_READY_TO_UPLOAD, |
| 71 NOT_READY_TO_COLLECT, | 64 NOT_READY_TO_COLLECT, |
| 72 INCOGNITO_ACTIVE, | 65 INCOGNITO_ACTIVE, |
| 73 INCOGNITO_LAUNCHED, | 66 INCOGNITO_LAUNCHED, |
| 74 PROTOBUF_NOT_PARSED, | 67 PROTOBUF_NOT_PARSED, |
| 68 ILLEGAL_DATA_RETURNED, |
| 75 NUM_OUTCOMES | 69 NUM_OUTCOMES |
| 76 }; | 70 }; |
| 77 | 71 |
| 78 // Name of the histogram that represents the success and various failure modes | 72 // Name of the histogram that represents the success and various failure modes |
| 79 // for collecting and sending perf data. | 73 // for collecting and sending perf data. |
| 80 const char kGetPerfDataOutcomeHistogram[] = "UMA.Perf.GetData"; | 74 const char kGetPerfDataOutcomeHistogram[] = "UMA.Perf.GetData"; |
| 81 | 75 |
| 82 void AddToPerfHistogram(GetPerfDataOutcome outcome) { | 76 void AddToPerfHistogram(GetPerfDataOutcome outcome) { |
| 83 UMA_HISTOGRAM_ENUMERATION(kGetPerfDataOutcomeHistogram, | 77 UMA_HISTOGRAM_ENUMERATION(kGetPerfDataOutcomeHistogram, |
| 84 outcome, | 78 outcome, |
| 85 NUM_OUTCOMES); | 79 NUM_OUTCOMES); |
| 86 } | 80 } |
| 87 | 81 |
| 88 // Returns true if a normal user is logged in. Returns false otherwise (e.g. if | 82 // Returns true if a normal user is logged in. Returns false otherwise (e.g. if |
| 89 // logged in as a guest or as a kiosk app). | 83 // logged in as a guest or as a kiosk app). |
| 90 bool IsNormalUserLoggedIn() { | 84 bool IsNormalUserLoggedIn() { |
| 91 return chromeos::LoginState::Get()->IsUserAuthenticated(); | 85 return chromeos::LoginState::Get()->IsUserAuthenticated(); |
| 92 } | 86 } |
| 93 | 87 |
| 94 } // namespace | 88 } // namespace |
| 95 | 89 |
| 96 | |
| 97 namespace metrics { | 90 namespace metrics { |
| 98 | 91 |
| 99 // This class must be created and used on the UI thread. It watches for any | |
| 100 // incognito window being opened from the time it is instantiated to the time it | |
| 101 // is destroyed. | |
| 102 class WindowedIncognitoObserver : public chrome::BrowserListObserver { | |
| 103 public: | |
| 104 WindowedIncognitoObserver() : incognito_launched_(false) { | |
| 105 BrowserList::AddObserver(this); | |
| 106 } | |
| 107 | |
| 108 ~WindowedIncognitoObserver() override { BrowserList::RemoveObserver(this); } | |
| 109 | |
| 110 // This method can be checked to see whether any incognito window has been | |
| 111 // opened since the time this object was created. | |
| 112 bool incognito_launched() { | |
| 113 return incognito_launched_; | |
| 114 } | |
| 115 | |
| 116 private: | |
| 117 // chrome::BrowserListObserver implementation. | |
| 118 void OnBrowserAdded(Browser* browser) override { | |
| 119 if (browser->profile()->IsOffTheRecord()) | |
| 120 incognito_launched_ = true; | |
| 121 } | |
| 122 | |
| 123 bool incognito_launched_; | |
| 124 }; | |
| 125 | |
| 126 PerfProvider::PerfProvider() | 92 PerfProvider::PerfProvider() |
| 127 : login_observer_(this), | 93 : login_observer_(this), |
| 128 next_profiling_interval_start_(base::TimeTicks::Now()), | 94 next_profiling_interval_start_(base::TimeTicks::Now()), |
| 129 weak_factory_(this) { | 95 weak_factory_(this) { |
| 130 // Register the login observer with LoginState. | 96 // Register the login observer with LoginState. |
| 131 chromeos::LoginState::Get()->AddObserver(&login_observer_); | 97 chromeos::LoginState::Get()->AddObserver(&login_observer_); |
| 132 | 98 |
| 133 // Register as an observer of power manager events. | 99 // Register as an observer of power manager events. |
| 134 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> | 100 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> |
| 135 AddObserver(this); | 101 AddObserver(this); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 160 return false; | 126 return false; |
| 161 } | 127 } |
| 162 | 128 |
| 163 sampled_profiles->swap(cached_perf_data_); | 129 sampled_profiles->swap(cached_perf_data_); |
| 164 cached_perf_data_.clear(); | 130 cached_perf_data_.clear(); |
| 165 | 131 |
| 166 AddToPerfHistogram(SUCCESS); | 132 AddToPerfHistogram(SUCCESS); |
| 167 return true; | 133 return true; |
| 168 } | 134 } |
| 169 | 135 |
| 136 void PerfProvider::ParseOutputProtoIfValid( |
| 137 scoped_ptr<WindowedIncognitoObserver> incognito_observer, |
| 138 scoped_ptr<SampledProfile> sampled_profile, |
| 139 int result, |
| 140 const std::vector<uint8>& perf_data, |
| 141 const std::vector<uint8>& perf_stat) { |
| 142 DCHECK(CalledOnValidThread()); |
| 143 |
| 144 if (incognito_observer->incognito_launched()) { |
| 145 AddToPerfHistogram(INCOGNITO_LAUNCHED); |
| 146 return; |
| 147 } |
| 148 |
| 149 if (result != 0 || (perf_data.empty() && perf_stat.empty())) { |
| 150 AddToPerfHistogram(PROTOBUF_NOT_PARSED); |
| 151 return; |
| 152 } |
| 153 |
| 154 if (!perf_data.empty() && !perf_stat.empty()) { |
| 155 AddToPerfHistogram(ILLEGAL_DATA_RETURNED); |
| 156 return; |
| 157 } |
| 158 |
| 159 if (!perf_data.empty()) { |
| 160 PerfDataProto perf_data_proto; |
| 161 if (!perf_data_proto.ParseFromArray(perf_data.data(), perf_data.size())) { |
| 162 AddToPerfHistogram(PROTOBUF_NOT_PARSED); |
| 163 return; |
| 164 } |
| 165 sampled_profile->set_ms_after_boot( |
| 166 perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond); |
| 167 sampled_profile->mutable_perf_data()->Swap(&perf_data_proto); |
| 168 } else { |
| 169 DCHECK(!perf_stat.empty()); |
| 170 PerfStatProto perf_stat_proto; |
| 171 if (!perf_stat_proto.ParseFromArray(perf_stat.data(), perf_stat.size())) { |
| 172 AddToPerfHistogram(PROTOBUF_NOT_PARSED); |
| 173 return; |
| 174 } |
| 175 sampled_profile->mutable_perf_stat()->Swap(&perf_stat_proto); |
| 176 } |
| 177 |
| 178 DCHECK(!login_time_.is_null()); |
| 179 sampled_profile->set_ms_after_login( |
| 180 (base::TimeTicks::Now() - login_time_).InMilliseconds()); |
| 181 |
| 182 // Add the collected data to the container of collected SampledProfiles. |
| 183 cached_perf_data_.resize(cached_perf_data_.size() + 1); |
| 184 cached_perf_data_.back().Swap(sampled_profile.get()); |
| 185 } |
| 186 |
| 170 PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider) | 187 PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider) |
| 171 : perf_provider_(perf_provider) {} | 188 : perf_provider_(perf_provider) {} |
| 172 | 189 |
| 173 void PerfProvider::LoginObserver::LoggedInStateChanged() { | 190 void PerfProvider::LoginObserver::LoggedInStateChanged() { |
| 174 if (IsNormalUserLoggedIn()) | 191 if (IsNormalUserLoggedIn()) |
| 175 perf_provider_->OnUserLoggedIn(); | 192 perf_provider_->OnUserLoggedIn(); |
| 176 else | 193 else |
| 177 perf_provider_->Deactivate(); | 194 perf_provider_->Deactivate(); |
| 178 } | 195 } |
| 179 | 196 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 331 |
| 315 scoped_ptr<WindowedIncognitoObserver> incognito_observer( | 332 scoped_ptr<WindowedIncognitoObserver> incognito_observer( |
| 316 new WindowedIncognitoObserver); | 333 new WindowedIncognitoObserver); |
| 317 | 334 |
| 318 chromeos::DebugDaemonClient* client = | 335 chromeos::DebugDaemonClient* client = |
| 319 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); | 336 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); |
| 320 | 337 |
| 321 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds( | 338 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds( |
| 322 kPerfCommandDurationDefaultSeconds); | 339 kPerfCommandDurationDefaultSeconds); |
| 323 | 340 |
| 324 client->GetPerfData(collection_duration.InSeconds(), | 341 client->GetPerfOutput( |
| 325 base::Bind(&PerfProvider::ParseProtoIfValid, | 342 collection_duration.InSeconds(), |
| 326 weak_factory_.GetWeakPtr(), | 343 base::Bind(&PerfProvider::ParseOutputProtoIfValid, |
| 327 base::Passed(&incognito_observer), | 344 weak_factory_.GetWeakPtr(), base::Passed(&incognito_observer), |
| 328 base::Passed(&sampled_profile))); | 345 base::Passed(&sampled_profile))); |
| 329 } | 346 } |
| 330 | 347 |
| 331 void PerfProvider::DoPeriodicCollection() { | 348 void PerfProvider::DoPeriodicCollection() { |
| 332 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); | 349 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); |
| 333 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); | 350 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); |
| 334 | 351 |
| 335 CollectIfNecessary(sampled_profile.Pass()); | 352 CollectIfNecessary(sampled_profile.Pass()); |
| 336 } | 353 } |
| 337 | 354 |
| 338 void PerfProvider::CollectPerfDataAfterResume( | 355 void PerfProvider::CollectPerfDataAfterResume( |
| (...skipping 14 matching lines...) Expand all Loading... |
| 353 // Fill out a SampledProfile protobuf that will contain the collected data. | 370 // Fill out a SampledProfile protobuf that will contain the collected data. |
| 354 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); | 371 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); |
| 355 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); | 372 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); |
| 356 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds()); | 373 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds()); |
| 357 sampled_profile->set_num_tabs_restored(num_tabs_restored); | 374 sampled_profile->set_num_tabs_restored(num_tabs_restored); |
| 358 | 375 |
| 359 CollectIfNecessary(sampled_profile.Pass()); | 376 CollectIfNecessary(sampled_profile.Pass()); |
| 360 last_session_restore_collection_time_ = base::TimeTicks::Now(); | 377 last_session_restore_collection_time_ = base::TimeTicks::Now(); |
| 361 } | 378 } |
| 362 | 379 |
| 363 void PerfProvider::ParseProtoIfValid( | |
| 364 scoped_ptr<WindowedIncognitoObserver> incognito_observer, | |
| 365 scoped_ptr<SampledProfile> sampled_profile, | |
| 366 const std::vector<uint8>& data) { | |
| 367 DCHECK(CalledOnValidThread()); | |
| 368 | |
| 369 if (incognito_observer->incognito_launched()) { | |
| 370 AddToPerfHistogram(INCOGNITO_LAUNCHED); | |
| 371 return; | |
| 372 } | |
| 373 | |
| 374 PerfDataProto perf_data_proto; | |
| 375 if (!perf_data_proto.ParseFromArray(data.data(), data.size())) { | |
| 376 AddToPerfHistogram(PROTOBUF_NOT_PARSED); | |
| 377 return; | |
| 378 } | |
| 379 | |
| 380 // Populate a profile collection protobuf with the collected perf data and | |
| 381 // extra metadata. | |
| 382 cached_perf_data_.resize(cached_perf_data_.size() + 1); | |
| 383 SampledProfile& collection_data = cached_perf_data_.back(); | |
| 384 collection_data.Swap(sampled_profile.get()); | |
| 385 | |
| 386 // Fill out remaining fields of the SampledProfile protobuf. | |
| 387 collection_data.set_ms_after_boot( | |
| 388 perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond); | |
| 389 | |
| 390 DCHECK(!login_time_.is_null()); | |
| 391 collection_data. | |
| 392 set_ms_after_login((base::TimeTicks::Now() - login_time_) | |
| 393 .InMilliseconds()); | |
| 394 | |
| 395 // Finally, store the perf data itself. | |
| 396 collection_data.mutable_perf_data()->Swap(&perf_data_proto); | |
| 397 } | |
| 398 | |
| 399 } // namespace metrics | 380 } // namespace metrics |
| OLD | NEW |