OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/task_profiler/task_profiler_data_serializer.h" | 5 #include "chrome/browser/task_profiler/task_profiler_data_serializer.h" |
6 | 6 |
7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/json/json_string_value_serializer.h" | 9 #include "base/json/json_string_value_serializer.h" |
10 #include "base/time.h" | 10 #include "base/time.h" |
11 #include "base/tracked_objects.h" | 11 #include "base/tracked_objects.h" |
12 #include "content/public/common/content_client.h" | 12 #include "content/public/common/content_client.h" |
| 13 #include "content/public/common/process_type.h" |
13 #include "googleurl/src/gurl.h" | 14 #include "googleurl/src/gurl.h" |
14 | 15 |
| 16 using base::DictionaryValue; |
| 17 using base::ListValue; |
| 18 using base::Value; |
| 19 using tracked_objects::BirthOnThreadSnapshot; |
| 20 using tracked_objects::DeathDataSnapshot; |
| 21 using tracked_objects::LocationSnapshot; |
| 22 using tracked_objects::ParentChildPairSnapshot; |
| 23 using tracked_objects::TaskSnapshot; |
| 24 using tracked_objects::ProcessDataSnapshot; |
| 25 |
| 26 namespace { |
| 27 |
| 28 // Re-serializes the |location| into |dictionary|. |
| 29 void LocationSnapshotToValue(const LocationSnapshot& location, |
| 30 DictionaryValue* dictionary) { |
| 31 dictionary->Set("file_name", Value::CreateStringValue(location.file_name)); |
| 32 // Note: This function name is not escaped, and templates have less-than |
| 33 // characters, which means this is not suitable for display as HTML unless |
| 34 // properly escaped. |
| 35 dictionary->Set("function_name", |
| 36 Value::CreateStringValue(location.function_name)); |
| 37 dictionary->Set("line_number", |
| 38 Value::CreateIntegerValue(location.line_number)); |
| 39 } |
| 40 |
| 41 // Re-serializes the |birth| into |dictionary|. Prepends the |prefix| to the |
| 42 // "thread" and "location" key names in the dictionary. |
| 43 void BirthOnThreadSnapshotToValue(const BirthOnThreadSnapshot& birth, |
| 44 const std::string& prefix, |
| 45 DictionaryValue* dictionary) { |
| 46 DCHECK(!prefix.empty()); |
| 47 |
| 48 scoped_ptr<DictionaryValue> location_value(new DictionaryValue); |
| 49 LocationSnapshotToValue(birth.location, location_value.get()); |
| 50 dictionary->Set(prefix + "_location", location_value.release()); |
| 51 |
| 52 dictionary->Set(prefix + "_thread", |
| 53 Value::CreateStringValue(birth.thread_name)); |
| 54 } |
| 55 |
| 56 // Re-serializes the |death_data| into |dictionary|. |
| 57 void DeathDataSnapshotToValue(const DeathDataSnapshot& death_data, |
| 58 base::DictionaryValue* dictionary) { |
| 59 dictionary->Set("count", |
| 60 Value::CreateIntegerValue(death_data.count)); |
| 61 dictionary->Set("run_ms", |
| 62 Value::CreateIntegerValue(death_data.run_duration_sum)); |
| 63 dictionary->Set("run_ms_max", |
| 64 Value::CreateIntegerValue(death_data.run_duration_max)); |
| 65 dictionary->Set("run_ms_sample", |
| 66 Value::CreateIntegerValue(death_data.run_duration_sample)); |
| 67 dictionary->Set("queue_ms", |
| 68 Value::CreateIntegerValue(death_data.queue_duration_sum)); |
| 69 dictionary->Set("queue_ms_max", |
| 70 Value::CreateIntegerValue(death_data.queue_duration_max)); |
| 71 dictionary->Set("queue_ms_sample", |
| 72 Value::CreateIntegerValue(death_data.queue_duration_sample)); |
| 73 |
| 74 } |
| 75 |
| 76 // Re-serializes the |snapshot| into |dictionary|. |
| 77 void TaskSnapshotToValue(const TaskSnapshot& snapshot, |
| 78 base::DictionaryValue* dictionary) { |
| 79 BirthOnThreadSnapshotToValue(snapshot.birth, "birth", dictionary); |
| 80 |
| 81 scoped_ptr<DictionaryValue> death_data(new DictionaryValue); |
| 82 DeathDataSnapshotToValue(snapshot.death_data, death_data.get()); |
| 83 dictionary->Set("death_data", death_data.release()); |
| 84 |
| 85 dictionary->Set("death_thread", |
| 86 Value::CreateStringValue(snapshot.death_thread_name)); |
| 87 |
| 88 } |
| 89 |
| 90 } // anonymous namespace |
| 91 |
15 namespace task_profiler { | 92 namespace task_profiler { |
16 | 93 |
17 bool TaskProfilerDataSerializer::WriteToFile(const FilePath &path) { | 94 // static |
| 95 void TaskProfilerDataSerializer::ToValue( |
| 96 const ProcessDataSnapshot& process_data, |
| 97 content::ProcessType process_type, |
| 98 base::DictionaryValue* dictionary) { |
| 99 scoped_ptr<base::ListValue> tasks_list(new base::ListValue); |
| 100 for (std::vector<TaskSnapshot>::const_iterator it = |
| 101 process_data.tasks.begin(); |
| 102 it != process_data.tasks.end(); ++it) { |
| 103 scoped_ptr<DictionaryValue> snapshot(new DictionaryValue); |
| 104 TaskSnapshotToValue(*it, snapshot.get()); |
| 105 tasks_list->Append(snapshot.release()); |
| 106 } |
| 107 dictionary->Set("list", tasks_list.release()); |
| 108 |
| 109 dictionary->SetInteger("process_id", process_data.process_id); |
| 110 dictionary->SetString("process_type", |
| 111 content::GetProcessTypeNameInEnglish(process_type)); |
| 112 |
| 113 scoped_ptr<base::ListValue> descendants_list(new base::ListValue); |
| 114 for (std::vector<ParentChildPairSnapshot>::const_iterator it = |
| 115 process_data.descendants.begin(); |
| 116 it != process_data.descendants.end(); ++it) { |
| 117 scoped_ptr<base::DictionaryValue> parent_child(new base::DictionaryValue); |
| 118 BirthOnThreadSnapshotToValue(it->parent, "parent", parent_child.get()); |
| 119 BirthOnThreadSnapshotToValue(it->child, "child", parent_child.get()); |
| 120 descendants_list->Append(parent_child.release()); |
| 121 } |
| 122 dictionary->Set("descendants", descendants_list.release()); |
| 123 } |
| 124 |
| 125 |
| 126 bool TaskProfilerDataSerializer::WriteToFile(const FilePath& path) { |
18 std::string output; | 127 std::string output; |
19 JSONStringValueSerializer serializer(&output); | 128 JSONStringValueSerializer serializer(&output); |
20 serializer.set_pretty_print(true); | 129 serializer.set_pretty_print(true); |
21 | 130 |
22 scoped_ptr<base::DictionaryValue> root(new DictionaryValue()); | 131 scoped_ptr<base::DictionaryValue> root(new DictionaryValue()); |
23 | 132 |
24 base::ListValue* snapshot_list = new ListValue(); | 133 base::ListValue* snapshot_list = new ListValue(); |
25 base::DictionaryValue* shutdown_snapshot = new DictionaryValue(); | 134 base::DictionaryValue* shutdown_snapshot = new DictionaryValue(); |
26 base::ListValue* per_process_data = new ListValue(); | 135 base::ListValue* per_process_data = new ListValue(); |
27 | 136 |
28 root->SetInteger("version", 1); | 137 root->SetInteger("version", 1); |
29 root->SetString("userAgent", content::GetUserAgent(GURL())); | 138 root->SetString("userAgent", content::GetUserAgent(GURL())); |
30 | 139 |
31 // TODO(ramant): Collect data from other processes, then add that data to the | 140 // TODO(ramant): Collect data from other processes, then add that data to the |
32 // 'per_process_data' array here. | 141 // 'per_process_data' array here. Should leverage the TrackingSynchronizer |
33 base::DictionaryValue* this_process_data = | 142 // class to implement this. |
34 tracked_objects::ThreadData::ToValue(false); | 143 ProcessDataSnapshot this_process_data; |
35 per_process_data->Append(this_process_data); | 144 tracked_objects::ThreadData::Snapshot(false, &this_process_data); |
| 145 scoped_ptr<base::DictionaryValue> this_process_data_json( |
| 146 new base::DictionaryValue); |
| 147 TaskProfilerDataSerializer::ToValue(this_process_data, |
| 148 content::PROCESS_TYPE_BROWSER, |
| 149 this_process_data_json.get()); |
| 150 per_process_data->Append(this_process_data_json.release()); |
36 | 151 |
37 shutdown_snapshot->SetInteger( | 152 shutdown_snapshot->SetInteger( |
38 "timestamp", | 153 "timestamp", |
39 (base::Time::Now() - base::Time::UnixEpoch()).InSeconds()); | 154 (base::Time::Now() - base::Time::UnixEpoch()).InSeconds()); |
40 shutdown_snapshot->Set("data", per_process_data); | 155 shutdown_snapshot->Set("data", per_process_data); |
41 snapshot_list->Append(shutdown_snapshot); | 156 snapshot_list->Append(shutdown_snapshot); |
42 root->Set("snapshots", snapshot_list); | 157 root->Set("snapshots", snapshot_list); |
43 | 158 |
44 serializer.Serialize(*root); | 159 serializer.Serialize(*root); |
45 int data_size = static_cast<int>(output.size()); | 160 int data_size = static_cast<int>(output.size()); |
46 | 161 |
47 return data_size == file_util::WriteFile(path, output.data(), data_size); | 162 return data_size == file_util::WriteFile(path, output.data(), data_size); |
48 } | 163 } |
49 | 164 |
50 } // namespace task_profiler | 165 } // namespace task_profiler |
OLD | NEW |