xref: /aosp_15_r20/external/perfetto/src/trace_processor/forwarding_trace_parser.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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