1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/json_trace_parser.h"
18
19 #include <inttypes.h>
20 #include <json/reader.h>
21 #include <json/value.h>
22
23 #include <limits>
24 #include <string>
25
26 #include "perfetto/base/build_config.h"
27 #include "perfetto/base/logging.h"
28 #include "perfetto/base/string_view.h"
29 #include "perfetto/base/utils.h"
30 #include "src/trace_processor/json_trace_utils.h"
31 #include "src/trace_processor/process_tracker.h"
32 #include "src/trace_processor/slice_tracker.h"
33 #include "src/trace_processor/trace_processor_context.h"
34
35 #if !PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
36 #error The JSON trace parser is supported only in the standalone build for now.
37 #endif
38
39 namespace perfetto {
40 namespace trace_processor {
41
JsonTraceParser(TraceProcessorContext * context)42 JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
43 : context_(context) {}
44
45 JsonTraceParser::~JsonTraceParser() = default;
46
ParseFtracePacket(uint32_t,int64_t,TraceSorter::TimestampedTracePiece)47 void JsonTraceParser::ParseFtracePacket(uint32_t,
48 int64_t,
49 TraceSorter::TimestampedTracePiece) {
50 PERFETTO_FATAL("Json Trace Parser cannot handle ftrace packets.");
51 }
52
ParseTracePacket(int64_t timestamp,TraceSorter::TimestampedTracePiece ttp)53 void JsonTraceParser::ParseTracePacket(int64_t timestamp,
54 TraceSorter::TimestampedTracePiece ttp) {
55 PERFETTO_DCHECK(ttp.json_value != nullptr);
56 const Json::Value& value = *(ttp.json_value);
57
58 ProcessTracker* procs = context_->process_tracker.get();
59 TraceStorage* storage = context_->storage.get();
60 SliceTracker* slice_tracker = context_->slice_tracker.get();
61
62 auto& ph = value["ph"];
63 if (!ph.isString())
64 return;
65 char phase = *ph.asCString();
66
67 base::Optional<uint32_t> opt_pid;
68 base::Optional<uint32_t> opt_tid;
69
70 if (value.isMember("pid"))
71 opt_pid = json_trace_utils::CoerceToUint32(value["pid"]);
72 if (value.isMember("tid"))
73 opt_tid = json_trace_utils::CoerceToUint32(value["tid"]);
74
75 uint32_t pid = opt_pid.value_or(0);
76 uint32_t tid = opt_tid.value_or(pid);
77
78 base::StringView cat = value.isMember("cat")
79 ? base::StringView(value["cat"].asCString())
80 : base::StringView();
81 base::StringView name = value.isMember("name")
82 ? base::StringView(value["name"].asCString())
83 : base::StringView();
84
85 StringId cat_id = storage->InternString(cat);
86 StringId name_id = storage->InternString(name);
87 UniqueTid utid = procs->UpdateThread(tid, pid);
88
89 switch (phase) {
90 case 'B': { // TRACE_EVENT_BEGIN.
91 slice_tracker->Begin(timestamp, utid, cat_id, name_id);
92 break;
93 }
94 case 'E': { // TRACE_EVENT_END.
95 slice_tracker->End(timestamp, utid, cat_id, name_id);
96 break;
97 }
98 case 'X': { // TRACE_EVENT (scoped event).
99 base::Optional<int64_t> opt_dur =
100 json_trace_utils::CoerceToNs(value["dur"]);
101 if (!opt_dur.has_value())
102 return;
103 slice_tracker->Scoped(timestamp, utid, cat_id, name_id, opt_dur.value());
104 break;
105 }
106 case 'M': { // Metadata events (process and thread names).
107 if (strcmp(value["name"].asCString(), "thread_name") == 0) {
108 const char* thread_name = value["args"]["name"].asCString();
109 auto thread_name_id = context_->storage->InternString(thread_name);
110 procs->UpdateThreadName(tid, thread_name_id);
111 break;
112 }
113 if (strcmp(value["name"].asCString(), "process_name") == 0) {
114 const char* proc_name = value["args"]["name"].asCString();
115 procs->UpdateProcess(pid, base::nullopt, proc_name);
116 break;
117 }
118 }
119 }
120 }
121
122 } // namespace trace_processor
123 } // namespace perfetto
124