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

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

Issue 2715903003: Bound the impact of system instability on chrome instability. (Closed)
Patch Set: record start timestamp, analysis metric, make log scrape lazy Created 3 years, 9 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/postmortem_report_collector.h" 5 #include "components/browser_watcher/postmortem_report_collector.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/debug/activity_analyzer.h" 9 #include "base/debug/activity_analyzer.h"
10 #include "base/files/file_enumerator.h" 10 #include "base/files/file_enumerator.h"
(...skipping 18 matching lines...) Expand all
29 using base::debug::ActivityUserData; 29 using base::debug::ActivityUserData;
30 using base::debug::GlobalActivityAnalyzer; 30 using base::debug::GlobalActivityAnalyzer;
31 using base::debug::GlobalActivityTracker; 31 using base::debug::GlobalActivityTracker;
32 using base::debug::ThreadActivityAnalyzer; 32 using base::debug::ThreadActivityAnalyzer;
33 using crashpad::CrashReportDatabase; 33 using crashpad::CrashReportDatabase;
34 34
35 namespace { 35 namespace {
36 36
37 const char kFieldTrialKeyPrefix[] = "FieldTrial."; 37 const char kFieldTrialKeyPrefix[] = "FieldTrial.";
38 38
39 // DO NOT CHANGE VALUES. This is logged persistently in a histogram.
40 enum SystemSessionAnalysisStatus {
41 SYSTEM_SESSION_ANALYSIS_SUCCESS = 0,
42 SYSTEM_SESSION_ANALYSIS_NO_TIMESTAMP = 1,
43 SYSTEM_SESSION_ANALYSIS_NO_ANALYZER = 2,
44 SYSTEM_SESSION_ANALYSIS_FAILED = 3,
45 SYSTEM_SESSION_ANALYSIS_OUTSIDE_RANGE = 4,
46 SYSTEM_SESSION_ANALYSIS_STATUS_MAX = 5
47 };
48
39 // Collects stability user data from the recorded format to the collected 49 // Collects stability user data from the recorded format to the collected
40 // format. 50 // format.
41 void CollectUserData( 51 void CollectUserData(
42 const ActivityUserData::Snapshot& recorded_map, 52 const ActivityUserData::Snapshot& recorded_map,
43 google::protobuf::Map<std::string, TypedValue>* collected_map, 53 google::protobuf::Map<std::string, TypedValue>* collected_map,
44 StabilityReport* report) { 54 StabilityReport* report) {
45 DCHECK(collected_map); 55 DCHECK(collected_map);
46 56
47 for (const auto& name_and_value : recorded_map) { 57 for (const auto& name_and_value : recorded_map) {
48 const std::string& key = name_and_value.first; 58 const std::string& key = name_and_value.first;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 break; 118 break;
109 case ActivityUserData::UNSIGNED_VALUE: 119 case ActivityUserData::UNSIGNED_VALUE:
110 collected_value.set_unsigned_value(recorded_value.GetUint()); 120 collected_value.set_unsigned_value(recorded_value.GetUint());
111 break; 121 break;
112 } 122 }
113 123
114 (*collected_map)[key].Swap(&collected_value); 124 (*collected_map)[key].Swap(&collected_value);
115 } 125 }
116 } 126 }
117 127
128 bool GetStartTimestamp(
129 const google::protobuf::Map<std::string, TypedValue>& global_data,
130 base::Time* time) {
131 DCHECK(time);
132
133 const auto& it = global_data.find(kStabilityStartTimestamp);
134 if (it == global_data.end())
135 return false;
136
137 const TypedValue& value = it->second;
138 if (value.value_case() != TypedValue::kSignedValue)
139 return false;
140
141 *time = base::Time::FromInternalValue(value.signed_value());
142 return true;
143 }
144
118 void CollectModuleInformation( 145 void CollectModuleInformation(
119 const std::vector<GlobalActivityTracker::ModuleInfo>& modules, 146 const std::vector<GlobalActivityTracker::ModuleInfo>& modules,
120 ProcessState* process_state) { 147 ProcessState* process_state) {
121 DCHECK(process_state); 148 DCHECK(process_state);
122 149
123 char code_identifier[17]; 150 char code_identifier[17];
124 char debug_identifier[41]; 151 char debug_identifier[41];
125 152
126 for (const GlobalActivityTracker::ModuleInfo& recorded : modules) { 153 for (const GlobalActivityTracker::ModuleInfo& recorded : modules) {
127 CodeModule* collected = process_state->add_modules(); 154 CodeModule* collected = process_state->add_modules();
(...skipping 18 matching lines...) Expand all
146 collected->set_debug_identifier(debug_identifier); 173 collected->set_debug_identifier(debug_identifier);
147 collected->set_is_unloaded(!recorded.is_loaded); 174 collected->set_is_unloaded(!recorded.is_loaded);
148 } 175 }
149 } 176 }
150 177
151 } // namespace 178 } // namespace
152 179
153 PostmortemReportCollector::PostmortemReportCollector( 180 PostmortemReportCollector::PostmortemReportCollector(
154 const std::string& product_name, 181 const std::string& product_name,
155 const std::string& version_number, 182 const std::string& version_number,
156 const std::string& channel_name) 183 const std::string& channel_name,
184 std::unique_ptr<SystemSessionAnalyzer> analyzer)
157 : product_name_(product_name), 185 : product_name_(product_name),
158 version_number_(version_number), 186 version_number_(version_number),
159 channel_name_(channel_name) {} 187 channel_name_(channel_name),
188 system_session_analyzer_(std::move(analyzer)) {}
160 189
161 int PostmortemReportCollector::CollectAndSubmitForUpload( 190 int PostmortemReportCollector::CollectAndSubmitForUpload(
162 const base::FilePath& debug_info_dir, 191 const base::FilePath& debug_info_dir,
163 const base::FilePath::StringType& debug_file_pattern, 192 const base::FilePath::StringType& debug_file_pattern,
164 const std::set<base::FilePath>& excluded_debug_files, 193 const std::set<base::FilePath>& excluded_debug_files,
165 crashpad::CrashReportDatabase* report_database) { 194 crashpad::CrashReportDatabase* report_database) {
166 DCHECK_NE(true, debug_info_dir.empty()); 195 DCHECK_NE(true, debug_info_dir.empty());
167 DCHECK_NE(true, debug_file_pattern.empty()); 196 DCHECK_NE(true, debug_file_pattern.empty());
168 DCHECK_NE(nullptr, report_database); 197 DCHECK_NE(nullptr, report_database);
169 198
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 332
304 // Create the report, then flesh it out. 333 // Create the report, then flesh it out.
305 report->reset(new StabilityReport()); 334 report->reset(new StabilityReport());
306 335
307 // Collect log messages. 336 // Collect log messages.
308 for (const std::string& message : log_messages) { 337 for (const std::string& message : log_messages) {
309 (*report)->add_log_messages(message); 338 (*report)->add_log_messages(message);
310 } 339 }
311 340
312 // Collect global user data. 341 // Collect global user data.
313 google::protobuf::Map<std::string, TypedValue>& global_data = 342 CollectUserData(global_data_snapshot, (*report)->mutable_global_data(),
314 *(*report)->mutable_global_data(); 343 report->get());
315 CollectUserData(global_data_snapshot, &global_data, report->get()); 344 SetReporterDetails(report->get());
316 345 DetermineSystemSate(report->get());
317 // Add the reporting Chrome's details to the report.
318 global_data[kStabilityReporterChannel].set_string_value(channel_name());
319 #if defined(ARCH_CPU_X86)
320 global_data[kStabilityReporterPlatform].set_string_value(
321 std::string("Win32"));
322 #elif defined(ARCH_CPU_X86_64)
323 global_data[kStabilityReporterPlatform].set_string_value(
324 std::string("Win64"));
325 #endif
326 global_data[kStabilityReporterProduct].set_string_value(product_name());
327 global_data[kStabilityReporterVersion].set_string_value(version_number());
328 346
329 // Collect thread activity data. 347 // Collect thread activity data.
330 // Note: a single process is instrumented. 348 // Note: a single process is instrumented.
331 ProcessState* process_state = (*report)->add_process_states(); 349 ProcessState* process_state = (*report)->add_process_states();
332 for (; thread_analyzer != nullptr; 350 for (; thread_analyzer != nullptr;
333 thread_analyzer = global_analyzer->GetNextAnalyzer()) { 351 thread_analyzer = global_analyzer->GetNextAnalyzer()) {
334 // Only valid analyzers are expected per contract of GetFirstAnalyzer / 352 // Only valid analyzers are expected per contract of GetFirstAnalyzer /
335 // GetNextAnalyzer. 353 // GetNextAnalyzer.
336 DCHECK(thread_analyzer->IsValid()); 354 DCHECK(thread_analyzer->IsValid());
337 355
338 if (!process_state->has_process_id()) { 356 if (!process_state->has_process_id()) {
339 process_state->set_process_id( 357 process_state->set_process_id(
340 thread_analyzer->activity_snapshot().process_id); 358 thread_analyzer->activity_snapshot().process_id);
341 } 359 }
342 DCHECK_EQ(thread_analyzer->activity_snapshot().process_id, 360 DCHECK_EQ(thread_analyzer->activity_snapshot().process_id,
343 process_state->process_id()); 361 process_state->process_id());
344 362
345 ThreadState* thread_state = process_state->add_threads(); 363 ThreadState* thread_state = process_state->add_threads();
346 CollectThread(thread_analyzer->activity_snapshot(), thread_state); 364 CollectThread(thread_analyzer->activity_snapshot(), thread_state);
347 } 365 }
348 366
349 // Collect module information. 367 // Collect module information.
350 CollectModuleInformation(global_analyzer->GetModules(), process_state); 368 CollectModuleInformation(global_analyzer->GetModules(), process_state);
351 369
352 return SUCCESS; 370 return SUCCESS;
353 } 371 }
354 372
373 void PostmortemReportCollector::SetReporterDetails(
374 StabilityReport* report) const {
375 DCHECK(report);
376
377 google::protobuf::Map<std::string, TypedValue>& global_data =
378 *(report->mutable_global_data());
379
380 // Reporter version details.
381 global_data[kStabilityReporterChannel].set_string_value(channel_name());
382 #if defined(ARCH_CPU_X86)
383 global_data[kStabilityReporterPlatform].set_string_value(
384 std::string("Win32"));
385 #elif defined(ARCH_CPU_X86_64)
386 global_data[kStabilityReporterPlatform].set_string_value(
387 std::string("Win64"));
388 #endif
389 global_data[kStabilityReporterProduct].set_string_value(product_name());
390 global_data[kStabilityReporterVersion].set_string_value(version_number());
391 }
392
393 void PostmortemReportCollector::DetermineSystemSate(
394 StabilityReport* report) const {
395 DCHECK(report);
396
397 // A session state for the stability report: was the system session clean?
398 SystemState::SessionState session_state = SystemState::UNKNOWN;
399 // An analasis status for metrics: did the analysis succeed?
400 SystemSessionAnalysisStatus status = SYSTEM_SESSION_ANALYSIS_SUCCESS;
401
402 base::Time time;
403 if (!GetStartTimestamp(report->global_data(), &time)) {
404 status = SYSTEM_SESSION_ANALYSIS_NO_TIMESTAMP;
405 } else if (!system_session_analyzer_) {
406 status = SYSTEM_SESSION_ANALYSIS_NO_ANALYZER;
407 } else {
408 SystemSessionAnalyzer::Status analyzer_status =
409 system_session_analyzer_->IsSessionUnclean(time);
410 switch (analyzer_status) {
411 case SystemSessionAnalyzer::FAILED:
412 status = SYSTEM_SESSION_ANALYSIS_FAILED;
413 break;
414 case SystemSessionAnalyzer::CLEAN:
415 session_state = SystemState::CLEAN;
416 break;
417 case SystemSessionAnalyzer::UNCLEAN:
418 session_state = SystemState::UNCLEAN;
419 break;
420 case SystemSessionAnalyzer::OUTSIDE_RANGE:
421 status = SYSTEM_SESSION_ANALYSIS_OUTSIDE_RANGE;
422 break;
423 }
424 }
425
426 report->mutable_system_state()->set_session_state(session_state);
427 UMA_HISTOGRAM_ENUMERATION(
428 "ActivityTracker.Collect.SystemSessionAnalysisStatus", status,
429 SYSTEM_SESSION_ANALYSIS_STATUS_MAX);
430 }
431
355 void PostmortemReportCollector::CollectThread( 432 void PostmortemReportCollector::CollectThread(
356 const base::debug::ThreadActivityAnalyzer::Snapshot& snapshot, 433 const base::debug::ThreadActivityAnalyzer::Snapshot& snapshot,
357 ThreadState* thread_state) { 434 ThreadState* thread_state) {
358 DCHECK(thread_state); 435 DCHECK(thread_state);
359 436
360 thread_state->set_thread_name(snapshot.thread_name); 437 thread_state->set_thread_name(snapshot.thread_name);
361 thread_state->set_thread_id(snapshot.thread_id); 438 thread_state->set_thread_id(snapshot.thread_id);
362 thread_state->set_activity_count(snapshot.activity_stack_depth); 439 thread_state->set_activity_count(snapshot.activity_stack_depth);
363 440
364 for (size_t i = 0; i < snapshot.activity_stack.size(); ++i) { 441 for (size_t i = 0; i < snapshot.activity_stack.size(); ++i) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 StabilityReport* report, 481 StabilityReport* report,
405 const crashpad::UUID& client_id, 482 const crashpad::UUID& client_id,
406 const crashpad::UUID& report_id, 483 const crashpad::UUID& report_id,
407 base::PlatformFile minidump_file) { 484 base::PlatformFile minidump_file) {
408 DCHECK(report); 485 DCHECK(report);
409 486
410 return WritePostmortemDump(minidump_file, client_id, report_id, report); 487 return WritePostmortemDump(minidump_file, client_id, report_id, report);
411 } 488 }
412 489
413 } // namespace browser_watcher 490 } // namespace browser_watcher
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698