• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
19 
20 #include <stdint.h>
21 
22 #include "src/trace_processor/importers/common/chunked_trace_reader.h"
23 #include "src/trace_processor/importers/systrace/systrace_line_tokenizer.h"
24 #include "src/trace_processor/storage/trace_storage.h"
25 
26 namespace Json {
27 class Value;
28 }
29 
30 namespace perfetto {
31 namespace trace_processor {
32 
33 class TraceProcessorContext;
34 
35 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
36 // Visible for testing.
37 enum class ReadDictRes {
38   kFoundDict,
39   kNeedsMoreData,
40   kEndOfTrace,
41   kEndOfArray,
42 };
43 
44 // Parses at most one JSON dictionary and returns a pointer to the end of it,
45 // or nullptr if no dict could be detected.
46 // This is to avoid decoding the full trace in memory and reduce heap traffic.
47 // E.g.  input:  { a:1 b:{ c:2, d:{ e:3 } } } , { a:4, ... },
48 //       output: [   only this is parsed    ] ^return value points here.
49 // Visible for testing.
50 ReadDictRes ReadOneJsonDict(const char* start,
51                             const char* end,
52                             base::StringView* value,
53                             const char** next);
54 
55 enum class ReadKeyRes {
56   kFoundKey,
57   kNeedsMoreData,
58   kEndOfDictionary,
59   kFatalError,
60 };
61 
62 // Parses at most one JSON key and returns a pointer to the start of the value
63 // associated with that key.
64 // This is to avoid decoding the full trace in memory and reduce heap traffic.
65 // E.g. input:  a:1 b:{ c:2}}
66 //     output:    ^ return value points here, key is set to "a".
67 // Note: even if the whole key may be available, this method will return
68 // kNeedsMoreData until the first character of the value is available.
69 // Visible for testing.
70 ReadKeyRes ReadOneJsonKey(const char* start,
71                           const char* end,
72                           std::string* key,
73                           const char** next);
74 
75 // Takes as input a JSON dictionary and returns the value associated with
76 // the provided key (if it exists).
77 // Implementation note: this method does not currently support dictionaries
78 // which have arrays as JSON values because current users of this method
79 // do not require this.
80 // Visible for testing.
81 util::Status ExtractValueForJsonKey(base::StringView dict,
82                                     const std::string& key,
83                                     base::Optional<std::string>* value);
84 
85 enum class ReadSystemLineRes {
86   kFoundLine,
87   kNeedsMoreData,
88   kEndOfSystemTrace,
89   kFatalError,
90 };
91 
92 ReadSystemLineRes ReadOneSystemTraceLine(const char* start,
93                                          const char* end,
94                                          std::string* line,
95                                          const char** next);
96 #endif
97 
98 // Reads a JSON trace in chunks and extracts top level json objects.
99 class JsonTraceTokenizer : public ChunkedTraceReader {
100  public:
101   explicit JsonTraceTokenizer(TraceProcessorContext*);
102   ~JsonTraceTokenizer() override;
103 
104   // ChunkedTraceReader implementation.
105   util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
106   void NotifyEndOfFile() override;
107 
108  private:
109   // Enum which tracks which type of JSON trace we are dealing with.
110   enum class TraceFormat {
111     // Enum value when ther outer-most layer is a dictionary with multiple
112     // key value pairs
113     kOuterDictionary,
114 
115     // Enum value when we only have trace events (i.e. the outermost
116     // layer is just a array of trace events).
117     kOnlyTraceEvents,
118   };
119 
120   // Enum which tracks our current position within the trace.
121   enum class TracePosition {
122     // This indicates that we are inside the outermost dictionary of the
123     // trace and need to read the next key of the dictionary.
124     // This position is only valid when the |format_| == |kOuterDictionary|.
125     kDictionaryKey,
126 
127     // This indicates we are inside the systemTraceEvents string.
128     // This position is only valid when the |format_| == |kOuterDictionary|.
129     kSystemTraceEventsString,
130 
131     // This indicates we are waiting for the entire metadata dictionary to be
132     // available.
133     kWaitingForMetadataDictionary,
134 
135     // This indicates where are inside the traceEvents array.
136     kTraceEventsArray,
137 
138     // This indicates we cannot parse any more data in the trace.
139     kEof,
140   };
141 
142 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
143   util::Status ParseInternal(const char* start,
144                              const char* end,
145                              const char** next);
146 #endif
147 
148   TraceProcessorContext* const context_;
149 
150   TraceFormat format_ = TraceFormat::kOuterDictionary;
151   TracePosition position_ = TracePosition::kDictionaryKey;
152 
153   SystraceLineTokenizer systrace_line_tokenizer_;
154 
155   uint64_t offset_ = 0;
156   // Used to glue together JSON objects that span across two (or more)
157   // Parse boundaries.
158   std::vector<char> buffer_;
159 };
160 
161 }  // namespace trace_processor
162 }  // namespace perfetto
163 
164 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
165