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

Side by Side Diff: components/browser_watcher/watcher_metrics_provider_win.cc

Issue 2344343002: Wire in postmortem report collection (Closed)
Patch Set: Address Siggi's second round Created 4 years, 2 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) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 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 "components/browser_watcher/watcher_metrics_provider_win.h" 5 #include "components/browser_watcher/watcher_metrics_provider_win.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <limits> 9 #include <limits>
10 #include <memory>
11 #include <set>
10 #include <vector> 12 #include <vector>
11 13
12 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/feature_list.h"
16 #include "base/metrics/histogram.h"
17 #include "base/metrics/histogram_base.h"
18 #include "base/metrics/histogram_macros.h"
13 #include "base/metrics/sparse_histogram.h" 19 #include "base/metrics/sparse_histogram.h"
14 #include "base/process/process.h" 20 #include "base/process/process.h"
15 #include "base/strings/string_number_conversions.h" 21 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_piece.h" 22 #include "base/strings/string_piece.h"
17 #include "base/strings/utf_string_conversions.h" 23 #include "base/strings/utf_string_conversions.h"
18 #include "base/win/registry.h" 24 #include "base/win/registry.h"
25 #include "components/browser_watcher/features.h"
26 #include "components/browser_watcher/postmortem_report_collector.h"
27 #include "components/browser_watcher/stability_debugging_win.h"
28 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
19 29
20 namespace browser_watcher { 30 namespace browser_watcher {
21 31
22 namespace { 32 namespace {
23 33
24 // Process ID APIs on Windows talk in DWORDs, whereas for string formatting 34 // Process ID APIs on Windows talk in DWORDs, whereas for string formatting
25 // and parsing, this code uses int. In practice there are no process IDs with 35 // and parsing, this code uses int. In practice there are no process IDs with
26 // the high bit set on Windows, so there's no danger of overflow if this is 36 // the high bit set on Windows, so there's no danger of overflow if this is
27 // done consistently. 37 // done consistently.
28 static_assert(sizeof(DWORD) == sizeof(int), 38 static_assert(sizeof(DWORD) == sizeof(int),
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 LONG res = key.Open(HKEY_CURRENT_USER, registry_path.c_str(), 188 LONG res = key.Open(HKEY_CURRENT_USER, registry_path.c_str(),
179 KEY_QUERY_VALUE | KEY_SET_VALUE); 189 KEY_QUERY_VALUE | KEY_SET_VALUE);
180 if (res == ERROR_SUCCESS) { 190 if (res == ERROR_SUCCESS) {
181 DeleteAllValues(&key); 191 DeleteAllValues(&key);
182 res = key.DeleteEmptyKey(L""); 192 res = key.DeleteEmptyKey(L"");
183 } 193 }
184 if (res != ERROR_FILE_NOT_FOUND && res != ERROR_SUCCESS) 194 if (res != ERROR_FILE_NOT_FOUND && res != ERROR_SUCCESS)
185 DVLOG(1) << "Failed to delete exit code key " << registry_path; 195 DVLOG(1) << "Failed to delete exit code key " << registry_path;
186 } 196 }
187 197
198 enum CollectionInitializationStatus {
199 INIT_SUCCESS = 0,
200 UNKNOWN_DIR = 1,
201 GET_STABILITY_FILE_PATH_FAILED = 2,
202 CRASHPAD_DATABASE_INIT_FAILED = 3,
203 INIT_STATUS_MAX = 4
204 };
205
206 void LogCollectionInitStatusWithoutStaticVar(
207 CollectionInitializationStatus status) {
208 base::HistogramBase* init_status_hist = base::LinearHistogram::FactoryGet(
209 "ActivityTracker.Collect.InitStatus", 1, INIT_STATUS_MAX,
210 INIT_STATUS_MAX + 1, base::HistogramBase::kUmaTargetedHistogramFlag);
Sigurður Ásgeirsson 2016/09/22 15:46:14 same comment here.
manzagop (departed) 2016/09/23 21:57:01 Done.
211 init_status_hist->Add(status);
212 }
213
188 } // namespace 214 } // namespace
189 215
190 const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] = 216 const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] =
191 "Stability.BrowserExitCodes"; 217 "Stability.BrowserExitCodes";
192 218
193 WatcherMetricsProviderWin::WatcherMetricsProviderWin( 219 WatcherMetricsProviderWin::WatcherMetricsProviderWin(
194 const base::string16& registry_path, 220 const base::string16& registry_path,
195 base::TaskRunner* cleanup_io_task_runner) 221 const base::FilePath& user_data_dir,
222 const base::FilePath& crash_dir,
223 base::TaskRunner* io_task_runner)
196 : recording_enabled_(false), 224 : recording_enabled_(false),
197 cleanup_scheduled_(false), 225 cleanup_scheduled_(false),
198 registry_path_(registry_path), 226 registry_path_(registry_path),
199 cleanup_io_task_runner_(cleanup_io_task_runner) { 227 user_data_dir_(user_data_dir),
200 DCHECK(cleanup_io_task_runner_); 228 crash_dir_(crash_dir),
229 io_task_runner_(io_task_runner),
230 weak_ptr_factory_(this) {
231 DCHECK(io_task_runner_);
201 } 232 }
202 233
203 WatcherMetricsProviderWin::~WatcherMetricsProviderWin() { 234 WatcherMetricsProviderWin::~WatcherMetricsProviderWin() {
204 } 235 }
205 236
206 void WatcherMetricsProviderWin::OnRecordingEnabled() { 237 void WatcherMetricsProviderWin::OnRecordingEnabled() {
207 recording_enabled_ = true; 238 recording_enabled_ = true;
208 } 239 }
209 240
210 void WatcherMetricsProviderWin::OnRecordingDisabled() { 241 void WatcherMetricsProviderWin::OnRecordingDisabled() {
211 if (!recording_enabled_ && !cleanup_scheduled_) { 242 if (!recording_enabled_ && !cleanup_scheduled_) {
212 // When metrics reporting is disabled, the providers get an 243 // When metrics reporting is disabled, the providers get an
213 // OnRecordingDisabled notification at startup. Use that first notification 244 // OnRecordingDisabled notification at startup. Use that first notification
214 // to issue the cleanup task. 245 // to issue the cleanup task.
215 cleanup_io_task_runner_->PostTask( 246 io_task_runner_->PostTask(
216 FROM_HERE, base::Bind(&DeleteExitCodeRegistryKey, registry_path_)); 247 FROM_HERE, base::Bind(&DeleteExitCodeRegistryKey, registry_path_));
217 248
218 cleanup_scheduled_ = true; 249 cleanup_scheduled_ = true;
219 } 250 }
220 } 251 }
221 252
222 void WatcherMetricsProviderWin::ProvideStabilityMetrics( 253 void WatcherMetricsProviderWin::ProvideStabilityMetrics(
223 metrics::SystemProfileProto* /* system_profile_proto */) { 254 metrics::SystemProfileProto* /* system_profile_proto */) {
224 // Note that if there are multiple instances of Chrome running in the same 255 // Note that if there are multiple instances of Chrome running in the same
225 // user account, there's a small race that will double-report the exit codes 256 // user account, there's a small race that will double-report the exit codes
226 // from both/multiple instances. This ought to be vanishingly rare and will 257 // from both/multiple instances. This ought to be vanishingly rare and will
227 // only manifest as low-level "random" noise. To work around this it would be 258 // only manifest as low-level "random" noise. To work around this it would be
228 // necessary to implement some form of global locking, which is not worth it 259 // necessary to implement some form of global locking, which is not worth it
229 // here. 260 // here.
230 RecordExitCodes(registry_path_); 261 RecordExitCodes(registry_path_);
231 DeleteExitFunnels(registry_path_); 262 DeleteExitFunnels(registry_path_);
232 } 263 }
233 264
265 void WatcherMetricsProviderWin::CollectPostmortemReports(
266 const base::Closure& done_callback) {
267 io_task_runner_->PostTaskAndReply(
268 FROM_HERE,
269 base::Bind(
270 &WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool,
271 weak_ptr_factory_.GetWeakPtr()),
272 done_callback);
273 }
274
275 void WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool() {
276 // Note: the feature controls both instrumentation and collection.
277 bool is_stability_debugging_on =
278 base::FeatureList::IsEnabled(browser_watcher::kStabilityDebuggingFeature);
279 if (!is_stability_debugging_on) {
280 // TODO(manzagop): delete possible leftover data.
281 return;
282 }
283
284 SCOPED_UMA_HISTOGRAM_TIMER("ActivityTracker.Collect.TotalTime");
285
286 if (user_data_dir_.empty() || crash_dir_.empty()) {
287 LOG(ERROR) << "User data directory or crash directory is unknown.";
288 LogCollectionInitStatusWithoutStaticVar(UNKNOWN_DIR);
289 return;
290 }
291
292 // Determine the stability directory and the stability file for the current
293 // process.
294 base::FilePath stability_dir = StabilityDebugging::GetDir(user_data_dir_);
295 base::FilePath current_stability_file;
296 if (!StabilityDebugging::GetFileForProcess(
297 base::Process::Current(), user_data_dir_, &current_stability_file)) {
298 LOG(ERROR) << "Failed to get the current stability file.";
299 LogCollectionInitStatusWithoutStaticVar(GET_STABILITY_FILE_PATH_FAILED);
300 return;
301 }
302 const std::set<base::FilePath>& excluded_debug_files = {
303 current_stability_file};
304
305 // Create a database. Note: Chrome already has a g_database in crashpad.cc but
306 // it has internal linkage. Create a new one.
307 std::unique_ptr<crashpad::CrashReportDatabase> crashpad_database =
308 crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir_);
309 if (!crashpad_database) {
310 LOG(ERROR) << "Failed to initialize a CrashPad database.";
311 LogCollectionInitStatusWithoutStaticVar(CRASHPAD_DATABASE_INIT_FAILED);
312 return;
313 }
314
315 // Note: not caching the histogram pointer as this function isn't expected to
316 // be called multiple times.
317 LogCollectionInitStatusWithoutStaticVar(INIT_SUCCESS);
318
319 // TODO(manzagop): fix incorrect version attribution on update.
320 PostmortemReportCollector collector;
321 collector.CollectAndSubmitForUpload(
322 stability_dir, StabilityDebugging::GetFilePattern(), excluded_debug_files,
323 crashpad_database.get());
324 }
325
234 } // namespace browser_watcher 326 } // namespace browser_watcher
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698