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

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

Issue 2344343002: Wire in postmortem report collection (Closed)
Patch Set: Merge 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 LogCollectionInitStatus(CollectionInitializationStatus status) {
207 UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.InitStatus", status,
208 INIT_STATUS_MAX);
209 }
210
188 } // namespace 211 } // namespace
189 212
190 const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] = 213 const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] =
191 "Stability.BrowserExitCodes"; 214 "Stability.BrowserExitCodes";
192 215
193 WatcherMetricsProviderWin::WatcherMetricsProviderWin( 216 WatcherMetricsProviderWin::WatcherMetricsProviderWin(
194 const base::string16& registry_path, 217 const base::string16& registry_path,
195 base::TaskRunner* cleanup_io_task_runner) 218 const base::FilePath& user_data_dir,
219 const base::FilePath& crash_dir,
220 base::TaskRunner* io_task_runner)
196 : recording_enabled_(false), 221 : recording_enabled_(false),
197 cleanup_scheduled_(false), 222 cleanup_scheduled_(false),
198 registry_path_(registry_path), 223 registry_path_(registry_path),
199 cleanup_io_task_runner_(cleanup_io_task_runner) { 224 user_data_dir_(user_data_dir),
200 DCHECK(cleanup_io_task_runner_); 225 crash_dir_(crash_dir),
226 io_task_runner_(io_task_runner),
227 weak_ptr_factory_(this) {
228 DCHECK(io_task_runner_);
201 } 229 }
202 230
203 WatcherMetricsProviderWin::~WatcherMetricsProviderWin() { 231 WatcherMetricsProviderWin::~WatcherMetricsProviderWin() {
204 } 232 }
205 233
206 void WatcherMetricsProviderWin::OnRecordingEnabled() { 234 void WatcherMetricsProviderWin::OnRecordingEnabled() {
207 recording_enabled_ = true; 235 recording_enabled_ = true;
208 } 236 }
209 237
210 void WatcherMetricsProviderWin::OnRecordingDisabled() { 238 void WatcherMetricsProviderWin::OnRecordingDisabled() {
211 if (!recording_enabled_ && !cleanup_scheduled_) { 239 if (!recording_enabled_ && !cleanup_scheduled_) {
212 // When metrics reporting is disabled, the providers get an 240 // When metrics reporting is disabled, the providers get an
213 // OnRecordingDisabled notification at startup. Use that first notification 241 // OnRecordingDisabled notification at startup. Use that first notification
214 // to issue the cleanup task. 242 // to issue the cleanup task.
215 cleanup_io_task_runner_->PostTask( 243 io_task_runner_->PostTask(
216 FROM_HERE, base::Bind(&DeleteExitCodeRegistryKey, registry_path_)); 244 FROM_HERE, base::Bind(&DeleteExitCodeRegistryKey, registry_path_));
217 245
218 cleanup_scheduled_ = true; 246 cleanup_scheduled_ = true;
219 } 247 }
220 } 248 }
221 249
222 void WatcherMetricsProviderWin::ProvideStabilityMetrics( 250 void WatcherMetricsProviderWin::ProvideStabilityMetrics(
223 metrics::SystemProfileProto* /* system_profile_proto */) { 251 metrics::SystemProfileProto* /* system_profile_proto */) {
224 // Note that if there are multiple instances of Chrome running in the same 252 // 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 253 // 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 254 // 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 255 // 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 256 // necessary to implement some form of global locking, which is not worth it
229 // here. 257 // here.
230 RecordExitCodes(registry_path_); 258 RecordExitCodes(registry_path_);
231 DeleteExitFunnels(registry_path_); 259 DeleteExitFunnels(registry_path_);
232 } 260 }
233 261
262 void WatcherMetricsProviderWin::CollectPostmortemReports(
263 const base::Closure& done_callback) {
264 io_task_runner_->PostTaskAndReply(
265 FROM_HERE,
266 base::Bind(
267 &WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool,
268 weak_ptr_factory_.GetWeakPtr()),
269 done_callback);
270 }
271
272 void WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool() {
273 // Note: the feature controls both instrumentation and collection.
274 bool is_stability_debugging_on =
275 base::FeatureList::IsEnabled(browser_watcher::kStabilityDebuggingFeature);
276 if (!is_stability_debugging_on) {
277 // TODO(manzagop): delete possible leftover data.
278 return;
279 }
280
281 SCOPED_UMA_HISTOGRAM_TIMER("ActivityTracker.Collect.TotalTime");
282
283 if (user_data_dir_.empty() || crash_dir_.empty()) {
284 LOG(ERROR) << "User data directory or crash directory is unknown.";
285 LogCollectionInitStatus(UNKNOWN_DIR);
286 return;
287 }
288
289 // Determine the stability directory and the stability file for the current
290 // process.
291 base::FilePath stability_dir = GetStabilityDir(user_data_dir_);
292 base::FilePath current_stability_file;
293 if (!GetStabilityFileForProcess(base::Process::Current(), user_data_dir_,
294 &current_stability_file)) {
295 LOG(ERROR) << "Failed to get the current stability file.";
296 LogCollectionInitStatus(GET_STABILITY_FILE_PATH_FAILED);
297 return;
298 }
299 const std::set<base::FilePath>& excluded_debug_files = {
300 current_stability_file};
301
302 // Create a database. Note: Chrome already has a g_database in crashpad.cc but
303 // it has internal linkage. Create a new one.
304 std::unique_ptr<crashpad::CrashReportDatabase> crashpad_database =
305 crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir_);
306 if (!crashpad_database) {
307 LOG(ERROR) << "Failed to initialize a CrashPad database.";
308 LogCollectionInitStatus(CRASHPAD_DATABASE_INIT_FAILED);
309 return;
310 }
311
312 // Note: not caching the histogram pointer as this function isn't expected to
313 // be called multiple times.
314 LogCollectionInitStatus(INIT_SUCCESS);
315
316 // TODO(manzagop): fix incorrect version attribution on update.
317 PostmortemReportCollector collector;
318 collector.CollectAndSubmitForUpload(stability_dir, GetStabilityFilePattern(),
319 excluded_debug_files,
320 crashpad_database.get());
321 }
322
234 } // namespace browser_watcher 323 } // namespace browser_watcher
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698