• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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