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

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: Requested changes made 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 std::string TimeToString(base::Time time) {
39 int64 time_int64 = time.ToInternalValue();
40 return base::Int64ToString(time_int64);
41 }
42
43 bool StringToTime(std::string time, base::Time* output) {
44 int64 time_int64 = 0;
45 if (!base::StringToInt64(time, &time_int64))
46 return false;
47 *output = base::Time::FromInternalValue(time_int64);
48 return true;
49 }
50
51 } // namespace
52
28 namespace performance_monitor { 53 namespace performance_monitor {
29 54
30 PerformanceMonitor::PerformanceMonitor() : database_(NULL) { 55 PerformanceMonitor::PerformanceMonitor() : database_(NULL) {
31 } 56 }
32 57
33 PerformanceMonitor::~PerformanceMonitor() { 58 PerformanceMonitor::~PerformanceMonitor() {
34 } 59 }
35 60
36 void PerformanceMonitor::Start() { 61 void PerformanceMonitor::Start() {
62 std::string time = TimeToString(base::Time::Now());
37 content::BrowserThread::PostBlockingPoolTaskAndReply( 63 content::BrowserThread::PostBlockingPoolTaskAndReply(
38 FROM_HERE, 64 FROM_HERE,
39 base::Bind(&PerformanceMonitor::InitOnBackgroundThread, 65 base::Bind(&PerformanceMonitor::InitOnBackgroundThread,
40 base::Unretained(this)), 66 base::Unretained(this)),
41 base::Bind(&PerformanceMonitor::FinishInit, 67 base::Bind(&PerformanceMonitor::FinishInit,
42 base::Unretained(this))); 68 base::Unretained(this)));
43 } 69 }
44 70
45 void PerformanceMonitor::InitOnBackgroundThread() { 71 void PerformanceMonitor::InitOnBackgroundThread() {
46 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 72 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
47 database_ = Database::Create(database_path_); 73 database_ = Database::Create(database_path_);
48 } 74 }
49 75
50 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) { 76 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) {
51 if (!database_.get()) { 77 if (!database_.get()) {
52 database_path_ = path; 78 database_path_ = path;
53 return true; 79 return true;
54 } 80 }
55 81
56 // PerformanceMonitor already initialized with another path. 82 // PerformanceMonitor already initialized with another path.
57 return false; 83 return false;
58 } 84 }
59 85
60 void PerformanceMonitor::FinishInit() { 86 void PerformanceMonitor::FinishInit() {
61 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 87 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
62 RegisterForNotifications(); 88 RegisterForNotifications();
89 CheckForUncleanExits();
63 CheckForVersionUpdate(); 90 CheckForVersionUpdate();
91
92 timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(2),
93 this, &PerformanceMonitor::DoTimedCollections);
64 } 94 }
65 95
66 void PerformanceMonitor::RegisterForNotifications() { 96 void PerformanceMonitor::RegisterForNotifications() {
67 // Extensions 97 // Extensions
68 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, 98 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
69 content::NotificationService::AllSources()); 99 content::NotificationService::AllSources());
70 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED, 100 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
71 content::NotificationService::AllSources()); 101 content::NotificationService::AllSources());
72 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 102 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
73 content::NotificationService::AllSources()); 103 content::NotificationService::AllSources());
74 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE, 104 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
75 content::NotificationService::AllSources()); 105 content::NotificationService::AllSources());
76 106
77 // Crashes 107 // Crashes
78 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG, 108 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG,
79 content::NotificationService::AllSources()); 109 content::NotificationService::AllSources());
80 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 110 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
81 content::NotificationService::AllSources()); 111 content::NotificationService::AllSources());
112
113 // Profiles (for unclean exit)
114 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
115 content::NotificationService::AllSources());
82 } 116 }
83 117
84 // Static 118 // Static
85 PerformanceMonitor* PerformanceMonitor::GetInstance() { 119 PerformanceMonitor* PerformanceMonitor::GetInstance() {
86 return Singleton<PerformanceMonitor>::get(); 120 return Singleton<PerformanceMonitor>::get();
87 } 121 }
88 122
89 void PerformanceMonitor::AddEvent(scoped_ptr<Event> event) { 123 void PerformanceMonitor::AddEvent(scoped_ptr<Event> event) {
90 content::BrowserThread::PostBlockingPoolSequencedTask( 124 content::BrowserThread::PostBlockingPoolSequencedTask(
91 Database::kDatabaseSequenceToken, 125 Database::kDatabaseSequenceToken,
92 FROM_HERE, 126 FROM_HERE,
93 base::Bind(&PerformanceMonitor::AddEventOnBackgroundThread, 127 base::Bind(&PerformanceMonitor::AddEventOnBackgroundThread,
94 base::Unretained(this), 128 base::Unretained(this),
95 base::Passed(event.Pass()))); 129 base::Passed(event.Pass())));
96 } 130 }
97 131
98 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) { 132 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) {
99 database_->AddEvent(*event.get()); 133 database_->AddEvent(*event.get());
100 } 134 }
101 135
102 void PerformanceMonitor::GetStateValueOnBackgroundThread( 136 void PerformanceMonitor::GetStateValueOnBackgroundThread(
103 const std::string& key, 137 const std::string& key,
104 const StateValueCallback& callback) { 138 const StateValueCallback& callback) {
105 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 139 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
106 std::string state_value = database_->GetStateValue(key); 140 std::string state_value = database_->GetStateValue(key);
107 141
108 callback.Run(state_value); 142 callback.Run(state_value);
109 } 143 }
110 144
111 void PerformanceMonitor::CheckForVersionUpdate() { 145 void PerformanceMonitor::CheckForVersionUpdate() {
112 StateValueCallback callback = 146 StateValueCallback callback =
113 base::Bind(&PerformanceMonitor::CheckForVersionUpdateHelper, 147 base::Bind(&PerformanceMonitor::CheckForVersionUpdateHelper,
114 base::Unretained(this)); 148 base::Unretained(this));
115 149
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 current_version)); 181 current_version));
148 if (!previous_version.empty()) { 182 if (!previous_version.empty()) {
149 AddEvent(util::CreateChromeUpdateEvent( 183 AddEvent(util::CreateChromeUpdateEvent(
150 base::Time::Now(), 184 base::Time::Now(),
151 previous_version, 185 previous_version,
152 current_version)); 186 current_version));
153 } 187 }
154 } 188 }
155 } 189 }
156 190
191 // We check if profiles exited cleanly initialization time in case they were
192 // loaded prior to PerformanceMonitor's initialization. Later profiles will be
193 // checked through the PROFILE_ADDED notification.
194 void PerformanceMonitor::CheckForUncleanExits() {
195 std::vector<Profile*> profiles =
196 g_browser_process->profile_manager()->GetLoadedProfiles();
197
198 for (std::vector<Profile*>::const_iterator iter = profiles.begin();
199 iter != profiles.end(); ++iter) {
200 if (!(*iter)->DidLastSessionExitCleanly()) {
201 content::BrowserThread::PostBlockingPoolSequencedTask(
202 Database::kDatabaseSequenceToken,
203 FROM_HERE,
204 base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
205 base::Unretained(this),
206 (*iter)->GetDebugName()));
207 }
208 }
209 }
210
211 void PerformanceMonitor::AddUncleanExitEvent(std::string profile_name) {
212 std::string database_key = kStateProfilePrefix + profile_name;
213 std::string last_active_string = database_->GetStateValue(database_key);
214
215 // Check if there was no previous time; this should only happen if the profile
216 // was last used prior to PerformanceMonitor's integration. Do nothing in this
217 // case, since the event was prior to the beginning of our recording.
218 if (last_active_string.empty())
219 return;
220
221 base::Time last_active_time;
222 CHECK(StringToTime(last_active_string, &last_active_time));
223
224 scoped_ptr<Event> event =
225 util::CreateUncleanExitEvent(last_active_time, profile_name);
226
227 database_->AddEvent(*event.get());
228 }
229
230 void PerformanceMonitor::UpdateLiveProfiles() {
231 std::string time = TimeToString(base::Time::Now());
232 scoped_ptr<std::set<std::string> > active_profiles(
233 new std::set<std::string>());
234
235 for (BrowserList::const_iterator iter = BrowserList::begin();
236 iter != BrowserList::end(); ++iter) {
237 active_profiles->insert((*iter)->profile()->GetDebugName());
238 }
239
240 content::BrowserThread::PostBlockingPoolSequencedTask(
241 Database::kDatabaseSequenceToken,
242 FROM_HERE,
243 base::Bind(&PerformanceMonitor::UpdateLiveProfilesHelper,
244 base::Unretained(this),
245 base::Passed(active_profiles.Pass()),
246 time));
247 }
248
249 void PerformanceMonitor::UpdateLiveProfilesHelper(
250 scoped_ptr<std::set<std::string> > active_profiles,
251 std::string time) {
252 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
253
254 for (std::set<std::string>::const_iterator iter = active_profiles->begin();
255 iter != active_profiles->end(); ++iter) {
256 database_->AddStateValue(kStateProfilePrefix + *iter, time);
257 }
258 }
259
260 void PerformanceMonitor::DoTimedCollections() {
261 UpdateLiveProfiles();
262 }
263
157 void PerformanceMonitor::Observe(int type, 264 void PerformanceMonitor::Observe(int type,
158 const content::NotificationSource& source, 265 const content::NotificationSource& source,
159 const content::NotificationDetails& details) { 266 const content::NotificationDetails& details) {
160 switch (type) { 267 switch (type) {
161 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 268 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
162 const Extension* extension = content::Details<Extension>(details).ptr(); 269 const Extension* extension = content::Details<Extension>(details).ptr();
163 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(), 270 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(),
164 extension->id(), 271 extension->id(),
165 extension->name(), 272 extension->name(),
166 extension->url().spec(), 273 extension->url().spec(),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 // Determine the type of crash. 340 // Determine the type of crash.
234 EventType type = 341 EventType type =
235 status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ? 342 status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
236 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH; 343 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH;
237 344
238 AddEvent(util::CreateCrashEvent(base::Time::Now(), 345 AddEvent(util::CreateCrashEvent(base::Time::Now(),
239 type, 346 type,
240 contents->GetURL().spec())); 347 contents->GetURL().spec()));
241 break; 348 break;
242 } 349 }
350 case chrome::NOTIFICATION_PROFILE_ADDED: {
351 Profile* profile = content::Source<Profile>(source).ptr();
352 if (!profile->DidLastSessionExitCleanly()) {
353 content::BrowserThread::PostBlockingPoolSequencedTask(
354 Database::kDatabaseSequenceToken,
355 FROM_HERE,
356 base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
357 base::Unretained(this),
358 profile->GetDebugName()));
359 }
360 break;
361 }
243 default: { 362 default: {
244 NOTREACHED(); 363 NOTREACHED();
245 break; 364 break;
246 } 365 }
247 } 366 }
248 } 367 }
249 368
250 } // namespace performance_monitor 369 } // namespace performance_monitor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698