Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(489)

Side by Side Diff: chrome/browser/performance_monitor/performance_monitor.cc

Issue 10815079: CPM: revised unclean exit watching, revised renderer crash test (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Latest master (with OWNERS) for cq Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/performance_monitor/performance_monitor.h" 5 #include "chrome/browser/performance_monitor/performance_monitor.h"
6 6
7 #include <set>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/logging.h" 10 #include "base/logging.h"
9 #include "base/process_util.h" 11 #include "base/process_util.h"
12 #include "base/string_number_conversions.h"
10 #include "base/threading/worker_pool.h" 13 #include "base/threading/worker_pool.h"
11 #include "base/time.h" 14 #include "base/time.h"
15 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/browser_shutdown.h" 16 #include "chrome/browser/browser_shutdown.h"
17 #include "chrome/browser/extensions/crx_installer.h"
13 #include "chrome/browser/performance_monitor/constants.h" 18 #include "chrome/browser/performance_monitor/constants.h"
14 #include "chrome/browser/performance_monitor/database.h" 19 #include "chrome/browser/performance_monitor/database.h"
15 #include "chrome/browser/performance_monitor/performance_monitor_util.h" 20 #include "chrome/browser/performance_monitor/performance_monitor_util.h"
16 #include "chrome/browser/extensions/crx_installer.h" 21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_list.h"
17 #include "chrome/common/chrome_notification_types.h" 25 #include "chrome/common/chrome_notification_types.h"
18 #include "chrome/common/chrome_version_info.h" 26 #include "chrome/common/chrome_version_info.h"
19 #include "chrome/common/extensions/extension.h" 27 #include "chrome/common/extensions/extension.h"
20 #include "chrome/common/extensions/extension_constants.h" 28 #include "chrome/common/extensions/extension_constants.h"
21 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_types.h" 31 #include "content/public/browser/notification_types.h"
24 #include "content/public/browser/render_process_host.h" 32 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents.h"
26 34
27 using content::BrowserThread; 35 using content::BrowserThread;
28 using extensions::Extension; 36 using extensions::Extension;
29 37
38 namespace {
39
40 std::string TimeToString(base::Time time) {
41 int64 time_int64 = time.ToInternalValue();
42 return base::Int64ToString(time_int64);
43 }
44
45 bool StringToTime(std::string time, base::Time* output) {
46 int64 time_int64 = 0;
47 if (!base::StringToInt64(time, &time_int64))
48 return false;
49 *output = base::Time::FromInternalValue(time_int64);
50 return true;
51 }
52
53 } // namespace
54
30 namespace performance_monitor { 55 namespace performance_monitor {
31 56
32 PerformanceMonitor::PerformanceMonitor() : database_(NULL) { 57 PerformanceMonitor::PerformanceMonitor() : database_(NULL) {
33 } 58 }
34 59
35 PerformanceMonitor::~PerformanceMonitor() { 60 PerformanceMonitor::~PerformanceMonitor() {
36 } 61 }
37 62
38 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) { 63 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) {
39 if (!database_.get()) { 64 if (!database_.get()) {
(...skipping 13 matching lines...) Expand all
53 void PerformanceMonitor::Start() { 78 void PerformanceMonitor::Start() {
54 util::PostTaskToDatabaseThreadAndReply( 79 util::PostTaskToDatabaseThreadAndReply(
55 FROM_HERE, 80 FROM_HERE,
56 base::Bind(&PerformanceMonitor::InitOnBackgroundThread, 81 base::Bind(&PerformanceMonitor::InitOnBackgroundThread,
57 base::Unretained(this)), 82 base::Unretained(this)),
58 base::Bind(&PerformanceMonitor::FinishInit, 83 base::Bind(&PerformanceMonitor::FinishInit,
59 base::Unretained(this))); 84 base::Unretained(this)));
60 } 85 }
61 86
62 void PerformanceMonitor::InitOnBackgroundThread() { 87 void PerformanceMonitor::InitOnBackgroundThread() {
63 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 88 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
64 database_ = Database::Create(database_path_); 89 database_ = Database::Create(database_path_);
65 } 90 }
66 91
67 void PerformanceMonitor::FinishInit() { 92 void PerformanceMonitor::FinishInit() {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 93 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
69 RegisterForNotifications(); 94 RegisterForNotifications();
95 CheckForUncleanExits();
70 BrowserThread::PostBlockingPoolSequencedTask( 96 BrowserThread::PostBlockingPoolSequencedTask(
71 Database::kDatabaseSequenceToken, 97 Database::kDatabaseSequenceToken,
72 FROM_HERE, 98 FROM_HERE,
73 base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread, 99 base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread,
74 base::Unretained(this))); 100 base::Unretained(this)));
75 101
102 timer_.Start(FROM_HERE,
103 base::TimeDelta::FromMinutes(kGatherIntervalInMinutes),
104 this,
105 &PerformanceMonitor::DoTimedCollections);
106
76 // Post a task to the background thread to a function which does nothing. 107 // Post a task to the background thread to a function which does nothing.
77 // This will force any tasks the database is performing to finish prior to 108 // This will force any tasks the database is performing to finish prior to
78 // the reply being sent, since they use the same thread. 109 // the reply being sent, since they use the same thread.
79 // 110 //
80 // Important! Make sure that methods in FinishInit() only rely on posting 111 // Important! Make sure that methods in FinishInit() only rely on posting
81 // to the background thread, and do not rely upon a reply from the background 112 // to the background thread, and do not rely upon a reply from the background
82 // thread; this is necessary for this notification to be valid. 113 // thread; this is necessary for this notification to be valid.
83 util::PostTaskToDatabaseThreadAndReply( 114 util::PostTaskToDatabaseThreadAndReply(
84 FROM_HERE, 115 FROM_HERE,
85 base::Bind(&base::DoNothing), 116 base::Bind(&base::DoNothing),
(...skipping 12 matching lines...) Expand all
98 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE, 129 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
99 content::NotificationService::AllSources()); 130 content::NotificationService::AllSources());
100 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 131 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
101 content::NotificationService::AllSources()); 132 content::NotificationService::AllSources());
102 133
103 // Crashes 134 // Crashes
104 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG, 135 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG,
105 content::NotificationService::AllSources()); 136 content::NotificationService::AllSources());
106 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 137 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
107 content::NotificationService::AllSources()); 138 content::NotificationService::AllSources());
139
140 // Profiles (for unclean exit)
141 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
142 content::NotificationService::AllSources());
143 }
144
145 // We check if profiles exited cleanly initialization time in case they were
146 // loaded prior to PerformanceMonitor's initialization. Later profiles will be
147 // checked through the PROFILE_ADDED notification.
148 void PerformanceMonitor::CheckForUncleanExits() {
149 std::vector<Profile*> profiles =
150 g_browser_process->profile_manager()->GetLoadedProfiles();
151
152 for (std::vector<Profile*>::const_iterator iter = profiles.begin();
153 iter != profiles.end(); ++iter) {
154 if (!(*iter)->DidLastSessionExitCleanly()) {
155 BrowserThread::PostBlockingPoolSequencedTask(
156 Database::kDatabaseSequenceToken,
157 FROM_HERE,
158 base::Bind(&PerformanceMonitor::AddUncleanExitEventOnBackgroundThread,
159 base::Unretained(this),
160 (*iter)->GetDebugName()));
161 }
162 }
163 }
164
165 void PerformanceMonitor::AddUncleanExitEventOnBackgroundThread(
166 const std::string& profile_name) {
167 std::string database_key = kStateProfilePrefix + profile_name;
168 std::string last_active_string = database_->GetStateValue(database_key);
169
170 // Check if there was no previous time; this should only happen if the profile
171 // was last used prior to PerformanceMonitor's integration. Do nothing in this
172 // case, since the event was prior to the beginning of our recording.
173 if (last_active_string.empty())
174 return;
175
176 base::Time last_active_time;
177 CHECK(StringToTime(last_active_string, &last_active_time));
178
179 scoped_ptr<Event> event =
180 util::CreateUncleanExitEvent(last_active_time, profile_name);
181
182 database_->AddEvent(*event.get());
108 } 183 }
109 184
110 void PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread() { 185 void PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread() {
111 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 186 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
112 187
113 chrome::VersionInfo version; 188 chrome::VersionInfo version;
114 DCHECK(version.is_valid()); 189 DCHECK(version.is_valid());
115 std::string current_version = version.Version(); 190 std::string current_version = version.Version();
116 191
117 std::string previous_version = database_->GetStateValue(kStateChromeVersion); 192 std::string previous_version = database_->GetStateValue(kStateChromeVersion);
118 193
119 // We should never have a current_version which is older than the 194 // We should never have a current_version which is older than the
120 // previous_version. 195 // previous_version.
121 DCHECK(current_version >= previous_version); 196 DCHECK(current_version >= previous_version);
(...skipping 21 matching lines...) Expand all
143 base::Passed(event.Pass()))); 218 base::Passed(event.Pass())));
144 } 219 }
145 220
146 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) { 221 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) {
147 database_->AddEvent(*event.get()); 222 database_->AddEvent(*event.get());
148 } 223 }
149 224
150 void PerformanceMonitor::GetStateValueOnBackgroundThread( 225 void PerformanceMonitor::GetStateValueOnBackgroundThread(
151 const std::string& key, 226 const std::string& key,
152 const StateValueCallback& callback) { 227 const StateValueCallback& callback) {
153 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 228 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
154 std::string state_value = database_->GetStateValue(key); 229 std::string state_value = database_->GetStateValue(key);
155 230
156 BrowserThread::PostTask(BrowserThread::UI, 231 BrowserThread::PostTask(BrowserThread::UI,
157 FROM_HERE, 232 FROM_HERE,
158 base::Bind(callback, state_value)); 233 base::Bind(callback, state_value));
159 } 234 }
160 235
161 void PerformanceMonitor::NotifyInitialized() { 236 void PerformanceMonitor::NotifyInitialized() {
162 content::NotificationService::current()->Notify( 237 content::NotificationService::current()->Notify(
163 chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED, 238 chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
164 content::Source<PerformanceMonitor>(this), 239 content::Source<PerformanceMonitor>(this),
165 content::NotificationService::NoDetails()); 240 content::NotificationService::NoDetails());
166 } 241 }
167 242
243 void PerformanceMonitor::UpdateLiveProfiles() {
244 std::string time = TimeToString(base::Time::Now());
245 scoped_ptr<std::set<std::string> > active_profiles(
246 new std::set<std::string>());
247
248 for (BrowserList::const_iterator iter = BrowserList::begin();
249 iter != BrowserList::end(); ++iter) {
250 active_profiles->insert((*iter)->profile()->GetDebugName());
251 }
252
253 BrowserThread::PostBlockingPoolSequencedTask(
254 Database::kDatabaseSequenceToken,
255 FROM_HERE,
256 base::Bind(&PerformanceMonitor::UpdateLiveProfilesHelper,
257 base::Unretained(this),
258 base::Passed(active_profiles.Pass()),
259 time));
260 }
261
262 void PerformanceMonitor::UpdateLiveProfilesHelper(
263 scoped_ptr<std::set<std::string> > active_profiles,
264 std::string time) {
265 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
266
267 for (std::set<std::string>::const_iterator iter = active_profiles->begin();
268 iter != active_profiles->end(); ++iter) {
269 database_->AddStateValue(kStateProfilePrefix + *iter, time);
270 }
271 }
272
273 void PerformanceMonitor::DoTimedCollections() {
274 UpdateLiveProfiles();
275 }
276
168 void PerformanceMonitor::Observe(int type, 277 void PerformanceMonitor::Observe(int type,
169 const content::NotificationSource& source, 278 const content::NotificationSource& source,
170 const content::NotificationDetails& details) { 279 const content::NotificationDetails& details) {
171 switch (type) { 280 switch (type) {
172 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 281 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
173 const Extension* extension = content::Details<Extension>(details).ptr(); 282 const Extension* extension = content::Details<Extension>(details).ptr();
174 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(), 283 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(),
175 extension->id(), 284 extension->id(),
176 extension->name(), 285 extension->name(),
177 extension->url().spec(), 286 extension->url().spec(),
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 362
254 // Determine the type of crash. 363 // Determine the type of crash.
255 EventType type = 364 EventType type =
256 closed_details.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ? 365 closed_details.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
257 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH; 366 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH;
258 367
259 AddEvent(util::CreateCrashEvent(base::Time::Now(), 368 AddEvent(util::CreateCrashEvent(base::Time::Now(),
260 type)); 369 type));
261 break; 370 break;
262 } 371 }
372 case chrome::NOTIFICATION_PROFILE_ADDED: {
373 Profile* profile = content::Source<Profile>(source).ptr();
374 if (!profile->DidLastSessionExitCleanly()) {
375 BrowserThread::PostBlockingPoolSequencedTask(
376 Database::kDatabaseSequenceToken,
377 FROM_HERE,
378 base::Bind(
379 &PerformanceMonitor::AddUncleanExitEventOnBackgroundThread,
380 base::Unretained(this),
381 profile->GetDebugName()));
382 }
383 break;
384 }
263 default: { 385 default: {
264 NOTREACHED(); 386 NOTREACHED();
265 break; 387 break;
266 } 388 }
267 } 389 }
268 } 390 }
269 391
270 } // namespace performance_monitor 392 } // namespace performance_monitor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698