blob: d25954d6509b23cbd3ec34a4d8a3e50d12d10ab9 [file] [log] [blame]
Deepanjan Roy01994ca2019-04-02 11:05:34 -07001/*
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
Eric Secklerd8b52082019-10-17 15:58:38 +010017#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
18#define SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
Deepanjan Roy01994ca2019-04-02 11:05:34 -070019
20#include <stdint.h>
21
Lalit Maganti1534bb72021-04-23 14:11:26 +010022#include "src/trace_processor/importers/common/chunked_trace_reader.h"
Lalit Magantib5072a92021-06-01 14:32:50 +010023#include "src/trace_processor/importers/json/json_utils.h"
Lalit Maganti31afb822020-03-05 17:36:57 +000024#include "src/trace_processor/importers/systrace/systrace_line_tokenizer.h"
Lalit Maganti7010b332020-02-07 10:51:15 +000025#include "src/trace_processor/storage/trace_storage.h"
Deepanjan Roy01994ca2019-04-02 11:05:34 -070026
27namespace Json {
28class Value;
29}
30
31namespace perfetto {
32namespace trace_processor {
33
34class TraceProcessorContext;
35
Hector Dearmanfcbc5e22019-04-08 13:12:28 +010036// Visible for testing.
Lalit Maganti31afb822020-03-05 17:36:57 +000037enum class ReadDictRes {
38 kFoundDict,
39 kNeedsMoreData,
40 kEndOfTrace,
41 kEndOfArray,
Lalit Maganti31afb822020-03-05 17:36:57 +000042};
Hector Dearmanfcbc5e22019-04-08 13:12:28 +010043
Lalit Maganti31afb822020-03-05 17:36:57 +000044// 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.
Hector Dearmanfcbc5e22019-04-08 13:12:28 +010049// Visible for testing.
50ReadDictRes ReadOneJsonDict(const char* start,
51 const char* end,
Lalit Maganti0732e002021-03-10 17:05:18 +000052 base::StringView* value,
Hector Dearmanfcbc5e22019-04-08 13:12:28 +010053 const char** next);
54
Lalit Maganti31afb822020-03-05 17:36:57 +000055enum 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.
70ReadKeyRes ReadOneJsonKey(const char* start,
71 const char* end,
72 std::string* key,
73 const char** next);
74
Lalit Maganti0732e002021-03-10 17:05:18 +000075// 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.
81util::Status ExtractValueForJsonKey(base::StringView dict,
82 const std::string& key,
83 base::Optional<std::string>* value);
84
Lalit Maganti31afb822020-03-05 17:36:57 +000085enum class ReadSystemLineRes {
86 kFoundLine,
87 kNeedsMoreData,
88 kEndOfSystemTrace,
89 kFatalError,
90};
91
92ReadSystemLineRes ReadOneSystemTraceLine(const char* start,
93 const char* end,
94 std::string* line,
95 const char** next);
Lalit Magantib5072a92021-06-01 14:32:50 +010096
97// Parses the "displayTimeUnit" key from the given trace buffer
98// and returns the associated time unit if one exists.
99base::Optional<json::TimeUnit> MaybeParseDisplayTimeUnit(
100 base::StringView buffer);
Lalit Maganti31afb822020-03-05 17:36:57 +0000101
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700102// Reads a JSON trace in chunks and extracts top level json objects.
103class JsonTraceTokenizer : public ChunkedTraceReader {
104 public:
105 explicit JsonTraceTokenizer(TraceProcessorContext*);
106 ~JsonTraceTokenizer() override;
107
108 // ChunkedTraceReader implementation.
Primiano Tucci3264b592021-11-08 18:20:51 +0000109 util::Status Parse(TraceBlobView) override;
Primiano Tucci40da82f2020-02-13 18:04:35 +0000110 void NotifyEndOfFile() override;
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700111
112 private:
Lalit Maganti31afb822020-03-05 17:36:57 +0000113 // Enum which tracks which type of JSON trace we are dealing with.
114 enum class TraceFormat {
115 // Enum value when ther outer-most layer is a dictionary with multiple
116 // key value pairs
117 kOuterDictionary,
118
119 // Enum value when we only have trace events (i.e. the outermost
120 // layer is just a array of trace events).
121 kOnlyTraceEvents,
122 };
123
124 // Enum which tracks our current position within the trace.
125 enum class TracePosition {
126 // This indicates that we are inside the outermost dictionary of the
127 // trace and need to read the next key of the dictionary.
128 // This position is only valid when the |format_| == |kOuterDictionary|.
129 kDictionaryKey,
130
131 // This indicates we are inside the systemTraceEvents string.
132 // This position is only valid when the |format_| == |kOuterDictionary|.
133 kSystemTraceEventsString,
134
135 // This indicates we are waiting for the entire metadata dictionary to be
136 // available.
137 kWaitingForMetadataDictionary,
138
139 // This indicates where are inside the traceEvents array.
140 kTraceEventsArray,
141
142 // This indicates we cannot parse any more data in the trace.
143 kEof,
144 };
145
146 util::Status ParseInternal(const char* start,
147 const char* end,
148 const char** next);
149
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700150 TraceProcessorContext* const context_;
151
Lalit Maganti31afb822020-03-05 17:36:57 +0000152 TraceFormat format_ = TraceFormat::kOuterDictionary;
153 TracePosition position_ = TracePosition::kDictionaryKey;
154
155 SystraceLineTokenizer systrace_line_tokenizer_;
156
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700157 uint64_t offset_ = 0;
158 // Used to glue together JSON objects that span across two (or more)
159 // Parse boundaries.
160 std::vector<char> buffer_;
161};
162
163} // namespace trace_processor
164} // namespace perfetto
165
Eric Secklerd8b52082019-10-17 15:58:38 +0100166#endif // SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_