15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/task_profiler/task_profiler_data_serializer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/chrome_content_client.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/process_type.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::DictionaryValue; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::ListValue; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Value; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using tracked_objects::BirthOnThreadSnapshot; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using tracked_objects::DeathDataSnapshot; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using tracked_objects::LocationSnapshot; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using tracked_objects::ParentChildPairSnapshot; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using tracked_objects::TaskSnapshot; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using tracked_objects::ProcessDataSnapshot; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Re-serializes the |location| into |dictionary|. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LocationSnapshotToValue(const LocationSnapshot& location, 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dictionary) { 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetString("file_name", location.file_name); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: This function name is not escaped, and templates have less-than 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // characters, which means this is not suitable for display as HTML unless 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // properly escaped. 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetString("function_name", location.function_name); 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("line_number", location.line_number); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Re-serializes the |birth| into |dictionary|. Prepends the |prefix| to the 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "thread" and "location" key names in the dictionary. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BirthOnThreadSnapshotToValue(const BirthOnThreadSnapshot& birth, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& prefix, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dictionary) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!prefix.empty()); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> location_value(new base::DictionaryValue); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocationSnapshotToValue(birth.location, location_value.get()); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary->Set(prefix + "_location", location_value.release()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dictionary->Set(prefix + "_thread", new base::StringValue(birth.thread_name)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Re-serializes the |death_data| into |dictionary|. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeathDataSnapshotToValue(const DeathDataSnapshot& death_data, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* dictionary) { 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("count", death_data.count); 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("run_ms", death_data.run_duration_sum); 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("run_ms_max", death_data.run_duration_max); 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("run_ms_sample", death_data.run_duration_sample); 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("queue_ms", death_data.queue_duration_sum); 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("queue_ms_max", death_data.queue_duration_max); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetInteger("queue_ms_sample", death_data.queue_duration_sample); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Re-serializes the |snapshot| into |dictionary|. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TaskSnapshotToValue(const TaskSnapshot& snapshot, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* dictionary) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThreadSnapshotToValue(snapshot.birth, "birth", dictionary); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> death_data(new base::DictionaryValue); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeathDataSnapshotToValue(snapshot.death_data, death_data.get()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary->Set("death_data", death_data.release()); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictionary->SetString("death_thread", snapshot.death_thread_name); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // anonymous namespace 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace task_profiler { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TaskProfilerDataSerializer::ToValue( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProcessDataSnapshot& process_data, 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int process_type, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* dictionary) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> tasks_list(new base::ListValue); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<TaskSnapshot>::const_iterator it = 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) process_data.tasks.begin(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != process_data.tasks.end(); ++it) { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> snapshot(new base::DictionaryValue); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TaskSnapshotToValue(*it, snapshot.get()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tasks_list->Append(snapshot.release()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary->Set("list", tasks_list.release()); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary->SetInteger("process_id", process_data.process_id); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary->SetString("process_type", 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::GetProcessTypeNameInEnglish(process_type)); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> descendants_list(new base::ListValue); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<ParentChildPairSnapshot>::const_iterator it = 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) process_data.descendants.begin(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != process_data.descendants.end(); ++it) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> parent_child(new base::DictionaryValue); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThreadSnapshotToValue(it->parent, "parent", parent_child.get()); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThreadSnapshotToValue(it->child, "child", parent_child.get()); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) descendants_list->Append(parent_child.release()); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary->Set("descendants", descendants_list.release()); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TaskProfilerDataSerializer::WriteToFile(const base::FilePath& path) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string output; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONStringValueSerializer serializer(&output); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serializer.set_pretty_print(true); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> root(new base::DictionaryValue()); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* snapshot_list = new base::ListValue(); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* shutdown_snapshot = new base::DictionaryValue(); 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* per_process_data = new base::ListValue(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root->SetInteger("version", 1); 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) root->SetString("userAgent", GetUserAgent()); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(ramant): Collect data from other processes, then add that data to the 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'per_process_data' array here. Should leverage the TrackingSynchronizer 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // class to implement this. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDataSnapshot this_process_data; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::ThreadData::Snapshot(false, &this_process_data); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> this_process_data_json( 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::DictionaryValue); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TaskProfilerDataSerializer::ToValue(this_process_data, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PROCESS_TYPE_BROWSER, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_process_data_json.get()); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) per_process_data->Append(this_process_data_json.release()); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_snapshot->SetInteger( 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "timestamp", 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::Time::Now() - base::Time::UnixEpoch()).InSeconds()); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_snapshot->Set("data", per_process_data); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot_list->Append(shutdown_snapshot); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root->Set("snapshots", snapshot_list); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serializer.Serialize(*root); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_size = static_cast<int>(output.size()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return data_size == base::WriteFile(path, output.data(), data_size); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace task_profiler 153