Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 15 #include "base/strings/string_piece.h" | 15 #include "base/strings/string_piece.h" |
| 16 #include "base/strings/string_util.h" | |
| 16 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 17 #include "components/browser_watcher/postmortem_minidump_writer.h" | 18 #include "components/browser_watcher/postmortem_minidump_writer.h" |
| 18 #include "components/browser_watcher/stability_data_names.h" | 19 #include "components/browser_watcher/stability_data_names.h" |
| 20 #include "components/variations/active_field_trials.h" | |
| 19 #include "third_party/crashpad/crashpad/client/settings.h" | 21 #include "third_party/crashpad/crashpad/client/settings.h" |
| 20 #include "third_party/crashpad/crashpad/util/misc/uuid.h" | 22 #include "third_party/crashpad/crashpad/util/misc/uuid.h" |
| 21 | 23 |
| 22 using base::FilePath; | 24 using base::FilePath; |
| 23 | 25 |
| 24 namespace browser_watcher { | 26 namespace browser_watcher { |
| 25 | 27 |
| 26 using ActivitySnapshot = base::debug::ThreadActivityAnalyzer::Snapshot; | 28 using ActivitySnapshot = base::debug::ThreadActivityAnalyzer::Snapshot; |
| 27 using base::debug::ActivityUserData; | 29 using base::debug::ActivityUserData; |
| 28 using base::debug::GlobalActivityAnalyzer; | 30 using base::debug::GlobalActivityAnalyzer; |
| 29 using base::debug::GlobalActivityTracker; | 31 using base::debug::GlobalActivityTracker; |
| 30 using base::debug::ThreadActivityAnalyzer; | 32 using base::debug::ThreadActivityAnalyzer; |
| 31 using crashpad::CrashReportDatabase; | 33 using crashpad::CrashReportDatabase; |
| 32 | 34 |
| 33 namespace { | 35 namespace { |
| 34 | 36 |
| 37 const char kFieldTrialKeyPrefix[] = "FieldTrial."; | |
| 38 | |
| 35 // Collects stability user data from the recorded format to the collected | 39 // Collects stability user data from the recorded format to the collected |
| 36 // format. | 40 // format. |
| 37 void CollectUserData( | 41 void CollectUserData( |
| 38 const ActivityUserData::Snapshot& recorded_map, | 42 const ActivityUserData::Snapshot& recorded_map, |
| 39 google::protobuf::Map<std::string, TypedValue>* collected_map) { | 43 google::protobuf::Map<std::string, TypedValue>* collected_map, |
| 44 StabilityReport* report) { | |
| 40 DCHECK(collected_map); | 45 DCHECK(collected_map); |
| 41 | 46 |
| 42 for (const auto& name_and_value : recorded_map) { | 47 for (const auto& name_and_value : recorded_map) { |
| 48 const std::string& key = name_and_value.first; | |
| 43 const ActivityUserData::TypedValue& recorded_value = name_and_value.second; | 49 const ActivityUserData::TypedValue& recorded_value = name_and_value.second; |
| 44 TypedValue collected_value; | 50 TypedValue collected_value; |
| 45 | 51 |
| 46 switch (recorded_value.type()) { | 52 switch (recorded_value.type()) { |
| 47 case ActivityUserData::END_OF_VALUES: | 53 case ActivityUserData::END_OF_VALUES: |
| 48 NOTREACHED(); | 54 NOTREACHED(); |
| 49 break; | 55 break; |
| 50 case ActivityUserData::RAW_VALUE: | 56 case ActivityUserData::RAW_VALUE: { |
| 51 collected_value.set_bytes_value(recorded_value.Get().as_string()); | 57 base::StringPiece raw = recorded_value.Get(); |
| 58 collected_value.set_bytes_value(raw.data(), raw.size()); | |
| 52 break; | 59 break; |
| 60 } | |
| 53 case ActivityUserData::RAW_VALUE_REFERENCE: { | 61 case ActivityUserData::RAW_VALUE_REFERENCE: { |
| 54 base::StringPiece recorded_ref = recorded_value.GetReference(); | 62 base::StringPiece recorded_ref = recorded_value.GetReference(); |
| 55 TypedValue::Reference* collected_ref = | 63 TypedValue::Reference* collected_ref = |
| 56 collected_value.mutable_bytes_reference(); | 64 collected_value.mutable_bytes_reference(); |
| 57 collected_ref->set_address( | 65 collected_ref->set_address( |
| 58 reinterpret_cast<uintptr_t>(recorded_ref.data())); | 66 reinterpret_cast<uintptr_t>(recorded_ref.data())); |
| 59 collected_ref->set_size(recorded_ref.size()); | 67 collected_ref->set_size(recorded_ref.size()); |
| 60 break; | 68 break; |
| 61 } | 69 } |
| 62 case ActivityUserData::STRING_VALUE: | 70 case ActivityUserData::STRING_VALUE: { |
| 63 collected_value.set_string_value( | 71 base::StringPiece value = recorded_value.GetString(); |
| 64 recorded_value.GetString().as_string()); | 72 |
| 73 if (report && base::StartsWith(key, kFieldTrialKeyPrefix, | |
| 74 base::CompareCase::SENSITIVE)) { | |
| 75 // This entry represents an active Finch experiment. | |
|
rkaplow
2017/02/16 21:27:28
nit, use Field Trial in chromium-land
manzagop (departed)
2017/02/17 22:20:05
Done.
| |
| 76 std::string trial_name = | |
| 77 key.substr(std::strlen(kFieldTrialKeyPrefix)); | |
| 78 variations::ActiveGroupId group_id = | |
| 79 variations::MakeActiveGroupId(trial_name, value.as_string()); | |
| 80 FieldTrial* field_trial = report->add_field_trials(); | |
| 81 field_trial->set_name_id(group_id.name); | |
| 82 field_trial->set_group_id(group_id.group); | |
| 83 continue; | |
| 84 } | |
| 85 | |
| 86 collected_value.set_string_value(value.data(), value.size()); | |
| 65 break; | 87 break; |
| 88 } | |
| 66 case ActivityUserData::STRING_VALUE_REFERENCE: { | 89 case ActivityUserData::STRING_VALUE_REFERENCE: { |
| 67 base::StringPiece recorded_ref = recorded_value.GetStringReference(); | 90 base::StringPiece recorded_ref = recorded_value.GetStringReference(); |
| 68 TypedValue::Reference* collected_ref = | 91 TypedValue::Reference* collected_ref = |
| 69 collected_value.mutable_string_reference(); | 92 collected_value.mutable_string_reference(); |
| 70 collected_ref->set_address( | 93 collected_ref->set_address( |
| 71 reinterpret_cast<uintptr_t>(recorded_ref.data())); | 94 reinterpret_cast<uintptr_t>(recorded_ref.data())); |
| 72 collected_ref->set_size(recorded_ref.size()); | 95 collected_ref->set_size(recorded_ref.size()); |
| 73 break; | 96 break; |
| 74 } | 97 } |
| 75 case ActivityUserData::CHAR_VALUE: | 98 case ActivityUserData::CHAR_VALUE: { |
| 76 collected_value.set_char_value( | 99 char char_value = recorded_value.GetChar(); |
| 77 std::string(1, recorded_value.GetChar())); | 100 collected_value.set_char_value(&char_value, 1); |
| 78 break; | 101 break; |
| 102 } | |
| 79 case ActivityUserData::BOOL_VALUE: | 103 case ActivityUserData::BOOL_VALUE: |
| 80 collected_value.set_bool_value(recorded_value.GetBool()); | 104 collected_value.set_bool_value(recorded_value.GetBool()); |
| 81 break; | 105 break; |
| 82 case ActivityUserData::SIGNED_VALUE: | 106 case ActivityUserData::SIGNED_VALUE: |
| 83 collected_value.set_signed_value(recorded_value.GetInt()); | 107 collected_value.set_signed_value(recorded_value.GetInt()); |
| 84 break; | 108 break; |
| 85 case ActivityUserData::UNSIGNED_VALUE: | 109 case ActivityUserData::UNSIGNED_VALUE: |
| 86 collected_value.set_unsigned_value(recorded_value.GetUint()); | 110 collected_value.set_unsigned_value(recorded_value.GetUint()); |
| 87 break; | 111 break; |
| 88 } | 112 } |
| 89 | 113 |
| 90 (*collected_map)[name_and_value.first].Swap(&collected_value); | 114 (*collected_map)[key].Swap(&collected_value); |
| 91 } | 115 } |
| 92 } | 116 } |
| 93 | 117 |
| 94 void CollectModuleInformation( | 118 void CollectModuleInformation( |
| 95 const std::vector<GlobalActivityTracker::ModuleInfo>& modules, | 119 const std::vector<GlobalActivityTracker::ModuleInfo>& modules, |
| 96 ProcessState* process_state) { | 120 ProcessState* process_state) { |
| 97 DCHECK(process_state); | 121 DCHECK(process_state); |
| 98 | 122 |
| 99 char code_identifier[17]; | 123 char code_identifier[17]; |
| 100 char debug_identifier[41]; | 124 char debug_identifier[41]; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 report->reset(new StabilityReport()); | 305 report->reset(new StabilityReport()); |
| 282 | 306 |
| 283 // Collect log messages. | 307 // Collect log messages. |
| 284 for (const std::string& message : log_messages) { | 308 for (const std::string& message : log_messages) { |
| 285 (*report)->add_log_messages(message); | 309 (*report)->add_log_messages(message); |
| 286 } | 310 } |
| 287 | 311 |
| 288 // Collect global user data. | 312 // Collect global user data. |
| 289 google::protobuf::Map<std::string, TypedValue>& global_data = | 313 google::protobuf::Map<std::string, TypedValue>& global_data = |
| 290 *(*report)->mutable_global_data(); | 314 *(*report)->mutable_global_data(); |
| 291 CollectUserData(global_data_snapshot, &global_data); | 315 CollectUserData(global_data_snapshot, &global_data, report->get()); |
| 292 | 316 |
| 293 // Add the reporting Chrome's details to the report. | 317 // Add the reporting Chrome's details to the report. |
| 294 global_data[kStabilityReporterChannel].set_string_value(channel_name()); | 318 global_data[kStabilityReporterChannel].set_string_value(channel_name()); |
| 295 #if defined(ARCH_CPU_X86) | 319 #if defined(ARCH_CPU_X86) |
| 296 global_data[kStabilityReporterPlatform].set_string_value( | 320 global_data[kStabilityReporterPlatform].set_string_value( |
| 297 std::string("Win32")); | 321 std::string("Win32")); |
| 298 #elif defined(ARCH_CPU_X86_64) | 322 #elif defined(ARCH_CPU_X86_64) |
| 299 global_data[kStabilityReporterPlatform].set_string_value( | 323 global_data[kStabilityReporterPlatform].set_string_value( |
| 300 std::string("Win64")); | 324 std::string("Win64")); |
| 301 #endif | 325 #endif |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 collected->set_type(Activity::ACT_PROCESS_WAIT); | 388 collected->set_type(Activity::ACT_PROCESS_WAIT); |
| 365 collected->set_process_id(recorded.data.process.process_id); | 389 collected->set_process_id(recorded.data.process.process_id); |
| 366 break; | 390 break; |
| 367 default: | 391 default: |
| 368 break; | 392 break; |
| 369 } | 393 } |
| 370 | 394 |
| 371 // Collect user data | 395 // Collect user data |
| 372 if (i < snapshot.user_data_stack.size()) { | 396 if (i < snapshot.user_data_stack.size()) { |
| 373 CollectUserData(snapshot.user_data_stack[i], | 397 CollectUserData(snapshot.user_data_stack[i], |
| 374 collected->mutable_user_data()); | 398 collected->mutable_user_data(), nullptr); |
| 375 } | 399 } |
| 376 } | 400 } |
| 377 } | 401 } |
| 378 | 402 |
| 379 bool PostmortemReportCollector::WriteReportToMinidump( | 403 bool PostmortemReportCollector::WriteReportToMinidump( |
| 380 StabilityReport* report, | 404 StabilityReport* report, |
| 381 const crashpad::UUID& client_id, | 405 const crashpad::UUID& client_id, |
| 382 const crashpad::UUID& report_id, | 406 const crashpad::UUID& report_id, |
| 383 base::PlatformFile minidump_file) { | 407 base::PlatformFile minidump_file) { |
| 384 DCHECK(report); | 408 DCHECK(report); |
| 385 | 409 |
| 386 return WritePostmortemDump(minidump_file, client_id, report_id, report); | 410 return WritePostmortemDump(minidump_file, client_id, report_id, report); |
| 387 } | 411 } |
| 388 | 412 |
| 389 } // namespace browser_watcher | 413 } // namespace browser_watcher |
| OLD | NEW |