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

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

Issue 2344343002: Wire in postmortem report collection (Closed)
Patch Set: Address first 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_macros.h"
13 #include "base/metrics/sparse_histogram.h" 17 #include "base/metrics/sparse_histogram.h"
14 #include "base/process/process.h" 18 #include "base/process/process.h"
15 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_piece.h" 20 #include "base/strings/string_piece.h"
17 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
18 #include "base/win/registry.h" 22 #include "base/win/registry.h"
23 #include "components/browser_watcher/features.h"
24 #include "components/browser_watcher/postmortem_report_collector.h"
25 #include "components/browser_watcher/stability_debugging_win.h"
26 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
19 27
20 namespace browser_watcher { 28 namespace browser_watcher {
21 29
22 namespace { 30 namespace {
23 31
24 // Process ID APIs on Windows talk in DWORDs, whereas for string formatting 32 // 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 33 // 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 34 // the high bit set on Windows, so there's no danger of overflow if this is
27 // done consistently. 35 // done consistently.
28 static_assert(sizeof(DWORD) == sizeof(int), 36 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(), 186 LONG res = key.Open(HKEY_CURRENT_USER, registry_path.c_str(),
179 KEY_QUERY_VALUE | KEY_SET_VALUE); 187 KEY_QUERY_VALUE | KEY_SET_VALUE);
180 if (res == ERROR_SUCCESS) { 188 if (res == ERROR_SUCCESS) {
181 DeleteAllValues(&key); 189 DeleteAllValues(&key);
182 res = key.DeleteEmptyKey(L""); 190 res = key.DeleteEmptyKey(L"");
183 } 191 }
184 if (res != ERROR_FILE_NOT_FOUND && res != ERROR_SUCCESS) 192 if (res != ERROR_FILE_NOT_FOUND && res != ERROR_SUCCESS)
185 DVLOG(1) << "Failed to delete exit code key " << registry_path; 193 DVLOG(1) << "Failed to delete exit code key " << registry_path;
186 } 194 }
187 195
196 enum CollectionInitializationStatus {
197 INIT_SUCCESS = 0,
198 UNKNOWN_DIR = 1,
199 GET_STABILITY_FILE_PATH_FAILED = 2,
200 CRASHPAD_DATABASE_INIT_FAILED = 3,
201 INIT_STATUS_MAX = 4
202 };
203
188 } // namespace 204 } // namespace
189 205
190 const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] = 206 const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] =
191 "Stability.BrowserExitCodes"; 207 "Stability.BrowserExitCodes";
192 208
193 WatcherMetricsProviderWin::WatcherMetricsProviderWin( 209 WatcherMetricsProviderWin::WatcherMetricsProviderWin(
194 const base::string16& registry_path, 210 const base::string16& registry_path,
195 base::TaskRunner* cleanup_io_task_runner) 211 const base::FilePath& user_data_dir,
212 const base::FilePath& crash_dir,
213 base::TaskRunner* io_task_runner)
196 : recording_enabled_(false), 214 : recording_enabled_(false),
197 cleanup_scheduled_(false), 215 cleanup_scheduled_(false),
198 registry_path_(registry_path), 216 registry_path_(registry_path),
199 cleanup_io_task_runner_(cleanup_io_task_runner) { 217 user_data_dir_(user_data_dir),
200 DCHECK(cleanup_io_task_runner_); 218 crash_dir_(crash_dir),
219 io_task_runner_(io_task_runner),
220 weak_ptr_factory_(this) {
221 DCHECK(io_task_runner_);
201 } 222 }
202 223
203 WatcherMetricsProviderWin::~WatcherMetricsProviderWin() { 224 WatcherMetricsProviderWin::~WatcherMetricsProviderWin() {
204 } 225 }
205 226
206 void WatcherMetricsProviderWin::OnRecordingEnabled() { 227 void WatcherMetricsProviderWin::OnRecordingEnabled() {
207 recording_enabled_ = true; 228 recording_enabled_ = true;
208 } 229 }
209 230
210 void WatcherMetricsProviderWin::OnRecordingDisabled() { 231 void WatcherMetricsProviderWin::OnRecordingDisabled() {
211 if (!recording_enabled_ && !cleanup_scheduled_) { 232 if (!recording_enabled_ && !cleanup_scheduled_) {
212 // When metrics reporting is disabled, the providers get an 233 // When metrics reporting is disabled, the providers get an
213 // OnRecordingDisabled notification at startup. Use that first notification 234 // OnRecordingDisabled notification at startup. Use that first notification
214 // to issue the cleanup task. 235 // to issue the cleanup task.
215 cleanup_io_task_runner_->PostTask( 236 io_task_runner_->PostTask(
216 FROM_HERE, base::Bind(&DeleteExitCodeRegistryKey, registry_path_)); 237 FROM_HERE, base::Bind(&DeleteExitCodeRegistryKey, registry_path_));
217 238
218 cleanup_scheduled_ = true; 239 cleanup_scheduled_ = true;
219 } 240 }
220 } 241 }
221 242
222 void WatcherMetricsProviderWin::ProvideStabilityMetrics( 243 void WatcherMetricsProviderWin::ProvideStabilityMetrics(
223 metrics::SystemProfileProto* /* system_profile_proto */) { 244 metrics::SystemProfileProto* /* system_profile_proto */) {
224 // Note that if there are multiple instances of Chrome running in the same 245 // 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 246 // 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 247 // 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 248 // 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 249 // necessary to implement some form of global locking, which is not worth it
229 // here. 250 // here.
230 RecordExitCodes(registry_path_); 251 RecordExitCodes(registry_path_);
231 DeleteExitFunnels(registry_path_); 252 DeleteExitFunnels(registry_path_);
232 } 253 }
233 254
255 void WatcherMetricsProviderWin::CollectPostmortemReports(
256 const base::Closure& done_callback) {
257 io_task_runner_->PostTaskAndReply(
258 FROM_HERE,
259 base::Bind(
260 &WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool,
261 weak_ptr_factory_.GetWeakPtr()),
262 done_callback);
263 }
264
265 void WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool() {
266 // Note: the feature controls both instrumentation and collection.
267 bool is_stability_debugging_on =
268 base::FeatureList::IsEnabled(browser_watcher::kStabilityDebuggingFeature);
269 if (!is_stability_debugging_on) {
270 // TODO(manzagop): delete possible leftover data.
271 return;
272 }
273
274 SCOPED_UMA_HISTOGRAM_TIMER("ActivityTracker.Collect.TotalTime");
275
276 if (user_data_dir_.empty() || crash_dir_.empty()) {
277 LOG(ERROR) << "User data directory or crash directory is unknown.";
278 UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.InitStatus",
Sigurður Ásgeirsson 2016/09/22 13:06:12 It irks me to see these macros used for code that'
manzagop (departed) 2016/09/22 15:41:57 There doesn't seem to be, so I went with a manual
279 UNKNOWN_DIR, INIT_STATUS_MAX);
280 return;
281 }
282
283 // Determine the stability directory and the stability file for the current
284 // process.
285 base::FilePath stability_dir = StabilityDebugging::GetDir(user_data_dir_);
286 base::FilePath current_stability_file;
287 if (!StabilityDebugging::GetFileForProcess(
288 base::Process::Current(), user_data_dir_, &current_stability_file)) {
289 LOG(ERROR) << "Failed to get the current stability file.";
290 UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.InitStatus",
291 GET_STABILITY_FILE_PATH_FAILED, INIT_STATUS_MAX);
292 return;
293 }
294 const std::set<base::FilePath>& excluded_debug_files = {
295 current_stability_file};
296
297 // Create a database. Note: Chrome already has a g_database in crashpad.cc but
298 // it has internal linkage. Create a new one.
299 std::unique_ptr<crashpad::CrashReportDatabase> crashpad_database =
300 crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir_);
301 if (!crashpad_database) {
302 LOG(ERROR) << "Failed to initialize a CrashPad database.";
303 UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.InitStatus",
304 CRASHPAD_DATABASE_INIT_FAILED, INIT_STATUS_MAX);
305 return;
306 }
307 UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.InitStatus",
308 INIT_SUCCESS, INIT_STATUS_MAX);
309
310 // TODO(manzagop): fix incorrect version attribution on update.
311 PostmortemReportCollector collector;
312 collector.CollectAndSubmitForUpload(
313 stability_dir, StabilityDebugging::GetFilePattern(), excluded_debug_files,
314 crashpad_database.get());
315 }
316
234 } // namespace browser_watcher 317 } // namespace browser_watcher
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698