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 #include "src/trace_processor/forwarding_trace_parser.h"
18
19 #include <memory>
20 #include <optional>
21 #include <utility>
22
23 #include "perfetto/base/logging.h"
24 #include "perfetto/base/status.h"
25 #include "perfetto/ext/base/status_or.h"
26 #include "perfetto/trace_processor/basic_types.h"
27 #include "src/trace_processor/importers/common/chunked_trace_reader.h"
28 #include "src/trace_processor/importers/common/process_tracker.h"
29 #include "src/trace_processor/importers/common/trace_file_tracker.h"
30 #include "src/trace_processor/importers/proto/proto_trace_reader.h"
31 #include "src/trace_processor/sorter/trace_sorter.h"
32 #include "src/trace_processor/storage/stats.h"
33 #include "src/trace_processor/tables/metadata_tables_py.h"
34 #include "src/trace_processor/trace_reader_registry.h"
35 #include "src/trace_processor/types/trace_processor_context.h"
36 #include "src/trace_processor/util/status_macros.h"
37 #include "src/trace_processor/util/trace_type.h"
38
39 namespace perfetto::trace_processor {
40 namespace {
41
ConvertSortingMode(SortingMode sorting_mode)42 TraceSorter::SortingMode ConvertSortingMode(SortingMode sorting_mode) {
43 switch (sorting_mode) {
44 case SortingMode::kDefaultHeuristics:
45 return TraceSorter::SortingMode::kDefault;
46 case SortingMode::kForceFullSort:
47 return TraceSorter::SortingMode::kFullSort;
48 }
49 PERFETTO_FATAL("For GCC");
50 }
51
GetMinimumSortingMode(TraceType trace_type,const TraceProcessorContext & context)52 std::optional<TraceSorter::SortingMode> GetMinimumSortingMode(
53 TraceType trace_type,
54 const TraceProcessorContext& context) {
55 switch (trace_type) {
56 case kNinjaLogTraceType:
57 case kSystraceTraceType:
58 case kGzipTraceType:
59 case kCtraceTraceType:
60 return std::nullopt;
61
62 case kPerfDataTraceType:
63 case kInstrumentsXmlTraceType:
64 return TraceSorter::SortingMode::kDefault;
65
66 case kUnknownTraceType:
67 case kJsonTraceType:
68 case kFuchsiaTraceType:
69 case kZipFile:
70 case kTarTraceType:
71 case kAndroidDumpstateTraceType:
72 case kAndroidLogcatTraceType:
73 case kGeckoTraceType:
74 case kArtMethodTraceType:
75 case kPerfTextTraceType:
76 return TraceSorter::SortingMode::kFullSort;
77
78 case kProtoTraceType:
79 case kSymbolsTraceType:
80 return ConvertSortingMode(context.config.sorting_mode);
81
82 case kAndroidBugreportTraceType:
83 PERFETTO_FATAL(
84 "This trace type should be handled at the ZipParser level");
85 }
86 PERFETTO_FATAL("For GCC");
87 }
88
89 } // namespace
90
ForwardingTraceParser(TraceProcessorContext * context,tables::TraceFileTable::Id id)91 ForwardingTraceParser::ForwardingTraceParser(TraceProcessorContext* context,
92 tables::TraceFileTable::Id id)
93 : context_(context), file_id_(id) {}
94
95 ForwardingTraceParser::~ForwardingTraceParser() = default;
96
Init(const TraceBlobView & blob)97 base::Status ForwardingTraceParser::Init(const TraceBlobView& blob) {
98 PERFETTO_CHECK(!reader_);
99
100 {
101 auto scoped_trace = context_->storage->TraceExecutionTimeIntoStats(
102 stats::guess_trace_type_duration_ns);
103 trace_type_ = GuessTraceType(blob.data(), blob.size());
104 }
105 if (trace_type_ == kUnknownTraceType) {
106 // If renaming this error message don't remove the "(ERR:fmt)" part.
107 // The UI's error_dialog.ts uses it to make the dialog more graceful.
108 return base::ErrStatus("Unknown trace type provided (ERR:fmt)");
109 }
110 context_->trace_file_tracker->StartParsing(file_id_, trace_type_);
111 ASSIGN_OR_RETURN(reader_,
112 context_->reader_registry->CreateTraceReader(trace_type_));
113
114 PERFETTO_DLOG("%s trace detected", TraceTypeToString(trace_type_));
115 UpdateSorterForTraceType(trace_type_);
116
117 // TODO(b/334978369) Make sure kProtoTraceType and kSystraceTraceType are
118 // parsed first so that we do not get issues with
119 // SetPidZeroIsUpidZeroIdleProcess()
120 if (trace_type_ == kProtoTraceType || trace_type_ == kSystraceTraceType) {
121 context_->process_tracker->SetPidZeroIsUpidZeroIdleProcess();
122 }
123 return base::OkStatus();
124 }
125
UpdateSorterForTraceType(TraceType trace_type)126 void ForwardingTraceParser::UpdateSorterForTraceType(TraceType trace_type) {
127 std::optional<TraceSorter::SortingMode> minimum_sorting_mode =
128 GetMinimumSortingMode(trace_type, *context_);
129 if (!minimum_sorting_mode.has_value()) {
130 return;
131 }
132
133 if (!context_->sorter) {
134 TraceSorter::EventHandling event_handling;
135 switch (context_->config.parsing_mode) {
136 case ParsingMode::kDefault:
137 event_handling = TraceSorter::EventHandling::kSortAndPush;
138 break;
139 case ParsingMode::kTokenizeOnly:
140 event_handling = TraceSorter::EventHandling::kDrop;
141 break;
142 case ParsingMode::kTokenizeAndSort:
143 event_handling = TraceSorter::EventHandling::kSortAndDrop;
144 break;
145 }
146 if (context_->config.enable_dev_features) {
147 auto it = context_->config.dev_flags.find("drop-after-sort");
148 if (it != context_->config.dev_flags.end() && it->second == "true") {
149 event_handling = TraceSorter::EventHandling::kSortAndDrop;
150 }
151 }
152 context_->sorter = std::make_shared<TraceSorter>(
153 context_, *minimum_sorting_mode, event_handling);
154 }
155
156 switch (context_->sorter->sorting_mode()) {
157 case TraceSorter::SortingMode::kDefault:
158 PERFETTO_CHECK(minimum_sorting_mode ==
159 TraceSorter::SortingMode::kDefault);
160 break;
161 case TraceSorter::SortingMode::kFullSort:
162 break;
163 }
164 }
165
Parse(TraceBlobView blob)166 base::Status ForwardingTraceParser::Parse(TraceBlobView blob) {
167 // If this is the first Parse() call, guess the trace type and create the
168 // appropriate parser.
169 if (!reader_) {
170 RETURN_IF_ERROR(Init(blob));
171 }
172 trace_size_ += blob.size();
173 return reader_->Parse(std::move(blob));
174 }
175
NotifyEndOfFile()176 base::Status ForwardingTraceParser::NotifyEndOfFile() {
177 if (reader_) {
178 RETURN_IF_ERROR(reader_->NotifyEndOfFile());
179 }
180 if (trace_type_ != kUnknownTraceType) {
181 context_->trace_file_tracker->DoneParsing(file_id_, trace_size_);
182 }
183 return base::OkStatus();
184 }
185
186 } // namespace perfetto::trace_processor
187