summaryrefslogtreecommitdiffstats
path: root/chrome/browser/task_profiler/task_profiler_data_serializer.cc
blob: c0f49721bf3a9982d067511b3b54f3569599eee9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/task_profiler/task_profiler_data_serializer.h"

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_string_value_serializer.h"
#include "base/time/time.h"
#include "base/tracked_objects.h"
#include "chrome/common/chrome_content_client.h"
#include "content/public/common/process_type.h"
#include "url/gurl.h"

using base::DictionaryValue;
using base::ListValue;
using base::Value;
using tracked_objects::BirthOnThreadSnapshot;
using tracked_objects::DeathDataSnapshot;
using tracked_objects::LocationSnapshot;
using tracked_objects::TaskSnapshot;
using tracked_objects::ProcessDataPhaseSnapshot;

namespace {

// Re-serializes the |location| into |dictionary|.
void LocationSnapshotToValue(const LocationSnapshot& location,
                             base::DictionaryValue* dictionary) {
  dictionary->SetString("file_name", location.file_name);
  // Note: This function name is not escaped, and templates have less-than
  // characters, which means this is not suitable for display as HTML unless
  // properly escaped.
  dictionary->SetString("function_name", location.function_name);
  dictionary->SetInteger("line_number", location.line_number);
}

// Re-serializes the |birth| into |dictionary|.  Prepends the |prefix| to the
// "thread" and "location" key names in the dictionary.
void BirthOnThreadSnapshotToValue(const BirthOnThreadSnapshot& birth,
                                  const std::string& prefix,
                                  base::DictionaryValue* dictionary) {
  DCHECK(!prefix.empty());

  scoped_ptr<base::DictionaryValue> location_value(new base::DictionaryValue);
  LocationSnapshotToValue(birth.location, location_value.get());
  dictionary->Set(prefix + "_location", location_value.release());

  dictionary->Set(prefix + "_thread", new base::StringValue(birth.thread_name));
}

// Re-serializes the |death_data| into |dictionary|.
void DeathDataSnapshotToValue(const DeathDataSnapshot& death_data,
                              base::DictionaryValue* dictionary) {
  dictionary->SetInteger("count", death_data.count);
  dictionary->SetInteger("run_ms", death_data.run_duration_sum);
  dictionary->SetInteger("run_ms_max", death_data.run_duration_max);
  dictionary->SetInteger("run_ms_sample", death_data.run_duration_sample);
  dictionary->SetInteger("queue_ms", death_data.queue_duration_sum);
  dictionary->SetInteger("queue_ms_max", death_data.queue_duration_max);
  dictionary->SetInteger("queue_ms_sample", death_data.queue_duration_sample);
}

// Re-serializes the |snapshot| into |dictionary|.
void TaskSnapshotToValue(const TaskSnapshot& snapshot,
                         base::DictionaryValue* dictionary) {
  BirthOnThreadSnapshotToValue(snapshot.birth, "birth", dictionary);

  scoped_ptr<base::DictionaryValue> death_data(new base::DictionaryValue);
  DeathDataSnapshotToValue(snapshot.death_data, death_data.get());
  dictionary->Set("death_data", death_data.release());

  dictionary->SetString("death_thread", snapshot.death_thread_name);
}

}  // anonymous namespace

namespace task_profiler {

// static
void TaskProfilerDataSerializer::ToValue(
    const ProcessDataPhaseSnapshot& process_data_phase,
    base::ProcessId process_id,
    int process_type,
    base::DictionaryValue* dictionary) {
  scoped_ptr<base::ListValue> tasks_list(new base::ListValue);
  for (const auto& task : process_data_phase.tasks) {
    scoped_ptr<base::DictionaryValue> snapshot(new base::DictionaryValue);
    TaskSnapshotToValue(task, snapshot.get());
    tasks_list->Append(snapshot.release());
  }
  dictionary->Set("list", tasks_list.release());

  dictionary->SetInteger("process_id", process_id);
  dictionary->SetString("process_type",
                        content::GetProcessTypeNameInEnglish(process_type));
}

}  // namespace task_profiler