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

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

Issue 10703078: Add Unclean Exit Watching to CPM (Closed) Base URL: http://git.chromium.org/chromium/src.git@dc_crash_event_watching
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"
13 #include "chrome/browser/performance_monitor/constants.h" 17 #include "chrome/browser/performance_monitor/constants.h"
14 #include "chrome/browser/performance_monitor/database.h" 18 #include "chrome/browser/performance_monitor/database.h"
15 #include "chrome/browser/performance_monitor/performance_monitor_util.h" 19 #include "chrome/browser/performance_monitor/performance_monitor_util.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/browser_list.h"
16 #include "chrome/browser/extensions/crx_installer.h" 24 #include "chrome/browser/extensions/crx_installer.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/web_contents.h" 32 #include "content/public/browser/web_contents.h"
25 33
26 using extensions::Extension; 34 using extensions::Extension;
27 35
36 namespace {
37
38 bool TimeToString(base::Time time, std::string* output) {
Yoyo Zhou 2012/07/10 02:35:06 It doesn't make sense that conversion in this dire
Devlin 2012/07/10 17:18:32 Done.
39 int64 time_int64 = time.ToInternalValue();
40 *output = base::Int64ToString(time_int64);
41 return !output->empty();
42 }
43
44 bool StringToTime(std::string time, base::Time* output) {
45 int64 time_int64 = 0;
46 if (!base::StringToInt64(time, &time_int64))
47 return false;
48 *output = base::Time::FromInternalValue(time_int64);
49 return true;
50 }
51
52 } // namespace
53
28 namespace performance_monitor { 54 namespace performance_monitor {
29 55
30 PerformanceMonitor::PerformanceMonitor() : database_(NULL) { 56 PerformanceMonitor::PerformanceMonitor() : database_(NULL) {
31 } 57 }
32 58
33 PerformanceMonitor::~PerformanceMonitor() { 59 PerformanceMonitor::~PerformanceMonitor() {
34 } 60 }
35 61
36 void PerformanceMonitor::Start() { 62 void PerformanceMonitor::Start() {
63 std::string time;
64 CHECK(TimeToString(base::Time::Now(), &time));
37 content::BrowserThread::PostBlockingPoolTaskAndReply( 65 content::BrowserThread::PostBlockingPoolTaskAndReply(
38 FROM_HERE, 66 FROM_HERE,
39 base::Bind(&PerformanceMonitor::InitOnBackgroundThread, 67 base::Bind(&PerformanceMonitor::InitOnBackgroundThread,
40 base::Unretained(this)), 68 base::Unretained(this)),
41 base::Bind(&PerformanceMonitor::FinishInit, 69 base::Bind(&PerformanceMonitor::FinishInit,
42 base::Unretained(this))); 70 base::Unretained(this)));
43 } 71 }
44 72
45 void PerformanceMonitor::InitOnBackgroundThread() { 73 void PerformanceMonitor::InitOnBackgroundThread() {
46 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 74 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
47 database_ = Database::Create(database_path_); 75 database_ = Database::Create(database_path_);
48 } 76 }
49 77
50 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) { 78 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) {
51 if (!database_.get()) { 79 if (!database_.get()) {
52 database_path_ = path; 80 database_path_ = path;
53 return true; 81 return true;
54 } 82 }
55 83
56 // PerformanceMonitor already initialized with another path. 84 // PerformanceMonitor already initialized with another path.
57 return false; 85 return false;
58 } 86 }
59 87
60 void PerformanceMonitor::FinishInit() { 88 void PerformanceMonitor::FinishInit() {
61 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 89 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
62 RegisterForNotifications(); 90 RegisterForNotifications();
91 CheckForUncleanExit();
63 CheckForVersionUpdate(); 92 CheckForVersionUpdate();
93
94 timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(2),
95 this, &PerformanceMonitor::DoTimedCollections);
64 } 96 }
65 97
66 void PerformanceMonitor::RegisterForNotifications() { 98 void PerformanceMonitor::RegisterForNotifications() {
67 // Extensions 99 // Extensions
68 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, 100 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
69 content::NotificationService::AllSources()); 101 content::NotificationService::AllSources());
70 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED, 102 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
71 content::NotificationService::AllSources()); 103 content::NotificationService::AllSources());
72 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 104 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
73 content::NotificationService::AllSources()); 105 content::NotificationService::AllSources());
74 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE, 106 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
75 content::NotificationService::AllSources()); 107 content::NotificationService::AllSources());
76 108
77 // Crashes 109 // Crashes
78 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG, 110 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG,
79 content::NotificationService::AllSources()); 111 content::NotificationService::AllSources());
80 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 112 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
81 content::NotificationService::AllSources()); 113 content::NotificationService::AllSources());
114
115 // Profiles (for unclean exit)
116 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
117 content::NotificationService::AllSources());
82 } 118 }
83 119
84 // Static 120 // Static
85 PerformanceMonitor* PerformanceMonitor::GetInstance() { 121 PerformanceMonitor* PerformanceMonitor::GetInstance() {
86 return Singleton<PerformanceMonitor>::get(); 122 return Singleton<PerformanceMonitor>::get();
87 } 123 }
88 124
89 void PerformanceMonitor::AddEvent(scoped_ptr<Event> event) { 125 void PerformanceMonitor::AddEvent(scoped_ptr<Event> event) {
90 content::BrowserThread::PostBlockingPoolSequencedTask( 126 content::BrowserThread::PostBlockingPoolSequencedTask(
91 Database::kDatabaseSequenceToken, 127 Database::kDatabaseSequenceToken,
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 current_version)); 182 current_version));
147 if (!previous_version.empty()) { 183 if (!previous_version.empty()) {
148 AddEvent(util::CreateChromeUpdateEvent( 184 AddEvent(util::CreateChromeUpdateEvent(
149 base::Time::Now(), 185 base::Time::Now(),
150 previous_version, 186 previous_version,
151 current_version)); 187 current_version));
152 } 188 }
153 } 189 }
154 } 190 }
155 191
192 // The reason we need this as well as a notification check is because the first
193 // profiles can be loaded prior to the initialization of PerformanceMonitor. In
194 // this case, we find if they exited uncleanly here.
Yoyo Zhou 2012/07/10 02:35:06 This comment is written backwards. I'd say "At ini
Devlin 2012/07/10 17:18:32 Done.
195 void PerformanceMonitor::CheckForUncleanExit() {
Yoyo Zhou 2012/07/10 02:35:06 CheckForUncleanExits
Devlin 2012/07/10 17:18:32 Done.
196 std::vector<Profile*> profiles =
197 g_browser_process->profile_manager()->GetLoadedProfiles();
198
199 for (std::vector<Profile*>::const_iterator iter = profiles.begin();
200 iter != profiles.end(); ++iter) {
201 if (!(*iter)->DidLastSessionExitCleanly()) {
202 content::BrowserThread::PostBlockingPoolSequencedTask(
203 Database::kDatabaseSequenceToken,
204 FROM_HERE,
205 base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
206 base::Unretained(this),
207 (*iter)->GetDebugName()));
208 }
209 }
210 }
211
212 void PerformanceMonitor::AddUncleanExitEvent(std::string profile_name) {
213 std::string database_key = kStateProfile + profile_name;
214 std::string last_active_string = database_->GetStateValue(database_key);
215
216 // Check if there was no previous time; this should only happen if the profile
217 // was last used prior to PerformanceMonitor's integration. Do nothing in this
218 // case, since the event was prior to the beginning of our recording.
219 if (last_active_string.empty())
220 return;
221
222 base::Time last_active_time;
223 CHECK(StringToTime(last_active_string, &last_active_time));
224
225 // We should never find a case where the last active time for the profile is
226 // after the current time. DCHECK (instead of CHECK) because of the chance
227 // that someone has backdated the system time, so that Chrome won't crash in
Yoyo Zhou 2012/07/10 02:35:06 This seems like a case that could actually happen,
Devlin 2012/07/10 17:18:32 Yeah, I wasn't sure about this one...it won't brea
228 // a release build.
229 DCHECK(last_active_time < base::Time::Now());
230
231 scoped_ptr<Event> event =
232 util::CreateUncleanExitEvent(last_active_time, profile_name);
233
234 database_->AddEvent(*event.get());
235 }
236
237 void PerformanceMonitor::UpdateLiveProfiles() {
238 std::string time;
239 CHECK(TimeToString(base::Time::Now(), &time));
240 scoped_ptr<std::set<std::string> > active_profiles(
241 new std::set<std::string>());
242
243 for (BrowserList::const_iterator iter = BrowserList::begin();
244 iter != BrowserList::end(); ++iter) {
245 active_profiles->insert((*iter)->profile()->GetDebugName());
246 }
247
248 content::BrowserThread::PostBlockingPoolSequencedTask(
249 Database::kDatabaseSequenceToken,
250 FROM_HERE,
251 base::Bind(&PerformanceMonitor::UpdateLiveProfilesHelper,
252 base::Unretained(this),
253 base::Passed(active_profiles.Pass()),
254 time));
255 }
256
257 void PerformanceMonitor::UpdateLiveProfilesHelper(
258 scoped_ptr<std::set<std::string> > active_profiles,
259 std::string time) {
260 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
261
262 for (std::set<std::string>::const_iterator iter = active_profiles->begin();
263 iter != active_profiles->end(); ++iter) {
264 database_->AddStateValue(kStateProfile + *iter, time);
265 }
266 }
267
268 void PerformanceMonitor::DoTimedCollections() {
269 UpdateLiveProfiles();
270 }
271
156 void PerformanceMonitor::Observe(int type, 272 void PerformanceMonitor::Observe(int type,
157 const content::NotificationSource& source, 273 const content::NotificationSource& source,
158 const content::NotificationDetails& details) { 274 const content::NotificationDetails& details) {
159 switch (type) { 275 switch (type) {
160 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 276 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
161 const Extension* extension = content::Details<Extension>(details).ptr(); 277 const Extension* extension = content::Details<Extension>(details).ptr();
162 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(), 278 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(),
163 extension->id(), 279 extension->id(),
164 extension->name(), 280 extension->name(),
165 extension->url().spec(), 281 extension->url().spec(),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 // Determine the type of crash. 348 // Determine the type of crash.
233 EventType type = 349 EventType type =
234 status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ? 350 status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
235 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH; 351 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH;
236 352
237 AddEvent(util::CreateCrashEvent(base::Time::Now(), 353 AddEvent(util::CreateCrashEvent(base::Time::Now(),
238 type, 354 type,
239 contents->GetURL().spec())); 355 contents->GetURL().spec()));
240 break; 356 break;
241 } 357 }
358 case chrome::NOTIFICATION_PROFILE_ADDED: {
359 Profile* profile = content::Source<Profile>(source).ptr();
360 if (!profile->DidLastSessionExitCleanly()) {
361 content::BrowserThread::PostBlockingPoolSequencedTask(
362 Database::kDatabaseSequenceToken,
363 FROM_HERE,
364 base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
365 base::Unretained(this),
366 profile->GetDebugName()));
367 }
368 break;
369 }
242 default: { 370 default: {
243 NOTREACHED(); 371 NOTREACHED();
244 break; 372 break;
245 } 373 }
246 } 374 }
247 } 375 }
248 376
249 } // namespace performance_monitor 377 } // namespace performance_monitor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698