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

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

Issue 2583223002: Collect stability data from global and activity scopes (Closed)
Patch Set: Merge Created 3 years, 11 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/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
16 #include "components/browser_watcher/postmortem_minidump_writer.h" 17 #include "components/browser_watcher/postmortem_minidump_writer.h"
17 #include "third_party/crashpad/crashpad/client/settings.h" 18 #include "third_party/crashpad/crashpad/client/settings.h"
18 #include "third_party/crashpad/crashpad/util/misc/uuid.h" 19 #include "third_party/crashpad/crashpad/util/misc/uuid.h"
19 20
20 using base::FilePath; 21 using base::FilePath;
21 22
22 namespace browser_watcher { 23 namespace browser_watcher {
23 24
24 using ActivitySnapshot = base::debug::ThreadActivityAnalyzer::Snapshot; 25 using ActivitySnapshot = base::debug::ThreadActivityAnalyzer::Snapshot;
26 using base::debug::ActivityUserData;
25 using base::debug::GlobalActivityAnalyzer; 27 using base::debug::GlobalActivityAnalyzer;
26 using base::debug::ThreadActivityAnalyzer; 28 using base::debug::ThreadActivityAnalyzer;
27 using crashpad::CrashReportDatabase; 29 using crashpad::CrashReportDatabase;
28 30
31 namespace {
32
33 // Collects stability user data from the recorded format to the collected
34 // format.
35 void CollectUserData(
36 const ActivityUserData::Snapshot& recorded_map,
37 google::protobuf::Map<std::string, TypedValue>* collected_map) {
38 DCHECK(collected_map);
39
40 for (const auto& name_and_value : recorded_map) {
41 const ActivityUserData::TypedValue& recorded_value = name_and_value.second;
42 TypedValue collected_value;
43
44 switch (recorded_value.type()) {
45 case ActivityUserData::END_OF_VALUES:
46 NOTREACHED();
47 break;
48 case ActivityUserData::RAW_VALUE:
49 collected_value.set_bytes_value(recorded_value.Get().as_string());
50 break;
51 case ActivityUserData::RAW_VALUE_REFERENCE: {
52 base::StringPiece recorded_ref = recorded_value.GetReference();
53 TypedValue::Reference* collected_ref =
54 collected_value.mutable_bytes_reference();
55 collected_ref->set_address(
56 reinterpret_cast<uintptr_t>(recorded_ref.data()));
57 collected_ref->set_size(recorded_ref.size());
58 break;
59 }
60 case ActivityUserData::STRING_VALUE:
61 collected_value.set_string_value(
62 recorded_value.GetString().as_string());
63 break;
64 case ActivityUserData::STRING_VALUE_REFERENCE: {
65 base::StringPiece recorded_ref = recorded_value.GetStringReference();
66 TypedValue::Reference* collected_ref =
67 collected_value.mutable_string_reference();
68 collected_ref->set_address(
69 reinterpret_cast<uintptr_t>(recorded_ref.data()));
70 collected_ref->set_size(recorded_ref.size());
71 break;
72 }
73 case ActivityUserData::CHAR_VALUE:
74 collected_value.set_char_value(
75 std::string(1, recorded_value.GetChar()));
76 break;
77 case ActivityUserData::BOOL_VALUE:
78 collected_value.set_bool_value(recorded_value.GetBool());
79 break;
80 case ActivityUserData::SIGNED_VALUE:
81 collected_value.set_signed_value(recorded_value.GetInt());
82 break;
83 case ActivityUserData::UNSIGNED_VALUE:
84 collected_value.set_unsigned_value(recorded_value.GetUint());
85 break;
86 }
87
88 (*collected_map)[name_and_value.first].Swap(&collected_value);
89 }
90 }
91
92 } // namespace
93
29 PostmortemReportCollector::PostmortemReportCollector( 94 PostmortemReportCollector::PostmortemReportCollector(
30 const std::string& product_name, 95 const std::string& product_name,
31 const std::string& version_number, 96 const std::string& version_number,
32 const std::string& channel_name) 97 const std::string& channel_name)
33 : product_name_(product_name), 98 : product_name_(product_name),
34 version_number_(version_number), 99 version_number_(version_number),
35 channel_name_(channel_name) {} 100 channel_name_(channel_name) {}
36 101
37 int PostmortemReportCollector::CollectAndSubmitForUpload( 102 int PostmortemReportCollector::CollectAndSubmitForUpload(
38 const base::FilePath& debug_info_dir, 103 const base::FilePath& debug_info_dir,
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 report->reset(); 227 report->reset();
163 228
164 // Create a global analyzer. 229 // Create a global analyzer.
165 std::unique_ptr<GlobalActivityAnalyzer> global_analyzer = 230 std::unique_ptr<GlobalActivityAnalyzer> global_analyzer =
166 GlobalActivityAnalyzer::CreateWithFile(debug_state_file); 231 GlobalActivityAnalyzer::CreateWithFile(debug_state_file);
167 if (!global_analyzer) 232 if (!global_analyzer)
168 return ANALYZER_CREATION_FAILED; 233 return ANALYZER_CREATION_FAILED;
169 234
170 // Early exit if there is no data. 235 // Early exit if there is no data.
171 std::vector<std::string> log_messages = global_analyzer->GetLogMessages(); 236 std::vector<std::string> log_messages = global_analyzer->GetLogMessages();
237 ActivityUserData::Snapshot global_data_snapshot =
238 global_analyzer->GetGlobalUserDataSnapshot();
172 ThreadActivityAnalyzer* thread_analyzer = global_analyzer->GetFirstAnalyzer(); 239 ThreadActivityAnalyzer* thread_analyzer = global_analyzer->GetFirstAnalyzer();
173 if (log_messages.empty() && !thread_analyzer) { 240 if (log_messages.empty() && global_data_snapshot.empty() &&
241 !thread_analyzer) {
174 return DEBUG_FILE_NO_DATA; 242 return DEBUG_FILE_NO_DATA;
175 } 243 }
176 244
177 // Create the report, then flesh it out. 245 // Create the report, then flesh it out.
178 report->reset(new StabilityReport()); 246 report->reset(new StabilityReport());
179 247
180 // Collect log messages. 248 // Collect log messages.
181 for (const std::string& message : log_messages) { 249 for (const std::string& message : log_messages) {
182 (*report)->add_log_messages(message); 250 (*report)->add_log_messages(message);
183 } 251 }
184 252
253 // Collect global user data.
254 CollectUserData(global_data_snapshot, (*report)->mutable_global_data());
255
185 // Collect thread activity data. 256 // Collect thread activity data.
186 // Note: a single process is instrumented. 257 // Note: a single process is instrumented.
187 ProcessState* process_state = (*report)->add_process_states(); 258 ProcessState* process_state = (*report)->add_process_states();
188 for (; thread_analyzer != nullptr; 259 for (; thread_analyzer != nullptr;
189 thread_analyzer = global_analyzer->GetNextAnalyzer()) { 260 thread_analyzer = global_analyzer->GetNextAnalyzer()) {
190 // Only valid analyzers are expected per contract of GetFirstAnalyzer / 261 // Only valid analyzers are expected per contract of GetFirstAnalyzer /
191 // GetNextAnalyzer. 262 // GetNextAnalyzer.
192 DCHECK(thread_analyzer->IsValid()); 263 DCHECK(thread_analyzer->IsValid());
193 264
194 if (!process_state->has_process_id()) { 265 if (!process_state->has_process_id()) {
(...skipping 12 matching lines...) Expand all
207 278
208 void PostmortemReportCollector::CollectThread( 279 void PostmortemReportCollector::CollectThread(
209 const base::debug::ThreadActivityAnalyzer::Snapshot& snapshot, 280 const base::debug::ThreadActivityAnalyzer::Snapshot& snapshot,
210 ThreadState* thread_state) { 281 ThreadState* thread_state) {
211 DCHECK(thread_state); 282 DCHECK(thread_state);
212 283
213 thread_state->set_thread_name(snapshot.thread_name); 284 thread_state->set_thread_name(snapshot.thread_name);
214 thread_state->set_thread_id(snapshot.thread_id); 285 thread_state->set_thread_id(snapshot.thread_id);
215 thread_state->set_activity_count(snapshot.activity_stack_depth); 286 thread_state->set_activity_count(snapshot.activity_stack_depth);
216 287
217 for (const base::debug::Activity& recorded : snapshot.activity_stack) { 288 for (size_t i = 0; i < snapshot.activity_stack.size(); ++i) {
289 const base::debug::Activity& recorded = snapshot.activity_stack[i];
218 Activity* collected = thread_state->add_activities(); 290 Activity* collected = thread_state->add_activities();
291
292 // Collect activity
219 switch (recorded.activity_type) { 293 switch (recorded.activity_type) {
220 case base::debug::Activity::ACT_TASK_RUN: 294 case base::debug::Activity::ACT_TASK_RUN:
221 collected->set_type(Activity::ACT_TASK_RUN); 295 collected->set_type(Activity::ACT_TASK_RUN);
222 collected->set_origin_address(recorded.origin_address); 296 collected->set_origin_address(recorded.origin_address);
223 collected->set_task_sequence_id(recorded.data.task.sequence_id); 297 collected->set_task_sequence_id(recorded.data.task.sequence_id);
224 break; 298 break;
225 case base::debug::Activity::ACT_LOCK_ACQUIRE: 299 case base::debug::Activity::ACT_LOCK_ACQUIRE:
226 collected->set_type(Activity::ACT_LOCK_ACQUIRE); 300 collected->set_type(Activity::ACT_LOCK_ACQUIRE);
227 collected->set_lock_address(recorded.data.lock.lock_address); 301 collected->set_lock_address(recorded.data.lock.lock_address);
228 break; 302 break;
229 case base::debug::Activity::ACT_EVENT_WAIT: 303 case base::debug::Activity::ACT_EVENT_WAIT:
230 collected->set_type(Activity::ACT_EVENT_WAIT); 304 collected->set_type(Activity::ACT_EVENT_WAIT);
231 collected->set_event_address(recorded.data.event.event_address); 305 collected->set_event_address(recorded.data.event.event_address);
232 break; 306 break;
233 case base::debug::Activity::ACT_THREAD_JOIN: 307 case base::debug::Activity::ACT_THREAD_JOIN:
234 collected->set_type(Activity::ACT_THREAD_JOIN); 308 collected->set_type(Activity::ACT_THREAD_JOIN);
235 collected->set_thread_id(recorded.data.thread.thread_id); 309 collected->set_thread_id(recorded.data.thread.thread_id);
236 break; 310 break;
237 case base::debug::Activity::ACT_PROCESS_WAIT: 311 case base::debug::Activity::ACT_PROCESS_WAIT:
238 collected->set_type(Activity::ACT_PROCESS_WAIT); 312 collected->set_type(Activity::ACT_PROCESS_WAIT);
239 collected->set_process_id(recorded.data.process.process_id); 313 collected->set_process_id(recorded.data.process.process_id);
240 break; 314 break;
241 default: 315 default:
242 break; 316 break;
243 } 317 }
318
319 // Collect user data
320 if (i < snapshot.user_data_stack.size()) {
321 CollectUserData(snapshot.user_data_stack[i],
322 collected->mutable_user_data());
323 }
244 } 324 }
245 } 325 }
246 326
247 bool PostmortemReportCollector::WriteReportToMinidump( 327 bool PostmortemReportCollector::WriteReportToMinidump(
248 const StabilityReport& report, 328 const StabilityReport& report,
249 const crashpad::UUID& client_id, 329 const crashpad::UUID& client_id,
250 const crashpad::UUID& report_id, 330 const crashpad::UUID& report_id,
251 base::PlatformFile minidump_file) { 331 base::PlatformFile minidump_file) {
252 MinidumpInfo minidump_info; 332 MinidumpInfo minidump_info;
253 minidump_info.client_id = client_id; 333 minidump_info.client_id = client_id;
254 minidump_info.report_id = report_id; 334 minidump_info.report_id = report_id;
255 // TODO(manzagop): replace this information, i.e. the reporter's attributes, 335 // TODO(manzagop): replace this information, i.e. the reporter's attributes,
256 // by that of the reportee. Doing so requires adding this information to the 336 // by that of the reportee. Doing so requires adding this information to the
257 // stability report. In the meantime, there is a tolerable information 337 // stability report. In the meantime, there is a tolerable information
258 // mismatch after upgrades. 338 // mismatch after upgrades.
259 minidump_info.product_name = product_name(); 339 minidump_info.product_name = product_name();
260 minidump_info.version_number = version_number(); 340 minidump_info.version_number = version_number();
261 minidump_info.channel_name = channel_name(); 341 minidump_info.channel_name = channel_name();
262 #if defined(ARCH_CPU_X86) 342 #if defined(ARCH_CPU_X86)
263 minidump_info.platform = std::string("Win32"); 343 minidump_info.platform = std::string("Win32");
264 #elif defined(ARCH_CPU_X86_64) 344 #elif defined(ARCH_CPU_X86_64)
265 minidump_info.platform = std::string("Win64"); 345 minidump_info.platform = std::string("Win64");
266 #endif 346 #endif
267 347
268 return WritePostmortemDump(minidump_file, report, minidump_info); 348 return WritePostmortemDump(minidump_file, report, minidump_info);
269 } 349 }
270 350
271 } // namespace browser_watcher 351 } // namespace browser_watcher
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698