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

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

Issue 2691033002: Collect field trial information from the stability file (Closed)
Patch Set: Merge Created 3 years, 10 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"
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"
19 #include "components/variations/active_field_trials.h"
18 #include "third_party/crashpad/crashpad/client/settings.h" 20 #include "third_party/crashpad/crashpad/client/settings.h"
19 #include "third_party/crashpad/crashpad/util/misc/uuid.h" 21 #include "third_party/crashpad/crashpad/util/misc/uuid.h"
20 22
21 using base::FilePath; 23 using base::FilePath;
22 24
23 namespace browser_watcher { 25 namespace browser_watcher {
24 26
25 using ActivitySnapshot = base::debug::ThreadActivityAnalyzer::Snapshot; 27 using ActivitySnapshot = base::debug::ThreadActivityAnalyzer::Snapshot;
26 using base::debug::ActivityUserData; 28 using base::debug::ActivityUserData;
27 using base::debug::GlobalActivityAnalyzer; 29 using base::debug::GlobalActivityAnalyzer;
28 using base::debug::GlobalActivityTracker; 30 using base::debug::GlobalActivityTracker;
29 using base::debug::ThreadActivityAnalyzer; 31 using base::debug::ThreadActivityAnalyzer;
30 using crashpad::CrashReportDatabase; 32 using crashpad::CrashReportDatabase;
31 33
32 namespace { 34 namespace {
33 35
36 const char kFieldTrialKeyPrefix[] = "FieldTrial.";
37
34 // Collects stability user data from the recorded format to the collected 38 // Collects stability user data from the recorded format to the collected
35 // format. 39 // format.
36 void CollectUserData( 40 void CollectUserData(
37 const ActivityUserData::Snapshot& recorded_map, 41 const ActivityUserData::Snapshot& recorded_map,
38 google::protobuf::Map<std::string, TypedValue>* collected_map) { 42 google::protobuf::Map<std::string, TypedValue>* collected_map,
43 StabilityReport* report) {
39 DCHECK(collected_map); 44 DCHECK(collected_map);
40 45
41 for (const auto& name_and_value : recorded_map) { 46 for (const auto& name_and_value : recorded_map) {
47 const std::string& key = name_and_value.first;
42 const ActivityUserData::TypedValue& recorded_value = name_and_value.second; 48 const ActivityUserData::TypedValue& recorded_value = name_and_value.second;
43 TypedValue collected_value; 49 TypedValue collected_value;
44 50
45 switch (recorded_value.type()) { 51 switch (recorded_value.type()) {
46 case ActivityUserData::END_OF_VALUES: 52 case ActivityUserData::END_OF_VALUES:
47 NOTREACHED(); 53 NOTREACHED();
48 break; 54 break;
49 case ActivityUserData::RAW_VALUE: 55 case ActivityUserData::RAW_VALUE:
50 collected_value.set_bytes_value(recorded_value.Get().as_string()); 56 collected_value.set_bytes_value(recorded_value.Get().as_string());
51 break; 57 break;
52 case ActivityUserData::RAW_VALUE_REFERENCE: { 58 case ActivityUserData::RAW_VALUE_REFERENCE: {
53 base::StringPiece recorded_ref = recorded_value.GetReference(); 59 base::StringPiece recorded_ref = recorded_value.GetReference();
54 TypedValue::Reference* collected_ref = 60 TypedValue::Reference* collected_ref =
55 collected_value.mutable_bytes_reference(); 61 collected_value.mutable_bytes_reference();
56 collected_ref->set_address( 62 collected_ref->set_address(
57 reinterpret_cast<uintptr_t>(recorded_ref.data())); 63 reinterpret_cast<uintptr_t>(recorded_ref.data()));
58 collected_ref->set_size(recorded_ref.size()); 64 collected_ref->set_size(recorded_ref.size());
59 break; 65 break;
60 } 66 }
61 case ActivityUserData::STRING_VALUE: 67 case ActivityUserData::STRING_VALUE: {
62 collected_value.set_string_value( 68 std::string value = recorded_value.GetString().as_string();
63 recorded_value.GetString().as_string()); 69
70 if (report && base::StartsWith(key, kFieldTrialKeyPrefix,
bcwhite 2017/02/14 15:42:14 To be clear, you want field-trial strings to go in
manzagop (departed) 2017/02/14 19:21:15 Yeah, this is clunky. I'm using this function to c
bcwhite 2017/02/14 21:05:16 On the second pass, do you want the field trials t
manzagop (departed) 2017/02/14 21:27:57 Not sure I follow: what's the second pass? Do you
bcwhite 2017/02/15 16:24:19 You said that "in the second I don't have one" so
manzagop (departed) 2017/02/15 18:35:07 Acknowledged.
71 base::CompareCase::SENSITIVE)) {
72 // This entry represents an active Finch experiment.
73 std::string trial_name =
74 key.substr(std::strlen(kFieldTrialKeyPrefix));
75 variations::ActiveGroupId group_id =
76 variations::MakeActiveGroupId(trial_name, value);
77 FieldTrial* field_trial = report->add_field_trials();
78 field_trial->set_name_id(group_id.name);
79 field_trial->set_group_id(group_id.group);
80 continue;
81 }
82
83 collected_value.set_string_value(value);
bcwhite 2017/02/14 15:42:14 I believe set_string_value will accept (char*, len
manzagop (departed) 2017/02/14 19:21:15 Nice! Ah, but MakeActiveGroupId wants a string. St
64 break; 84 break;
85 }
65 case ActivityUserData::STRING_VALUE_REFERENCE: { 86 case ActivityUserData::STRING_VALUE_REFERENCE: {
66 base::StringPiece recorded_ref = recorded_value.GetStringReference(); 87 base::StringPiece recorded_ref = recorded_value.GetStringReference();
67 TypedValue::Reference* collected_ref = 88 TypedValue::Reference* collected_ref =
68 collected_value.mutable_string_reference(); 89 collected_value.mutable_string_reference();
69 collected_ref->set_address( 90 collected_ref->set_address(
70 reinterpret_cast<uintptr_t>(recorded_ref.data())); 91 reinterpret_cast<uintptr_t>(recorded_ref.data()));
71 collected_ref->set_size(recorded_ref.size()); 92 collected_ref->set_size(recorded_ref.size());
72 break; 93 break;
73 } 94 }
74 case ActivityUserData::CHAR_VALUE: 95 case ActivityUserData::CHAR_VALUE:
75 collected_value.set_char_value( 96 collected_value.set_char_value(
76 std::string(1, recorded_value.GetChar())); 97 std::string(1, recorded_value.GetChar()));
77 break; 98 break;
78 case ActivityUserData::BOOL_VALUE: 99 case ActivityUserData::BOOL_VALUE:
79 collected_value.set_bool_value(recorded_value.GetBool()); 100 collected_value.set_bool_value(recorded_value.GetBool());
80 break; 101 break;
81 case ActivityUserData::SIGNED_VALUE: 102 case ActivityUserData::SIGNED_VALUE:
82 collected_value.set_signed_value(recorded_value.GetInt()); 103 collected_value.set_signed_value(recorded_value.GetInt());
83 break; 104 break;
84 case ActivityUserData::UNSIGNED_VALUE: 105 case ActivityUserData::UNSIGNED_VALUE:
85 collected_value.set_unsigned_value(recorded_value.GetUint()); 106 collected_value.set_unsigned_value(recorded_value.GetUint());
86 break; 107 break;
87 } 108 }
88 109
89 (*collected_map)[name_and_value.first].Swap(&collected_value); 110 (*collected_map)[key].Swap(&collected_value);
90 } 111 }
91 } 112 }
92 113
93 void CollectModuleInformation( 114 void CollectModuleInformation(
94 const std::vector<GlobalActivityTracker::ModuleInfo>& modules, 115 const std::vector<GlobalActivityTracker::ModuleInfo>& modules,
95 ProcessState* process_state) { 116 ProcessState* process_state) {
96 DCHECK(process_state); 117 DCHECK(process_state);
97 118
98 char code_identifier[17]; 119 char code_identifier[17];
99 char debug_identifier[41]; 120 char debug_identifier[41];
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 299
279 // Create the report, then flesh it out. 300 // Create the report, then flesh it out.
280 report->reset(new StabilityReport()); 301 report->reset(new StabilityReport());
281 302
282 // Collect log messages. 303 // Collect log messages.
283 for (const std::string& message : log_messages) { 304 for (const std::string& message : log_messages) {
284 (*report)->add_log_messages(message); 305 (*report)->add_log_messages(message);
285 } 306 }
286 307
287 // Collect global user data. 308 // Collect global user data.
288 CollectUserData(global_data_snapshot, (*report)->mutable_global_data()); 309 CollectUserData(global_data_snapshot, (*report)->mutable_global_data(),
310 report->get());
289 311
290 // Collect thread activity data. 312 // Collect thread activity data.
291 // Note: a single process is instrumented. 313 // Note: a single process is instrumented.
292 ProcessState* process_state = (*report)->add_process_states(); 314 ProcessState* process_state = (*report)->add_process_states();
293 for (; thread_analyzer != nullptr; 315 for (; thread_analyzer != nullptr;
294 thread_analyzer = global_analyzer->GetNextAnalyzer()) { 316 thread_analyzer = global_analyzer->GetNextAnalyzer()) {
295 // Only valid analyzers are expected per contract of GetFirstAnalyzer / 317 // Only valid analyzers are expected per contract of GetFirstAnalyzer /
296 // GetNextAnalyzer. 318 // GetNextAnalyzer.
297 DCHECK(thread_analyzer->IsValid()); 319 DCHECK(thread_analyzer->IsValid());
298 320
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 collected->set_type(Activity::ACT_PROCESS_WAIT); 371 collected->set_type(Activity::ACT_PROCESS_WAIT);
350 collected->set_process_id(recorded.data.process.process_id); 372 collected->set_process_id(recorded.data.process.process_id);
351 break; 373 break;
352 default: 374 default:
353 break; 375 break;
354 } 376 }
355 377
356 // Collect user data 378 // Collect user data
357 if (i < snapshot.user_data_stack.size()) { 379 if (i < snapshot.user_data_stack.size()) {
358 CollectUserData(snapshot.user_data_stack[i], 380 CollectUserData(snapshot.user_data_stack[i],
359 collected->mutable_user_data()); 381 collected->mutable_user_data(), nullptr);
360 } 382 }
361 } 383 }
362 } 384 }
363 385
364 bool PostmortemReportCollector::WriteReportToMinidump( 386 bool PostmortemReportCollector::WriteReportToMinidump(
365 const StabilityReport& report, 387 const StabilityReport& report,
366 const crashpad::UUID& client_id, 388 const crashpad::UUID& client_id,
367 const crashpad::UUID& report_id, 389 const crashpad::UUID& report_id,
368 base::PlatformFile minidump_file) { 390 base::PlatformFile minidump_file) {
369 MinidumpInfo minidump_info; 391 MinidumpInfo minidump_info;
370 minidump_info.client_id = client_id; 392 minidump_info.client_id = client_id;
371 minidump_info.report_id = report_id; 393 minidump_info.report_id = report_id;
372 // TODO(manzagop): replace this information, i.e. the reporter's attributes, 394 // TODO(manzagop): replace this information, i.e. the reporter's attributes,
373 // by that of the reportee. Doing so requires adding this information to the 395 // by that of the reportee. Doing so requires adding this information to the
374 // stability report. In the meantime, there is a tolerable information 396 // stability report. In the meantime, there is a tolerable information
375 // mismatch after upgrades. 397 // mismatch after upgrades.
376 minidump_info.product_name = product_name(); 398 minidump_info.product_name = product_name();
377 minidump_info.version_number = version_number(); 399 minidump_info.version_number = version_number();
378 minidump_info.channel_name = channel_name(); 400 minidump_info.channel_name = channel_name();
379 #if defined(ARCH_CPU_X86) 401 #if defined(ARCH_CPU_X86)
380 minidump_info.platform = std::string("Win32"); 402 minidump_info.platform = std::string("Win32");
381 #elif defined(ARCH_CPU_X86_64) 403 #elif defined(ARCH_CPU_X86_64)
382 minidump_info.platform = std::string("Win64"); 404 minidump_info.platform = std::string("Win64");
383 #endif 405 #endif
384 406
385 return WritePostmortemDump(minidump_file, report, minidump_info); 407 return WritePostmortemDump(minidump_file, report, minidump_info);
386 } 408 }
387 409
388 } // namespace browser_watcher 410 } // namespace browser_watcher
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698