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/stability_report_extractor.h" | 5 #include "components/browser_watcher/stability_report_extractor.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 key.substr(std::strlen(kFieldTrialKeyPrefix)); | 72 key.substr(std::strlen(kFieldTrialKeyPrefix)); |
73 variations::ActiveGroupId group_id = | 73 variations::ActiveGroupId group_id = |
74 variations::MakeActiveGroupId(trial_name, value.as_string()); | 74 variations::MakeActiveGroupId(trial_name, value.as_string()); |
75 FieldTrial* field_trial = report->add_field_trials(); | 75 FieldTrial* field_trial = report->add_field_trials(); |
76 field_trial->set_name_id(group_id.name); | 76 field_trial->set_name_id(group_id.name); |
77 field_trial->set_group_id(group_id.group); | 77 field_trial->set_group_id(group_id.group); |
78 continue; | 78 continue; |
79 } | 79 } |
80 | 80 |
81 collected_value.set_string_value(value.data(), value.size()); | 81 collected_value.set_string_value(value.data(), value.size()); |
| 82 |
| 83 // Promote version information to the global key value store. |
| 84 if (report) { |
| 85 bool should_promote = |
| 86 key == kStabilityProduct || key == kStabilityChannel || |
| 87 key == kStabilityPlatform || key == kStabilityVersion; |
| 88 if (should_promote) { |
| 89 (*report->mutable_global_data())[key].Swap(&collected_value); |
| 90 continue; |
| 91 } |
| 92 } |
| 93 |
82 break; | 94 break; |
83 } | 95 } |
84 case ActivityUserData::STRING_VALUE_REFERENCE: { | 96 case ActivityUserData::STRING_VALUE_REFERENCE: { |
85 base::StringPiece recorded_ref = recorded_value.GetStringReference(); | 97 base::StringPiece recorded_ref = recorded_value.GetStringReference(); |
86 TypedValue::Reference* collected_ref = | 98 TypedValue::Reference* collected_ref = |
87 collected_value.mutable_string_reference(); | 99 collected_value.mutable_string_reference(); |
88 collected_ref->set_address( | 100 collected_ref->set_address( |
89 reinterpret_cast<uintptr_t>(recorded_ref.data())); | 101 reinterpret_cast<uintptr_t>(recorded_ref.data())); |
90 collected_ref->set_size(recorded_ref.size()); | 102 collected_ref->set_size(recorded_ref.size()); |
91 break; | 103 break; |
92 } | 104 } |
93 case ActivityUserData::CHAR_VALUE: { | 105 case ActivityUserData::CHAR_VALUE: { |
94 char char_value = recorded_value.GetChar(); | 106 char char_value = recorded_value.GetChar(); |
95 collected_value.set_char_value(&char_value, 1); | 107 collected_value.set_char_value(&char_value, 1); |
96 break; | 108 break; |
97 } | 109 } |
98 case ActivityUserData::BOOL_VALUE: | 110 case ActivityUserData::BOOL_VALUE: |
99 collected_value.set_bool_value(recorded_value.GetBool()); | 111 collected_value.set_bool_value(recorded_value.GetBool()); |
100 break; | 112 break; |
101 case ActivityUserData::SIGNED_VALUE: | 113 case ActivityUserData::SIGNED_VALUE: |
102 collected_value.set_signed_value(recorded_value.GetInt()); | 114 collected_value.set_signed_value(recorded_value.GetInt()); |
| 115 |
| 116 // Promote the execution timestamp to the global key value store. |
| 117 if (report && key == kStabilityStartTimestamp) { |
| 118 (*report->mutable_global_data())[key].Swap(&collected_value); |
| 119 continue; |
| 120 } |
| 121 |
103 break; | 122 break; |
104 case ActivityUserData::UNSIGNED_VALUE: | 123 case ActivityUserData::UNSIGNED_VALUE: |
105 collected_value.set_unsigned_value(recorded_value.GetUint()); | 124 collected_value.set_unsigned_value(recorded_value.GetUint()); |
106 break; | 125 break; |
107 } | 126 } |
108 | 127 |
109 (*collected_map)[key].Swap(&collected_value); | 128 (*collected_map)[key].Swap(&collected_value); |
110 } | 129 } |
111 } | 130 } |
112 | 131 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 Activity* collected = thread_state->add_activities(); | 228 Activity* collected = thread_state->add_activities(); |
210 | 229 |
211 CollectActivity(snapshot.activity_stack[i], collected); | 230 CollectActivity(snapshot.activity_stack[i], collected); |
212 if (i < snapshot.user_data_stack.size()) { | 231 if (i < snapshot.user_data_stack.size()) { |
213 CollectUserData(snapshot.user_data_stack[i], | 232 CollectUserData(snapshot.user_data_stack[i], |
214 collected->mutable_user_data(), nullptr); | 233 collected->mutable_user_data(), nullptr); |
215 } | 234 } |
216 } | 235 } |
217 } | 236 } |
218 | 237 |
219 } // namespace | 238 bool SetProcessType(ProcessState* process_state) { |
| 239 DCHECK(process_state); |
| 240 google::protobuf::Map<std::string, TypedValue>* process_data = |
| 241 process_state->mutable_data(); |
220 | 242 |
221 CollectionStatus Extract(const base::FilePath& stability_file, | 243 const auto it = process_data->find(kStabilityProcessType); |
222 StabilityReport* report) { | 244 if (it == process_data->end()) |
| 245 return false; |
| 246 |
| 247 const TypedValue& value = it->second; |
| 248 if (value.value_case() != TypedValue::kSignedValue) |
| 249 return false; |
| 250 |
| 251 process_state->set_process_type( |
| 252 static_cast<browser_watcher::ProcessState_Type>(value.signed_value())); |
| 253 process_data->erase(it); |
| 254 return true; |
| 255 } |
| 256 |
| 257 void CollectProcess(int64_t pid, |
| 258 GlobalActivityAnalyzer* analyzer, |
| 259 StabilityReport* report) { |
| 260 DCHECK(analyzer); |
223 DCHECK(report); | 261 DCHECK(report); |
224 | 262 |
225 // Create a global analyzer. | 263 ProcessState* process_state = report->add_process_states(); |
226 std::unique_ptr<GlobalActivityAnalyzer> global_analyzer = | |
227 GlobalActivityAnalyzer::CreateWithFile(stability_file); | |
228 if (!global_analyzer) | |
229 return ANALYZER_CREATION_FAILED; | |
230 | |
231 // Extract data for only the first process. | |
232 // TODO(manzagop): Extend this to all processes. | |
233 int64_t pid = global_analyzer->GetFirstProcess(); | |
234 | |
235 // Early exit if there is no data. | |
236 std::vector<std::string> log_messages = global_analyzer->GetLogMessages(); | |
237 ActivityUserData::Snapshot process_data_snapshot = | |
238 global_analyzer->GetProcessDataSnapshot(pid); | |
239 | |
240 ThreadActivityAnalyzer* thread_analyzer = | |
241 global_analyzer->GetFirstAnalyzer(pid); | |
242 if (log_messages.empty() && process_data_snapshot.empty() && | |
243 !thread_analyzer) { | |
244 return DEBUG_FILE_NO_DATA; | |
245 } | |
246 | |
247 report->set_is_complete(global_analyzer->IsDataComplete()); | |
248 | |
249 // Collect log messages. | |
250 for (const std::string& message : log_messages) { | |
251 report->add_log_messages(message); | |
252 } | |
253 | |
254 // Collect global user data. | |
255 google::protobuf::Map<std::string, TypedValue>& global_data = | |
256 *(report->mutable_global_data()); | |
257 CollectUserData(process_data_snapshot, &global_data, report); | |
258 | 264 |
259 // Collect thread activity data. | 265 // Collect thread activity data. |
260 // Note: a single process is instrumented. | 266 ThreadActivityAnalyzer* thread_analyzer = analyzer->GetFirstAnalyzer(pid); |
261 ProcessState* process_state = report->add_process_states(); | |
262 for (; thread_analyzer != nullptr; | 267 for (; thread_analyzer != nullptr; |
263 thread_analyzer = global_analyzer->GetNextAnalyzer()) { | 268 thread_analyzer = analyzer->GetNextAnalyzer()) { |
264 // Only valid analyzers are expected per contract of GetFirstAnalyzer / | 269 // Only valid analyzers are expected per contract of GetFirstAnalyzer / |
265 // GetNextAnalyzer. | 270 // GetNextAnalyzer. |
266 DCHECK(thread_analyzer->IsValid()); | 271 DCHECK(thread_analyzer->IsValid()); |
267 | 272 |
268 if (!process_state->has_process_id()) { | 273 if (!process_state->has_process_id()) { |
269 process_state->set_process_id( | 274 process_state->set_process_id( |
270 thread_analyzer->activity_snapshot().process_id); | 275 thread_analyzer->activity_snapshot().process_id); |
271 } | 276 } |
272 DCHECK_EQ(thread_analyzer->activity_snapshot().process_id, | 277 DCHECK_EQ(thread_analyzer->activity_snapshot().process_id, |
273 process_state->process_id()); | 278 process_state->process_id()); |
274 | 279 |
275 ThreadState* thread_state = process_state->add_threads(); | 280 ThreadState* thread_state = process_state->add_threads(); |
276 CollectThread(thread_analyzer->activity_snapshot(), thread_state); | 281 CollectThread(thread_analyzer->activity_snapshot(), thread_state); |
277 } | 282 } |
278 | 283 |
| 284 // Collect global user data. |
| 285 ActivityUserData::Snapshot process_data_snapshot = |
| 286 analyzer->GetProcessDataSnapshot(pid); |
| 287 CollectUserData(process_data_snapshot, process_state->mutable_data(), report); |
| 288 SetProcessType(process_state); |
| 289 |
279 // Collect module information. | 290 // Collect module information. |
280 CollectModuleInformation(global_analyzer->GetModules(), process_state); | 291 CollectModuleInformation(analyzer->GetModules(pid), process_state); |
| 292 } |
| 293 |
| 294 } // namespace |
| 295 |
| 296 CollectionStatus Extract(const base::FilePath& stability_file, |
| 297 StabilityReport* report) { |
| 298 DCHECK(report); |
| 299 |
| 300 // Create a global analyzer. |
| 301 std::unique_ptr<GlobalActivityAnalyzer> global_analyzer = |
| 302 GlobalActivityAnalyzer::CreateWithFile(stability_file); |
| 303 if (!global_analyzer) |
| 304 return ANALYZER_CREATION_FAILED; |
| 305 report->set_is_complete(global_analyzer->IsDataComplete()); |
| 306 |
| 307 // Collect process data. |
| 308 for (int64_t pid = global_analyzer->GetFirstProcess(); pid != 0; |
| 309 pid = global_analyzer->GetNextProcess()) { |
| 310 CollectProcess(pid, global_analyzer.get(), report); |
| 311 } |
| 312 |
| 313 // Collect log messages. |
| 314 std::vector<std::string> log_messages = global_analyzer->GetLogMessages(); |
| 315 for (const std::string& message : log_messages) { |
| 316 report->add_log_messages(message); |
| 317 } |
281 | 318 |
282 return SUCCESS; | 319 return SUCCESS; |
283 } | 320 } |
284 | 321 |
285 } // namespace browser_watcher | 322 } // namespace browser_watcher |
OLD | NEW |