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

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: Created 8 years, 5 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 BrowserThread::PostBlockingPoolTaskAndReply( 79 BrowserThread::PostBlockingPoolTaskAndReply(
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, base::TimeDelta::FromMinutes(2),
103 this, &PerformanceMonitor::DoTimedCollections);
104
76 // Post a task to the background thread to a function which does nothing. 105 // 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 106 // This will force any tasks the database is performing to finish prior to
78 // the reply being sent, since they use the same thread. 107 // the reply being sent, since they use the same thread.
79 // 108 //
80 // Important! Make sure that methods in FinishInit() only rely on posting 109 // 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 110 // 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. 111 // thread; this is necessary for this notification to be valid.
83 util::PostTaskToDatabaseThreadAndReply( 112 util::PostTaskToDatabaseThreadAndReply(
84 base::Bind(&base::DoNothing), 113 base::Bind(&base::DoNothing),
85 base::Bind(&PerformanceMonitor::NotifyInitialized, 114 base::Bind(&PerformanceMonitor::NotifyInitialized,
(...skipping 11 matching lines...) Expand all
97 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE, 126 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
98 content::NotificationService::AllSources()); 127 content::NotificationService::AllSources());
99 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 128 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
100 content::NotificationService::AllSources()); 129 content::NotificationService::AllSources());
101 130
102 // Crashes 131 // Crashes
103 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG, 132 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG,
104 content::NotificationService::AllSources()); 133 content::NotificationService::AllSources());
105 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 134 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
106 content::NotificationService::AllSources()); 135 content::NotificationService::AllSources());
136
137 // Profiles (for unclean exit)
138 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
139 content::NotificationService::AllSources());
140 }
141
142 // We check if profiles exited cleanly initialization time in case they were
143 // loaded prior to PerformanceMonitor's initialization. Later profiles will be
144 // checked through the PROFILE_ADDED notification.
145 void PerformanceMonitor::CheckForUncleanExits() {
146 std::vector<Profile*> profiles =
147 g_browser_process->profile_manager()->GetLoadedProfiles();
148
149 for (std::vector<Profile*>::const_iterator iter = profiles.begin();
150 iter != profiles.end(); ++iter) {
151 if (!(*iter)->DidLastSessionExitCleanly()) {
152 BrowserThread::PostBlockingPoolSequencedTask(
153 Database::kDatabaseSequenceToken,
154 FROM_HERE,
155 base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
156 base::Unretained(this),
157 (*iter)->GetDebugName()));
158 }
159 }
160 }
161
162 void PerformanceMonitor::AddUncleanExitEvent(const std::string& profile_name) {
163 std::string database_key = kStateProfilePrefix + profile_name;
164 std::string last_active_string = database_->GetStateValue(database_key);
165
166 // Check if there was no previous time; this should only happen if the profile
167 // was last used prior to PerformanceMonitor's integration. Do nothing in this
168 // case, since the event was prior to the beginning of our recording.
169 if (last_active_string.empty())
170 return;
171
172 base::Time last_active_time;
173 CHECK(StringToTime(last_active_string, &last_active_time));
174
175 scoped_ptr<Event> event =
176 util::CreateUncleanExitEvent(last_active_time, profile_name);
177
178 database_->AddEvent(*event.get());
107 } 179 }
108 180
109 void PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread() { 181 void PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread() {
110 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 182 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
111 183
112 chrome::VersionInfo version; 184 chrome::VersionInfo version;
113 DCHECK(version.is_valid()); 185 DCHECK(version.is_valid());
114 std::string current_version = version.Version(); 186 std::string current_version = version.Version();
115 187
116 std::string previous_version = database_->GetStateValue(kStateChromeVersion); 188 std::string previous_version = database_->GetStateValue(kStateChromeVersion);
117 189
118 // We should never have a current_version which is older than the 190 // We should never have a current_version which is older than the
119 // previous_version. 191 // previous_version.
120 DCHECK(current_version >= previous_version); 192 DCHECK(current_version >= previous_version);
(...skipping 21 matching lines...) Expand all
142 base::Passed(event.Pass()))); 214 base::Passed(event.Pass())));
143 } 215 }
144 216
145 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) { 217 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) {
146 database_->AddEvent(*event.get()); 218 database_->AddEvent(*event.get());
147 } 219 }
148 220
149 void PerformanceMonitor::GetStateValueOnBackgroundThread( 221 void PerformanceMonitor::GetStateValueOnBackgroundThread(
150 const std::string& key, 222 const std::string& key,
151 const StateValueCallback& callback) { 223 const StateValueCallback& callback) {
152 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 224 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
153 std::string state_value = database_->GetStateValue(key); 225 std::string state_value = database_->GetStateValue(key);
154 226
155 BrowserThread::PostTask(BrowserThread::UI, 227 BrowserThread::PostTask(BrowserThread::UI,
156 FROM_HERE, 228 FROM_HERE,
157 base::Bind(callback, state_value)); 229 base::Bind(callback, state_value));
158 } 230 }
159 231
160 void PerformanceMonitor::NotifyInitialized() { 232 void PerformanceMonitor::NotifyInitialized() {
161 content::NotificationService::current()->Notify( 233 content::NotificationService::current()->Notify(
162 chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED, 234 chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
163 content::Source<PerformanceMonitor>(this), 235 content::Source<PerformanceMonitor>(this),
164 content::NotificationService::NoDetails()); 236 content::NotificationService::NoDetails());
165 } 237 }
166 238
239 void PerformanceMonitor::UpdateLiveProfiles() {
240 std::string time = TimeToString(base::Time::Now());
241 scoped_ptr<std::set<std::string> > active_profiles(
242 new std::set<std::string>());
243
244 for (BrowserList::const_iterator iter = BrowserList::begin();
245 iter != BrowserList::end(); ++iter) {
246 active_profiles->insert((*iter)->profile()->GetDebugName());
247 }
248
249 BrowserThread::PostBlockingPoolSequencedTask(
250 Database::kDatabaseSequenceToken,
251 FROM_HERE,
252 base::Bind(&PerformanceMonitor::UpdateLiveProfilesHelper,
253 base::Unretained(this),
254 base::Passed(active_profiles.Pass()),
255 time));
256 }
257
258 void PerformanceMonitor::UpdateLiveProfilesHelper(
259 scoped_ptr<std::set<std::string> > active_profiles,
260 std::string time) {
261 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
262
263 for (std::set<std::string>::const_iterator iter = active_profiles->begin();
264 iter != active_profiles->end(); ++iter) {
265 database_->AddStateValue(kStateProfilePrefix + *iter, time);
266 }
267 }
268
269 void PerformanceMonitor::DoTimedCollections() {
270 UpdateLiveProfiles();
271 }
272
167 void PerformanceMonitor::Observe(int type, 273 void PerformanceMonitor::Observe(int type,
168 const content::NotificationSource& source, 274 const content::NotificationSource& source,
169 const content::NotificationDetails& details) { 275 const content::NotificationDetails& details) {
170 switch (type) { 276 switch (type) {
171 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 277 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
172 const Extension* extension = content::Details<Extension>(details).ptr(); 278 const Extension* extension = content::Details<Extension>(details).ptr();
173 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(), 279 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(),
174 extension->id(), 280 extension->id(),
175 extension->name(), 281 extension->name(),
176 extension->url().spec(), 282 extension->url().spec(),
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 358
253 // Determine the type of crash. 359 // Determine the type of crash.
254 EventType type = 360 EventType type =
255 closed_details.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ? 361 closed_details.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
256 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH; 362 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH;
257 363
258 AddEvent(util::CreateCrashEvent(base::Time::Now(), 364 AddEvent(util::CreateCrashEvent(base::Time::Now(),
259 type)); 365 type));
260 break; 366 break;
261 } 367 }
368 case chrome::NOTIFICATION_PROFILE_ADDED: {
369 Profile* profile = content::Source<Profile>(source).ptr();
370 if (!profile->DidLastSessionExitCleanly()) {
371 BrowserThread::PostBlockingPoolSequencedTask(
372 Database::kDatabaseSequenceToken,
373 FROM_HERE,
374 base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
375 base::Unretained(this),
376 profile->GetDebugName()));
377 }
378 break;
379 }
262 default: { 380 default: {
263 NOTREACHED(); 381 NOTREACHED();
264 break; 382 break;
265 } 383 }
266 } 384 }
267 } 385 }
268 386
269 } // namespace performance_monitor 387 } // namespace performance_monitor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698