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/trace_processor_impl.h"
18
19 #include <algorithm>
20 #include <cinttypes>
21 #include <cstddef>
22 #include <cstdint>
23 #include <limits>
24 #include <memory>
25 #include <optional>
26 #include <string>
27 #include <unordered_map>
28 #include <utility>
29 #include <vector>
30
31 #include "perfetto/base/build_config.h"
32 #include "perfetto/base/logging.h"
33 #include "perfetto/base/status.h"
34 #include "perfetto/base/thread_utils.h"
35 #include "perfetto/base/time.h"
36 #include "perfetto/ext/base/clock_snapshots.h"
37 #include "perfetto/ext/base/flat_hash_map.h"
38 #include "perfetto/ext/base/small_vector.h"
39 #include "perfetto/ext/base/status_or.h"
40 #include "perfetto/ext/base/string_splitter.h"
41 #include "perfetto/ext/base/string_utils.h"
42 #include "perfetto/protozero/scattered_heap_buffer.h"
43 #include "perfetto/public/compiler.h"
44 #include "perfetto/trace_processor/basic_types.h"
45 #include "perfetto/trace_processor/iterator.h"
46 #include "perfetto/trace_processor/trace_blob_view.h"
47 #include "perfetto/trace_processor/trace_processor.h"
48 #include "src/trace_processor/importers/android_bugreport/android_dumpstate_event_parser_impl.h"
49 #include "src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h"
50 #include "src/trace_processor/importers/android_bugreport/android_log_event_parser_impl.h"
51 #include "src/trace_processor/importers/android_bugreport/android_log_reader.h"
52 #include "src/trace_processor/importers/archive/gzip_trace_parser.h"
53 #include "src/trace_processor/importers/archive/tar_trace_reader.h"
54 #include "src/trace_processor/importers/archive/zip_trace_reader.h"
55 #include "src/trace_processor/importers/art_method/art_method_parser_impl.h"
56 #include "src/trace_processor/importers/art_method/art_method_tokenizer.h"
57 #include "src/trace_processor/importers/common/clock_tracker.h"
58 #include "src/trace_processor/importers/common/trace_file_tracker.h"
59 #include "src/trace_processor/importers/common/trace_parser.h"
60 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
61 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
62 #include "src/trace_processor/importers/gecko/gecko_trace_parser_impl.h"
63 #include "src/trace_processor/importers/gecko/gecko_trace_tokenizer.h"
64 #include "src/trace_processor/importers/json/json_trace_parser_impl.h"
65 #include "src/trace_processor/importers/json/json_trace_tokenizer.h"
66 #include "src/trace_processor/importers/json/json_utils.h"
67 #include "src/trace_processor/importers/ninja/ninja_log_parser.h"
68 #include "src/trace_processor/importers/perf/perf_data_tokenizer.h"
69 #include "src/trace_processor/importers/perf/perf_event.h"
70 #include "src/trace_processor/importers/perf/perf_tracker.h"
71 #include "src/trace_processor/importers/perf/record_parser.h"
72 #include "src/trace_processor/importers/perf/spe_record_parser.h"
73 #include "src/trace_processor/importers/perf_text/perf_text_trace_parser_impl.h"
74 #include "src/trace_processor/importers/perf_text/perf_text_trace_tokenizer.h"
75 #include "src/trace_processor/importers/proto/additional_modules.h"
76 #include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
77 #include "src/trace_processor/iterator_impl.h"
78 #include "src/trace_processor/metrics/all_chrome_metrics.descriptor.h"
79 #include "src/trace_processor/metrics/all_webview_metrics.descriptor.h"
80 #include "src/trace_processor/metrics/metrics.descriptor.h"
81 #include "src/trace_processor/metrics/metrics.h"
82 #include "src/trace_processor/metrics/sql/amalgamated_sql_metrics.h"
83 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
84 #include "src/trace_processor/perfetto_sql/engine/table_pointer_module.h"
85 #include "src/trace_processor/perfetto_sql/generator/structured_query_generator.h"
86 #include "src/trace_processor/perfetto_sql/intrinsics/functions/base64.h"
87 #include "src/trace_processor/perfetto_sql/intrinsics/functions/clock_functions.h"
88 #include "src/trace_processor/perfetto_sql/intrinsics/functions/counter_intervals.h"
89 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_function.h"
90 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_view_function.h"
91 #include "src/trace_processor/perfetto_sql/intrinsics/functions/dominator_tree.h"
92 #include "src/trace_processor/perfetto_sql/intrinsics/functions/graph_scan.h"
93 #include "src/trace_processor/perfetto_sql/intrinsics/functions/graph_traversal.h"
94 #include "src/trace_processor/perfetto_sql/intrinsics/functions/import.h"
95 #include "src/trace_processor/perfetto_sql/intrinsics/functions/interval_intersect.h"
96 #include "src/trace_processor/perfetto_sql/intrinsics/functions/layout_functions.h"
97 #include "src/trace_processor/perfetto_sql/intrinsics/functions/math.h"
98 #include "src/trace_processor/perfetto_sql/intrinsics/functions/pprof_functions.h"
99 #include "src/trace_processor/perfetto_sql/intrinsics/functions/replace_numbers_function.h"
100 #include "src/trace_processor/perfetto_sql/intrinsics/functions/sqlite3_str_split.h"
101 #include "src/trace_processor/perfetto_sql/intrinsics/functions/stack_functions.h"
102 #include "src/trace_processor/perfetto_sql/intrinsics/functions/structural_tree_partition.h"
103 #include "src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.h"
104 #include "src/trace_processor/perfetto_sql/intrinsics/functions/type_builders.h"
105 #include "src/trace_processor/perfetto_sql/intrinsics/functions/utils.h"
106 #include "src/trace_processor/perfetto_sql/intrinsics/functions/window_functions.h"
107 #include "src/trace_processor/perfetto_sql/intrinsics/operators/counter_mipmap_operator.h"
108 #include "src/trace_processor/perfetto_sql/intrinsics/operators/slice_mipmap_operator.h"
109 #include "src/trace_processor/perfetto_sql/intrinsics/operators/span_join_operator.h"
110 #include "src/trace_processor/perfetto_sql/intrinsics/operators/window_operator.h"
111 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.h"
112 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.h"
113 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.h"
114 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs_weight_bounded.h"
115 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.h"
116 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flamegraph.h"
117 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice.h"
118 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout.h"
119 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/table_info.h"
120 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/winscope_proto_to_args_with_defaults.h"
121 #include "src/trace_processor/perfetto_sql/stdlib/stdlib.h"
122 #include "src/trace_processor/sqlite/bindings/sqlite_aggregate_function.h"
123 #include "src/trace_processor/sqlite/bindings/sqlite_result.h"
124 #include "src/trace_processor/sqlite/sql_source.h"
125 #include "src/trace_processor/sqlite/sql_stats_table.h"
126 #include "src/trace_processor/sqlite/stats_table.h"
127 #include "src/trace_processor/storage/trace_storage.h"
128 #include "src/trace_processor/tp_metatrace.h"
129 #include "src/trace_processor/trace_processor_storage_impl.h"
130 #include "src/trace_processor/trace_reader_registry.h"
131 #include "src/trace_processor/trace_summary/summary.h"
132 #include "src/trace_processor/trace_summary/trace_summary.descriptor.h"
133 #include "src/trace_processor/types/trace_processor_context.h"
134 #include "src/trace_processor/util/descriptors.h"
135 #include "src/trace_processor/util/gzip_utils.h"
136 #include "src/trace_processor/util/protozero_to_json.h"
137 #include "src/trace_processor/util/protozero_to_text.h"
138 #include "src/trace_processor/util/regex.h"
139 #include "src/trace_processor/util/sql_modules.h"
140 #include "src/trace_processor/util/status_macros.h"
141 #include "src/trace_processor/util/trace_type.h"
142
143 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
144 #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
145 #include "protos/perfetto/trace/trace.pbzero.h"
146 #include "protos/perfetto/trace/trace_packet.pbzero.h"
147
148 #if PERFETTO_BUILDFLAG(PERFETTO_TP_INSTRUMENTS)
149 #include "src/trace_processor/importers/instruments/instruments_xml_tokenizer.h"
150 #include "src/trace_processor/importers/instruments/row_parser.h"
151 #endif
152
153 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
154 #include "src/trace_processor/importers/etm/etm_tracker.h"
155 #include "src/trace_processor/importers/etm/etm_v4_stream_demultiplexer.h"
156 #include "src/trace_processor/importers/etm/file_tracker.h"
157 #include "src/trace_processor/perfetto_sql/intrinsics/operators/etm_decode_trace_vtable.h"
158 #include "src/trace_processor/perfetto_sql/intrinsics/operators/etm_iterate_range_vtable.h"
159 #endif
160
161 namespace perfetto::trace_processor {
162 namespace {
163
164 template <typename SqlFunction, typename Ptr = typename SqlFunction::Context*>
RegisterFunction(PerfettoSqlEngine * engine,const char * name,int argc,Ptr context=nullptr,bool deterministic=true)165 void RegisterFunction(PerfettoSqlEngine* engine,
166 const char* name,
167 int argc,
168 Ptr context = nullptr,
169 bool deterministic = true) {
170 auto status = engine->RegisterStaticFunction<SqlFunction>(
171 name, argc, std::move(context), deterministic);
172 if (!status.ok())
173 PERFETTO_ELOG("%s", status.c_message());
174 }
175
RegisterAllProtoBuilderFunctions(DescriptorPool * pool,std::unordered_map<std::string,std::string> * proto_fn_name_to_path,PerfettoSqlEngine * engine,TraceProcessor * tp)176 base::Status RegisterAllProtoBuilderFunctions(
177 DescriptorPool* pool,
178 std::unordered_map<std::string, std::string>* proto_fn_name_to_path,
179 PerfettoSqlEngine* engine,
180 TraceProcessor* tp) {
181 for (uint32_t i = 0; i < pool->descriptors().size(); ++i) {
182 // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
183 // into a function name of the form (TraceMetrics_SubMetric).
184 const auto& desc = pool->descriptors()[i];
185 auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
186 std::replace(fn_name.begin(), fn_name.end(), '.', '_');
187 auto registered_fn = proto_fn_name_to_path->find(fn_name);
188 if (registered_fn != proto_fn_name_to_path->end() &&
189 registered_fn->second != desc.full_name()) {
190 return base::ErrStatus(
191 "Attempt to create new metric function '%s' for different descriptor "
192 "'%s' that conflicts with '%s'",
193 fn_name.c_str(), desc.full_name().c_str(),
194 registered_fn->second.c_str());
195 }
196 RegisterFunction<metrics::BuildProto>(
197 engine, fn_name.c_str(), -1,
198 std::make_unique<metrics::BuildProto::Context>(
199 metrics::BuildProto::Context{tp, pool, i}));
200 proto_fn_name_to_path->emplace(fn_name, desc.full_name());
201 }
202 return base::OkStatus();
203 }
204
BuildBoundsTable(sqlite3 * db,std::pair<int64_t,int64_t> bounds)205 void BuildBoundsTable(sqlite3* db, std::pair<int64_t, int64_t> bounds) {
206 char* error = nullptr;
207 sqlite3_exec(db, "DELETE FROM _trace_bounds", nullptr, nullptr, &error);
208 if (error) {
209 PERFETTO_ELOG("Error deleting from bounds table: %s", error);
210 sqlite3_free(error);
211 return;
212 }
213
214 base::StackString<1024> sql("INSERT INTO _trace_bounds VALUES(%" PRId64
215 ", %" PRId64 ")",
216 bounds.first, bounds.second);
217 sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &error);
218 if (error) {
219 PERFETTO_ELOG("Error inserting bounds table: %s", error);
220 sqlite3_free(error);
221 }
222 }
223
224 class ValueAtMaxTs : public SqliteAggregateFunction<ValueAtMaxTs> {
225 public:
226 static constexpr char kName[] = "VALUE_AT_MAX_TS";
227 static constexpr int kArgCount = 2;
228 struct Context {
229 bool initialized;
230 int value_type;
231
232 int64_t max_ts;
233 int64_t int_value_at_max_ts;
234 double double_value_at_max_ts;
235 };
236
Step(sqlite3_context * ctx,int,sqlite3_value ** argv)237 static void Step(sqlite3_context* ctx, int, sqlite3_value** argv) {
238 sqlite3_value* ts = argv[0];
239 sqlite3_value* value = argv[1];
240
241 // Note that sqlite3_aggregate_context zeros the memory for us so all the
242 // variables of the struct should be zero.
243 auto* fn_ctx = reinterpret_cast<Context*>(
244 sqlite3_aggregate_context(ctx, sizeof(Context)));
245
246 // For performance reasons, we only do the check for the type of ts and
247 // value on the first call of the function.
248 if (PERFETTO_UNLIKELY(!fn_ctx->initialized)) {
249 if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
250 return sqlite::result::Error(
251 ctx, "VALUE_AT_MAX_TS: ts passed was not an integer");
252 }
253
254 fn_ctx->value_type = sqlite3_value_type(value);
255 if (fn_ctx->value_type != SQLITE_INTEGER &&
256 fn_ctx->value_type != SQLITE_FLOAT) {
257 return sqlite::result::Error(
258 ctx, "VALUE_AT_MAX_TS: value passed was not an integer or float");
259 }
260
261 fn_ctx->max_ts = std::numeric_limits<int64_t>::min();
262 fn_ctx->initialized = true;
263 }
264
265 // On dcheck builds however, we check every passed ts and value.
266 #if PERFETTO_DCHECK_IS_ON()
267 if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
268 return sqlite::result::Error(
269 ctx, "VALUE_AT_MAX_TS: ts passed was not an integer");
270 }
271 if (sqlite3_value_type(value) != fn_ctx->value_type) {
272 return sqlite::result::Error(
273 ctx, "VALUE_AT_MAX_TS: value type is inconsistent");
274 }
275 #endif
276
277 int64_t ts_int = sqlite3_value_int64(ts);
278 if (PERFETTO_LIKELY(fn_ctx->max_ts <= ts_int)) {
279 fn_ctx->max_ts = ts_int;
280
281 if (fn_ctx->value_type == SQLITE_INTEGER) {
282 fn_ctx->int_value_at_max_ts = sqlite3_value_int64(value);
283 } else {
284 fn_ctx->double_value_at_max_ts = sqlite3_value_double(value);
285 }
286 }
287 }
288
Final(sqlite3_context * ctx)289 static void Final(sqlite3_context* ctx) {
290 auto* fn_ctx = static_cast<Context*>(sqlite3_aggregate_context(ctx, 0));
291 if (!fn_ctx) {
292 sqlite::result::Null(ctx);
293 return;
294 }
295 if (fn_ctx->value_type == SQLITE_INTEGER) {
296 sqlite::result::Long(ctx, fn_ctx->int_value_at_max_ts);
297 } else {
298 sqlite::result::Double(ctx, fn_ctx->double_value_at_max_ts);
299 }
300 }
301 };
302
RegisterValueAtMaxTsFunction(PerfettoSqlEngine & engine)303 void RegisterValueAtMaxTsFunction(PerfettoSqlEngine& engine) {
304 base::Status status =
305 engine.RegisterSqliteAggregateFunction<ValueAtMaxTs>(nullptr);
306 if (!status.ok()) {
307 PERFETTO_ELOG("Error initializing VALUE_AT_MAX_TS");
308 }
309 }
310
SanitizeMetricMountPaths(const std::vector<std::string> & mount_paths)311 std::vector<std::string> SanitizeMetricMountPaths(
312 const std::vector<std::string>& mount_paths) {
313 std::vector<std::string> sanitized;
314 for (const auto& path : mount_paths) {
315 if (path.empty())
316 continue;
317 sanitized.push_back(path);
318 if (path.back() != '/')
319 sanitized.back().append("/");
320 }
321 return sanitized;
322 }
323
InsertIntoTraceMetricsTable(sqlite3 * db,const std::string & metric_name)324 void InsertIntoTraceMetricsTable(sqlite3* db, const std::string& metric_name) {
325 char* insert_sql = sqlite3_mprintf(
326 "INSERT INTO _trace_metrics(name) VALUES('%q')", metric_name.c_str());
327 char* insert_error = nullptr;
328 sqlite3_exec(db, insert_sql, nullptr, nullptr, &insert_error);
329 sqlite3_free(insert_sql);
330 if (insert_error) {
331 PERFETTO_ELOG("Error registering table: %s", insert_error);
332 sqlite3_free(insert_error);
333 }
334 }
335
GetStdlibPackages()336 sql_modules::NameToPackage GetStdlibPackages() {
337 sql_modules::NameToPackage packages;
338 for (const auto& file_to_sql : stdlib::kFileToSql) {
339 std::string module_name = sql_modules::GetIncludeKey(file_to_sql.path);
340 std::string package_name = sql_modules::GetPackageName(module_name);
341 packages.Insert(package_name, {})
342 .first->push_back({module_name, file_to_sql.sql});
343 }
344 return packages;
345 }
346
GetTraceTimestampBoundsNs(const TraceStorage & storage)347 std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs(
348 const TraceStorage& storage) {
349 int64_t start_ns = std::numeric_limits<int64_t>::max();
350 int64_t end_ns = std::numeric_limits<int64_t>::min();
351 for (auto it = storage.ftrace_event_table().IterateRows(); it; ++it) {
352 start_ns = std::min(it.ts(), start_ns);
353 end_ns = std::max(it.ts(), end_ns);
354 }
355 for (auto it = storage.sched_slice_table().IterateRows(); it; ++it) {
356 start_ns = std::min(it.ts(), start_ns);
357 end_ns = std::max(it.ts() + it.dur(), end_ns);
358 }
359 for (auto it = storage.counter_table().IterateRows(); it; ++it) {
360 start_ns = std::min(it.ts(), start_ns);
361 end_ns = std::max(it.ts(), end_ns);
362 }
363 for (auto it = storage.slice_table().IterateRows(); it; ++it) {
364 start_ns = std::min(it.ts(), start_ns);
365 end_ns = std::max(it.ts() + it.dur(), end_ns);
366 }
367 for (auto it = storage.heap_profile_allocation_table().IterateRows(); it;
368 ++it) {
369 start_ns = std::min(it.ts(), start_ns);
370 end_ns = std::max(it.ts(), end_ns);
371 }
372 for (auto it = storage.thread_state_table().IterateRows(); it; ++it) {
373 start_ns = std::min(it.ts(), start_ns);
374 end_ns = std::max(it.ts() + it.dur(), end_ns);
375 }
376 for (auto it = storage.android_log_table().IterateRows(); it; ++it) {
377 start_ns = std::min(it.ts(), start_ns);
378 end_ns = std::max(it.ts(), end_ns);
379 }
380 for (auto it = storage.heap_graph_object_table().IterateRows(); it; ++it) {
381 start_ns = std::min(it.graph_sample_ts(), start_ns);
382 end_ns = std::max(it.graph_sample_ts(), end_ns);
383 }
384 for (auto it = storage.perf_sample_table().IterateRows(); it; ++it) {
385 start_ns = std::min(it.ts(), start_ns);
386 end_ns = std::max(it.ts(), end_ns);
387 }
388 for (auto it = storage.instruments_sample_table().IterateRows(); it; ++it) {
389 start_ns = std::min(it.ts(), start_ns);
390 end_ns = std::max(it.ts(), end_ns);
391 }
392 for (auto it = storage.cpu_profile_stack_sample_table().IterateRows(); it;
393 ++it) {
394 start_ns = std::min(it.ts(), start_ns);
395 end_ns = std::max(it.ts(), end_ns);
396 }
397 if (start_ns == std::numeric_limits<int64_t>::max()) {
398 return std::make_pair(0, 0);
399 }
400 if (start_ns == end_ns) {
401 end_ns += 1;
402 }
403 return std::make_pair(start_ns, end_ns);
404 }
405
406 } // namespace
407
TraceProcessorImpl(const Config & cfg)408 TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
409 : TraceProcessorStorageImpl(cfg), config_(cfg) {
410 context_.reader_registry->RegisterTraceReader<AndroidDumpstateReader>(
411 kAndroidDumpstateTraceType);
412 context_.android_dumpstate_event_parser =
413 std::make_unique<AndroidDumpstateEventParserImpl>(&context_);
414
415 context_.reader_registry->RegisterTraceReader<AndroidLogReader>(
416 kAndroidLogcatTraceType);
417 context_.android_log_event_parser =
418 std::make_unique<AndroidLogEventParserImpl>(&context_);
419
420 context_.reader_registry->RegisterTraceReader<FuchsiaTraceTokenizer>(
421 kFuchsiaTraceType);
422 context_.fuchsia_record_parser =
423 std::make_unique<FuchsiaTraceParser>(&context_);
424
425 context_.reader_registry->RegisterTraceReader<SystraceTraceParser>(
426 kSystraceTraceType);
427 context_.reader_registry->RegisterTraceReader<NinjaLogParser>(
428 kNinjaLogTraceType);
429
430 context_.reader_registry
431 ->RegisterTraceReader<perf_importer::PerfDataTokenizer>(
432 kPerfDataTraceType);
433 context_.perf_record_parser =
434 std::make_unique<perf_importer::RecordParser>(&context_);
435 context_.spe_record_parser =
436 std::make_unique<perf_importer::SpeRecordParserImpl>(&context_);
437
438 #if PERFETTO_BUILDFLAG(PERFETTO_TP_INSTRUMENTS)
439 context_.reader_registry
440 ->RegisterTraceReader<instruments_importer::InstrumentsXmlTokenizer>(
441 kInstrumentsXmlTraceType);
442 context_.instruments_row_parser =
443 std::make_unique<instruments_importer::RowParser>(&context_);
444 #endif
445
446 if constexpr (util::IsGzipSupported()) {
447 context_.reader_registry->RegisterTraceReader<GzipTraceParser>(
448 kGzipTraceType);
449 context_.reader_registry->RegisterTraceReader<GzipTraceParser>(
450 kCtraceTraceType);
451 context_.reader_registry->RegisterTraceReader<ZipTraceReader>(kZipFile);
452 }
453
454 if constexpr (json::IsJsonSupported()) {
455 context_.reader_registry->RegisterTraceReader<JsonTraceTokenizer>(
456 kJsonTraceType);
457 context_.json_trace_parser =
458 std::make_unique<JsonTraceParserImpl>(&context_);
459
460 context_.reader_registry
461 ->RegisterTraceReader<gecko_importer::GeckoTraceTokenizer>(
462 kGeckoTraceType);
463 context_.gecko_trace_parser =
464 std::make_unique<gecko_importer::GeckoTraceParserImpl>(&context_);
465 }
466
467 context_.reader_registry->RegisterTraceReader<art_method::ArtMethodTokenizer>(
468 kArtMethodTraceType);
469 context_.art_method_parser =
470 std::make_unique<art_method::ArtMethodParserImpl>(&context_);
471
472 context_.reader_registry
473 ->RegisterTraceReader<perf_text_importer::PerfTextTraceTokenizer>(
474 kPerfTextTraceType);
475 context_.perf_text_parser =
476 std::make_unique<perf_text_importer::PerfTextTraceParserImpl>(&context_);
477
478 context_.reader_registry->RegisterTraceReader<TarTraceReader>(kTarTraceType);
479
480 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
481 perf_importer::PerfTracker::GetOrCreate(&context_)->RegisterAuxTokenizer(
482 PERF_AUXTRACE_CS_ETM, etm::CreateEtmV4StreamDemultiplexer);
483 #endif
484
485 const std::vector<std::string> sanitized_extension_paths =
486 SanitizeMetricMountPaths(config_.skip_builtin_metric_paths);
487 std::vector<std::string> skip_prefixes;
488 skip_prefixes.reserve(sanitized_extension_paths.size());
489 for (const auto& path : sanitized_extension_paths) {
490 skip_prefixes.push_back(kMetricProtoRoot + path);
491 }
492
493 // Add metrics to descriptor pool
494 metrics_descriptor_pool_.AddFromFileDescriptorSet(
495 kMetricsDescriptor.data(), kMetricsDescriptor.size(), skip_prefixes);
496 metrics_descriptor_pool_.AddFromFileDescriptorSet(
497 kAllChromeMetricsDescriptor.data(), kAllChromeMetricsDescriptor.size(),
498 skip_prefixes);
499 metrics_descriptor_pool_.AddFromFileDescriptorSet(
500 kAllWebviewMetricsDescriptor.data(), kAllWebviewMetricsDescriptor.size(),
501 skip_prefixes);
502
503 // Add the summary descriptor to the summary pool.
504 {
505 base::Status status = context_.descriptor_pool_->AddFromFileDescriptorSet(
506 kTraceSummaryDescriptor.data(), kTraceSummaryDescriptor.size());
507 PERFETTO_CHECK(status.ok());
508 }
509
510 RegisterAdditionalModules(&context_);
511 InitPerfettoSqlEngine();
512
513 sqlite_objects_post_prelude_ = engine_->SqliteRegisteredObjectCount();
514
515 bool skip_all_sql = std::find(config_.skip_builtin_metric_paths.begin(),
516 config_.skip_builtin_metric_paths.end(),
517 "") != config_.skip_builtin_metric_paths.end();
518 if (!skip_all_sql) {
519 for (const auto& file_to_sql : sql_metrics::kFileToSql) {
520 if (base::StartsWithAny(file_to_sql.path, sanitized_extension_paths))
521 continue;
522 RegisterMetric(file_to_sql.path, file_to_sql.sql);
523 }
524 }
525 }
526
527 TraceProcessorImpl::~TraceProcessorImpl() = default;
528
529 // =================================================================
530 // | TraceProcessorStorage implementation starts here |
531 // =================================================================
532
Parse(TraceBlobView blob)533 base::Status TraceProcessorImpl::Parse(TraceBlobView blob) {
534 bytes_parsed_ += blob.size();
535 return TraceProcessorStorageImpl::Parse(std::move(blob));
536 }
537
Flush()538 void TraceProcessorImpl::Flush() {
539 TraceProcessorStorageImpl::Flush();
540 BuildBoundsTable(engine_->sqlite_engine()->db(),
541 GetTraceTimestampBoundsNs(*context_.storage));
542 }
543
NotifyEndOfFile()544 base::Status TraceProcessorImpl::NotifyEndOfFile() {
545 if (notify_eof_called_) {
546 const char kMessage[] =
547 "NotifyEndOfFile should only be called once. Try calling Flush instead "
548 "if trying to commit the contents of the trace to tables.";
549 PERFETTO_ELOG(kMessage);
550 return base::ErrStatus(kMessage);
551 }
552 notify_eof_called_ = true;
553
554 if (current_trace_name_.empty())
555 current_trace_name_ = "Unnamed trace";
556
557 // Last opportunity to flush all pending data.
558 Flush();
559
560 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
561 if (context_.etm_tracker) {
562 RETURN_IF_ERROR(etm::EtmTracker::GetOrCreate(&context_)->Finalize());
563 }
564 #endif
565
566 RETURN_IF_ERROR(TraceProcessorStorageImpl::NotifyEndOfFile());
567 if (context_.perf_tracker) {
568 perf_importer::PerfTracker::GetOrCreate(&context_)->NotifyEndOfFile();
569 }
570 context_.storage->ShrinkToFitTables();
571
572 // Rebuild the bounds table once everything has been completed: we do this
573 // so that if any data was added to tables in
574 // TraceProcessorStorageImpl::NotifyEndOfFile, this will be counted in
575 // trace bounds: this is important for parsers like ninja which wait until
576 // the end to flush all their data.
577 BuildBoundsTable(engine_->sqlite_engine()->db(),
578 GetTraceTimestampBoundsNs(*context_.storage));
579
580 TraceProcessorStorageImpl::DestroyContext();
581
582 IncludeAfterEofPrelude();
583 sqlite_objects_post_prelude_ = engine_->SqliteRegisteredObjectCount();
584 return base::OkStatus();
585 }
586
587 // =================================================================
588 // | PerfettoSQL related functionality starts here |
589 // =================================================================
590
ExecuteQuery(const std::string & sql)591 Iterator TraceProcessorImpl::ExecuteQuery(const std::string& sql) {
592 PERFETTO_TP_TRACE(metatrace::Category::API_TIMELINE, "EXECUTE_QUERY",
593 [&](metatrace::Record* r) { r->AddArg("query", sql); });
594
595 uint32_t sql_stats_row =
596 context_.storage->mutable_sql_stats()->RecordQueryBegin(
597 sql, base::GetWallTimeNs().count());
598 std::string non_breaking_sql = base::ReplaceAll(sql, "\u00A0", " ");
599 base::StatusOr<PerfettoSqlEngine::ExecutionResult> result =
600 engine_->ExecuteUntilLastStatement(
601 SqlSource::FromExecuteQuery(std::move(non_breaking_sql)));
602 std::unique_ptr<IteratorImpl> impl(
603 new IteratorImpl(this, std::move(result), sql_stats_row));
604 return Iterator(std::move(impl));
605 }
606
RegisterSqlPackage(SqlPackage sql_package)607 base::Status TraceProcessorImpl::RegisterSqlPackage(SqlPackage sql_package) {
608 sql_modules::RegisteredPackage new_package;
609 std::string name = sql_package.name;
610 if (engine_->FindPackage(name) && !sql_package.allow_override) {
611 return base::ErrStatus(
612 "Package '%s' is already registered. Choose a different name.\n"
613 "If you want to replace the existing package using trace processor "
614 "shell, you need to pass the --dev flag and use "
615 "--override-sql-module "
616 "to pass the module path.",
617 name.c_str());
618 }
619 for (auto const& module_name_and_sql : sql_package.modules) {
620 if (sql_modules::GetPackageName(module_name_and_sql.first) != name) {
621 return base::ErrStatus(
622 "Module name doesn't match the package name. First part of module "
623 "name should be package name. Import key: '%s', package name: '%s'.",
624 module_name_and_sql.first.c_str(), name.c_str());
625 }
626 new_package.modules.Insert(module_name_and_sql.first,
627 {module_name_and_sql.second, false});
628 }
629 manually_registered_sql_packages_.push_back(SqlPackage(sql_package));
630 engine_->RegisterPackage(name, std::move(new_package));
631 return base::OkStatus();
632 }
633
RegisterSqlModule(SqlModule module)634 base::Status TraceProcessorImpl::RegisterSqlModule(SqlModule module) {
635 SqlPackage package;
636 package.name = std::move(module.name);
637 package.modules = std::move(module.files);
638 package.allow_override = module.allow_module_override;
639 return RegisterSqlPackage(package);
640 }
641
642 // =================================================================
643 // | Trace-based metrics (v2) related functionality starts here |
644 // =================================================================
645
Summarize(const TraceSummaryComputationSpec & computation,const std::vector<TraceSummarySpecBytes> & specs,std::vector<uint8_t> * output,const TraceSummaryOutputSpec & output_spec)646 base::Status TraceProcessorImpl::Summarize(
647 const TraceSummaryComputationSpec& computation,
648 const std::vector<TraceSummarySpecBytes>& specs,
649 std::vector<uint8_t>* output,
650 const TraceSummaryOutputSpec& output_spec) {
651 return summary::Summarize(this, *context_.descriptor_pool_, computation,
652 specs, output, output_spec);
653 }
654
655 // =================================================================
656 // | Metatracing related functionality starts here |
657 // =================================================================
658
EnableMetatrace(MetatraceConfig config)659 void TraceProcessorImpl::EnableMetatrace(MetatraceConfig config) {
660 metatrace::Enable(config);
661 }
662
663 // =================================================================
664 // | Experimental |
665 // =================================================================
666
AnalyzeStructuredQueries(const std::vector<StructuredQueryBytes> & sqs,std::vector<AnalyzedStructuredQuery> * output)667 base::Status TraceProcessorImpl::AnalyzeStructuredQueries(
668 const std::vector<StructuredQueryBytes>& sqs,
669 std::vector<AnalyzedStructuredQuery>* output) {
670 auto opt_idx = metrics_descriptor_pool_.FindDescriptorIdx(
671 ".perfetto.protos.TraceSummarySpec");
672 if (!opt_idx) {
673 metrics_descriptor_pool_.AddFromFileDescriptorSet(
674 kTraceSummaryDescriptor.data(), kTraceSummaryDescriptor.size());
675 }
676 perfetto_sql::generator::StructuredQueryGenerator sqg;
677 for (const auto& sq : sqs) {
678 AnalyzedStructuredQuery analyzed_sq;
679 ASSIGN_OR_RETURN(analyzed_sq.sql, sqg.Generate(sq.ptr, sq.size));
680 analyzed_sq.textproto =
681 perfetto::trace_processor::protozero_to_text::ProtozeroToText(
682 metrics_descriptor_pool_,
683 ".perfetto.protos.PerfettoSqlStructuredQuery",
684 protozero::ConstBytes{sq.ptr, sq.size},
685 perfetto::trace_processor::protozero_to_text::kIncludeNewLines);
686 analyzed_sq.modules = sqg.ComputeReferencedModules();
687 analyzed_sq.preambles = sqg.ComputePreambles();
688 sqg.AddQuery(sq.ptr, sq.size);
689 output->push_back(analyzed_sq);
690 }
691 return base::OkStatus();
692 }
693
694 namespace {
695
696 class StringInterner {
697 public:
StringInterner(protos::pbzero::PerfettoMetatrace & event,base::FlatHashMap<std::string,uint64_t> & interned_strings)698 StringInterner(protos::pbzero::PerfettoMetatrace& event,
699 base::FlatHashMap<std::string, uint64_t>& interned_strings)
700 : event_(event), interned_strings_(interned_strings) {}
701
~StringInterner()702 ~StringInterner() {
703 for (const auto& interned_string : new_interned_strings_) {
704 auto* interned_string_proto = event_.add_interned_strings();
705 interned_string_proto->set_iid(interned_string.first);
706 interned_string_proto->set_value(interned_string.second);
707 }
708 }
709
InternString(const std::string & str)710 uint64_t InternString(const std::string& str) {
711 uint64_t new_iid = interned_strings_.size();
712 auto insert_result = interned_strings_.Insert(str, new_iid);
713 if (insert_result.second) {
714 new_interned_strings_.emplace_back(new_iid, str);
715 }
716 return *insert_result.first;
717 }
718
719 private:
720 protos::pbzero::PerfettoMetatrace& event_;
721 base::FlatHashMap<std::string, uint64_t>& interned_strings_;
722
723 base::SmallVector<std::pair<uint64_t, std::string>, 16> new_interned_strings_;
724 };
725
726 } // namespace
727
DisableAndReadMetatrace(std::vector<uint8_t> * trace_proto)728 base::Status TraceProcessorImpl::DisableAndReadMetatrace(
729 std::vector<uint8_t>* trace_proto) {
730 protozero::HeapBuffered<protos::pbzero::Trace> trace;
731
732 auto* clock_snapshot = trace->add_packet()->set_clock_snapshot();
733 for (const auto& [clock_id, ts] : base::CaptureClockSnapshots()) {
734 auto* clock = clock_snapshot->add_clocks();
735 clock->set_clock_id(clock_id);
736 clock->set_timestamp(ts);
737 }
738
739 auto tid = static_cast<uint32_t>(base::GetThreadId());
740 base::FlatHashMap<std::string, uint64_t> interned_strings;
741 metatrace::DisableAndReadBuffer(
742 [&trace, &interned_strings, tid](metatrace::Record* record) {
743 auto* packet = trace->add_packet();
744 packet->set_timestamp(record->timestamp_ns);
745 auto* evt = packet->set_perfetto_metatrace();
746
747 StringInterner interner(*evt, interned_strings);
748
749 evt->set_event_name_iid(interner.InternString(record->event_name));
750 evt->set_event_duration_ns(record->duration_ns);
751 evt->set_thread_id(tid);
752
753 if (record->args_buffer_size == 0)
754 return;
755
756 base::StringSplitter s(
757 record->args_buffer, record->args_buffer_size, '\0',
758 base::StringSplitter::EmptyTokenMode::ALLOW_EMPTY_TOKENS);
759 for (; s.Next();) {
760 auto* arg_proto = evt->add_args();
761 arg_proto->set_key_iid(interner.InternString(s.cur_token()));
762
763 bool has_next = s.Next();
764 PERFETTO_CHECK(has_next);
765 arg_proto->set_value_iid(interner.InternString(s.cur_token()));
766 }
767 });
768 *trace_proto = trace.SerializeAsArray();
769 return base::OkStatus();
770 }
771
772 // =================================================================
773 // | Advanced functionality starts here |
774 // =================================================================
775
GetCurrentTraceName()776 std::string TraceProcessorImpl::GetCurrentTraceName() {
777 if (current_trace_name_.empty())
778 return "";
779 auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
780 return current_trace_name_ + size;
781 }
782
SetCurrentTraceName(const std::string & name)783 void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
784 current_trace_name_ = name;
785 }
786
RegisterFileContent(const std::string & path,TraceBlobView content)787 base::Status TraceProcessorImpl::RegisterFileContent(
788 [[maybe_unused]] const std::string& path,
789 [[maybe_unused]] TraceBlobView content) {
790 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
791 return etm::FileTracker::GetOrCreate(&context_)->AddFile(path,
792 std::move(content));
793 #else
794 return base::OkStatus();
795 #endif
796 }
797
InterruptQuery()798 void TraceProcessorImpl::InterruptQuery() {
799 if (!engine_->sqlite_engine()->db())
800 return;
801 query_interrupted_.store(true);
802 sqlite3_interrupt(engine_->sqlite_engine()->db());
803 }
804
RestoreInitialTables()805 size_t TraceProcessorImpl::RestoreInitialTables() {
806 // We should always have at least as many objects now as we did in the
807 // constructor.
808 uint64_t registered_count_before = engine_->SqliteRegisteredObjectCount();
809 PERFETTO_CHECK(registered_count_before >= sqlite_objects_post_prelude_);
810
811 InitPerfettoSqlEngine();
812
813 // The registered count should now be the same as it was in the constructor.
814 uint64_t registered_count_after = engine_->SqliteRegisteredObjectCount();
815 PERFETTO_CHECK(registered_count_after == sqlite_objects_post_prelude_);
816 return static_cast<size_t>(registered_count_before - registered_count_after);
817 }
818
819 // =================================================================
820 // | Trace-based metrics (v1) related functionality starts here |
821 // =================================================================
822
RegisterMetric(const std::string & path,const std::string & sql)823 base::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
824 const std::string& sql) {
825 // Check if the metric with the given path already exists and if it does,
826 // just update the SQL associated with it.
827 auto it = std::find_if(
828 sql_metrics_.begin(), sql_metrics_.end(),
829 [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
830 if (it != sql_metrics_.end()) {
831 it->sql = sql;
832 return base::OkStatus();
833 }
834
835 auto sep_idx = path.rfind('/');
836 std::string basename =
837 sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
838
839 auto sql_idx = basename.rfind(".sql");
840 if (sql_idx == std::string::npos) {
841 return base::ErrStatus("Unable to find .sql extension for metric");
842 }
843 auto no_ext_name = basename.substr(0, sql_idx);
844
845 metrics::SqlMetricFile metric;
846 metric.path = path;
847 metric.sql = sql;
848
849 if (IsRootMetricField(no_ext_name)) {
850 metric.proto_field_name = no_ext_name;
851 metric.output_table_name = no_ext_name + "_output";
852
853 auto field_it_and_inserted =
854 proto_field_to_sql_metric_path_.emplace(*metric.proto_field_name, path);
855 if (!field_it_and_inserted.second) {
856 // We already had a metric with this field name in the map. However, if
857 // this was the case, we should have found the metric in
858 // |path_to_sql_metric_file_| above if we are simply overriding the
859 // metric. Return an error since this means we have two different SQL
860 // files which are trying to output the same metric.
861 const auto& prev_path = field_it_and_inserted.first->second;
862 PERFETTO_DCHECK(prev_path != path);
863 return base::ErrStatus(
864 "RegisterMetric Error: Metric paths %s (which is already "
865 "registered) "
866 "and %s are both trying to output the proto field %s",
867 prev_path.c_str(), path.c_str(), metric.proto_field_name->c_str());
868 }
869 }
870
871 if (metric.proto_field_name) {
872 InsertIntoTraceMetricsTable(engine_->sqlite_engine()->db(),
873 *metric.proto_field_name);
874 }
875 sql_metrics_.emplace_back(metric);
876 return base::OkStatus();
877 }
878
ExtendMetricsProto(const uint8_t * data,size_t size)879 base::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
880 size_t size) {
881 return ExtendMetricsProto(data, size, /*skip_prefixes*/ {});
882 }
883
ExtendMetricsProto(const uint8_t * data,size_t size,const std::vector<std::string> & skip_prefixes)884 base::Status TraceProcessorImpl::ExtendMetricsProto(
885 const uint8_t* data,
886 size_t size,
887 const std::vector<std::string>& skip_prefixes) {
888 RETURN_IF_ERROR(metrics_descriptor_pool_.AddFromFileDescriptorSet(
889 data, size, skip_prefixes));
890 RETURN_IF_ERROR(RegisterAllProtoBuilderFunctions(
891 &metrics_descriptor_pool_, &proto_fn_name_to_path_, engine_.get(), this));
892 return base::OkStatus();
893 }
894
ComputeMetric(const std::vector<std::string> & metric_names,std::vector<uint8_t> * metrics_proto)895 base::Status TraceProcessorImpl::ComputeMetric(
896 const std::vector<std::string>& metric_names,
897 std::vector<uint8_t>* metrics_proto) {
898 auto opt_idx = metrics_descriptor_pool_.FindDescriptorIdx(
899 ".perfetto.protos.TraceMetrics");
900 if (!opt_idx.has_value())
901 return base::Status("Root metrics proto descriptor not found");
902
903 const auto& root_descriptor =
904 metrics_descriptor_pool_.descriptors()[opt_idx.value()];
905 return metrics::ComputeMetrics(engine_.get(), metric_names, sql_metrics_,
906 metrics_descriptor_pool_, root_descriptor,
907 metrics_proto);
908 }
909
ComputeMetricText(const std::vector<std::string> & metric_names,TraceProcessor::MetricResultFormat format,std::string * metrics_string)910 base::Status TraceProcessorImpl::ComputeMetricText(
911 const std::vector<std::string>& metric_names,
912 TraceProcessor::MetricResultFormat format,
913 std::string* metrics_string) {
914 std::vector<uint8_t> metrics_proto;
915 base::Status status = ComputeMetric(metric_names, &metrics_proto);
916 if (!status.ok())
917 return status;
918 switch (format) {
919 case TraceProcessor::MetricResultFormat::kProtoText:
920 *metrics_string = protozero_to_text::ProtozeroToText(
921 metrics_descriptor_pool_, ".perfetto.protos.TraceMetrics",
922 protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
923 protozero_to_text::kIncludeNewLines);
924 break;
925 case TraceProcessor::MetricResultFormat::kJson:
926 *metrics_string = protozero_to_json::ProtozeroToJson(
927 metrics_descriptor_pool_, ".perfetto.protos.TraceMetrics",
928 protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
929 protozero_to_json::kPretty | protozero_to_json::kInlineErrors |
930 protozero_to_json::kInlineAnnotations);
931 break;
932 }
933 return status;
934 }
935
GetMetricDescriptors()936 std::vector<uint8_t> TraceProcessorImpl::GetMetricDescriptors() {
937 return metrics_descriptor_pool_.SerializeAsDescriptorSet();
938 }
939
InitPerfettoSqlEngine()940 void TraceProcessorImpl::InitPerfettoSqlEngine() {
941 engine_ = std::make_unique<PerfettoSqlEngine>(
942 context_.storage->mutable_string_pool(), config_.enable_extra_checks);
943 sqlite3* db = engine_->sqlite_engine()->db();
944 sqlite3_str_split_init(db);
945
946 // Register SQL functions only used in local development instances.
947 if (config_.enable_dev_features) {
948 RegisterFunction<WriteFile>(engine_.get(), "WRITE_FILE", 2);
949 }
950 RegisterFunction<Glob>(engine_.get(), "glob", 2);
951 RegisterFunction<Hash>(engine_.get(), "HASH", -1);
952 RegisterFunction<Base64Encode>(engine_.get(), "BASE64_ENCODE", 1);
953 RegisterFunction<Demangle>(engine_.get(), "DEMANGLE", 1);
954 RegisterFunction<SourceGeq>(engine_.get(), "SOURCE_GEQ", -1);
955 RegisterFunction<TablePtrBind>(engine_.get(), "__intrinsic_table_ptr_bind",
956 -1);
957 RegisterFunction<ExportJson>(engine_.get(), "EXPORT_JSON", 1,
958 context_.storage.get(), false);
959 RegisterFunction<ExtractArg>(engine_.get(), "EXTRACT_ARG", 2,
960 context_.storage.get());
961 RegisterFunction<AbsTimeStr>(engine_.get(), "ABS_TIME_STR", 1,
962 context_.clock_converter.get());
963 RegisterFunction<Reverse>(engine_.get(), "REVERSE", 1);
964 RegisterFunction<ToMonotonic>(engine_.get(), "TO_MONOTONIC", 1,
965 context_.clock_converter.get());
966 RegisterFunction<ToRealtime>(engine_.get(), "TO_REALTIME", 1,
967 context_.clock_converter.get());
968 RegisterFunction<ToTimecode>(engine_.get(), "TO_TIMECODE", 1);
969 RegisterFunction<CreateFunction>(engine_.get(), "CREATE_FUNCTION", 3,
970 engine_.get());
971 RegisterFunction<CreateViewFunction>(engine_.get(), "CREATE_VIEW_FUNCTION", 3,
972 engine_.get());
973 RegisterFunction<ExperimentalMemoize>(engine_.get(), "EXPERIMENTAL_MEMOIZE",
974 1, engine_.get());
975 RegisterFunction<Import>(
976 engine_.get(), "IMPORT", 1,
977 std::make_unique<Import::Context>(Import::Context{engine_.get()}));
978 RegisterFunction<ToFtrace>(
979 engine_.get(), "TO_FTRACE", 1,
980 std::make_unique<ToFtrace::Context>(ToFtrace::Context{
981 context_.storage.get(), SystraceSerializer(&context_)}));
982
983 if constexpr (regex::IsRegexSupported()) {
984 RegisterFunction<Regex>(engine_.get(), "regexp", 2);
985 }
986 // Old style function registration.
987 // TODO(lalitm): migrate this over to using RegisterFunction once aggregate
988 // functions are supported.
989 RegisterValueAtMaxTsFunction(*engine_);
990 {
991 base::Status status = RegisterLastNonNullFunction(*engine_);
992 if (!status.ok())
993 PERFETTO_FATAL("%s", status.c_message());
994 }
995 {
996 base::Status status = RegisterStackFunctions(engine_.get(), &context_);
997 if (!status.ok())
998 PERFETTO_FATAL("%s", status.c_message());
999 }
1000 {
1001 base::Status status = RegisterStripHexFunction(engine_.get(), &context_);
1002 if (!status.ok())
1003 PERFETTO_FATAL("%s", status.c_message());
1004 }
1005 {
1006 base::Status status = PprofFunctions::Register(*engine_, &context_);
1007 if (!status.ok())
1008 PERFETTO_FATAL("%s", status.c_message());
1009 }
1010 {
1011 base::Status status = RegisterLayoutFunctions(*engine_);
1012 if (!status.ok())
1013 PERFETTO_FATAL("%s", status.c_message());
1014 }
1015 {
1016 base::Status status = RegisterMathFunctions(*engine_);
1017 if (!status.ok())
1018 PERFETTO_FATAL("%s", status.c_message());
1019 }
1020 {
1021 base::Status status = RegisterBase64Functions(*engine_);
1022 if (!status.ok())
1023 PERFETTO_FATAL("%s", status.c_message());
1024 }
1025 {
1026 base::Status status = RegisterTypeBuilderFunctions(*engine_);
1027 if (!status.ok())
1028 PERFETTO_FATAL("%s", status.c_message());
1029 }
1030 {
1031 base::Status status = RegisterGraphScanFunctions(
1032 *engine_, context_.storage->mutable_string_pool());
1033 if (!status.ok())
1034 PERFETTO_FATAL("%s", status.c_message());
1035 }
1036 {
1037 base::Status status = RegisterGraphTraversalFunctions(
1038 *engine_, *context_.storage->mutable_string_pool());
1039 if (!status.ok())
1040 PERFETTO_FATAL("%s", status.c_message());
1041 }
1042 {
1043 base::Status status = perfetto_sql::RegisterIntervalIntersectFunctions(
1044 *engine_, context_.storage->mutable_string_pool());
1045 }
1046 {
1047 base::Status status = perfetto_sql::RegisterCounterIntervalsFunctions(
1048 *engine_, context_.storage->mutable_string_pool());
1049 }
1050
1051 TraceStorage* storage = context_.storage.get();
1052
1053 // Operator tables.
1054 engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
1055 "span_join",
1056 std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
1057 engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
1058 "span_left_join",
1059 std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
1060 engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
1061 "span_outer_join",
1062 std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
1063 engine_->sqlite_engine()->RegisterVirtualTableModule<WindowOperatorModule>(
1064 "window", std::make_unique<WindowOperatorModule::Context>());
1065 engine_->sqlite_engine()->RegisterVirtualTableModule<CounterMipmapOperator>(
1066 "__intrinsic_counter_mipmap",
1067 std::make_unique<CounterMipmapOperator::Context>(engine_.get()));
1068 engine_->sqlite_engine()->RegisterVirtualTableModule<SliceMipmapOperator>(
1069 "__intrinsic_slice_mipmap",
1070 std::make_unique<SliceMipmapOperator::Context>(engine_.get()));
1071 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
1072 engine_->sqlite_engine()
1073 ->RegisterVirtualTableModule<etm::EtmDecodeTraceVtable>(
1074 "__intrinsic_etm_decode_trace", storage);
1075 engine_->sqlite_engine()
1076 ->RegisterVirtualTableModule<etm::EtmIterateRangeVtable>(
1077 "__intrinsic_etm_iterate_instruction_range", storage);
1078 #endif
1079
1080 // Register stdlib packages.
1081 auto packages = GetStdlibPackages();
1082 for (auto package = packages.GetIterator(); package; ++package) {
1083 base::Status status =
1084 RegisterSqlPackage({/*name=*/package.key(), /*modules=*/package.value(),
1085 /*allow_override=*/false});
1086 if (!status.ok())
1087 PERFETTO_ELOG("%s", status.c_message());
1088 }
1089
1090 // Register metrics functions.
1091 {
1092 base::Status status =
1093 engine_->RegisterSqliteAggregateFunction<metrics::RepeatedField>(
1094 nullptr);
1095 if (!status.ok())
1096 PERFETTO_ELOG("%s", status.c_message());
1097 }
1098
1099 RegisterFunction<metrics::NullIfEmpty>(engine_.get(), "NULL_IF_EMPTY", 1);
1100 RegisterFunction<metrics::UnwrapMetricProto>(engine_.get(),
1101 "UNWRAP_METRIC_PROTO", 2);
1102 RegisterFunction<metrics::RunMetric>(
1103 engine_.get(), "RUN_METRIC", -1,
1104 std::make_unique<metrics::RunMetric::Context>(
1105 metrics::RunMetric::Context{engine_.get(), &sql_metrics_}));
1106
1107 // Legacy tables.
1108 engine_->sqlite_engine()->RegisterVirtualTableModule<SqlStatsModule>(
1109 "sqlstats", storage);
1110 engine_->sqlite_engine()->RegisterVirtualTableModule<StatsModule>("stats",
1111 storage);
1112 engine_->sqlite_engine()->RegisterVirtualTableModule<TablePointerModule>(
1113 "__intrinsic_table_ptr", nullptr);
1114
1115 // New style db-backed tables.
1116 // Note: if adding a table here which might potentially contain many rows
1117 // (O(rows in sched/slice/counter)), then consider calling ShrinkToFit on
1118 // that table in TraceStorage::ShrinkToFitTables.
1119 RegisterStaticTable(storage->mutable_machine_table());
1120 RegisterStaticTable(storage->mutable_arg_table());
1121 RegisterStaticTable(storage->mutable_chrome_raw_table());
1122 RegisterStaticTable(storage->mutable_ftrace_event_table());
1123 RegisterStaticTable(storage->mutable_thread_table());
1124 RegisterStaticTable(storage->mutable_process_table());
1125 RegisterStaticTable(storage->mutable_filedescriptor_table());
1126 RegisterStaticTable(storage->mutable_trace_file_table());
1127
1128 RegisterStaticTable(storage->mutable_slice_table());
1129 RegisterStaticTable(storage->mutable_flow_table());
1130 RegisterStaticTable(storage->mutable_sched_slice_table());
1131 RegisterStaticTable(storage->mutable_spurious_sched_wakeup_table());
1132 RegisterStaticTable(storage->mutable_thread_state_table());
1133
1134 RegisterStaticTable(storage->mutable_track_table());
1135
1136 RegisterStaticTable(storage->mutable_counter_table());
1137
1138 RegisterStaticTable(storage->mutable_gpu_counter_group_table());
1139
1140 RegisterStaticTable(storage->mutable_heap_graph_object_table());
1141 RegisterStaticTable(storage->mutable_heap_graph_reference_table());
1142 RegisterStaticTable(storage->mutable_heap_graph_class_table());
1143
1144 RegisterStaticTable(storage->mutable_symbol_table());
1145 RegisterStaticTable(storage->mutable_heap_profile_allocation_table());
1146 RegisterStaticTable(storage->mutable_cpu_profile_stack_sample_table());
1147 RegisterStaticTable(storage->mutable_perf_session_table());
1148 RegisterStaticTable(storage->mutable_perf_sample_table());
1149 RegisterStaticTable(storage->mutable_instruments_sample_table());
1150 RegisterStaticTable(storage->mutable_stack_profile_callsite_table());
1151 RegisterStaticTable(storage->mutable_stack_profile_mapping_table());
1152 RegisterStaticTable(storage->mutable_stack_profile_frame_table());
1153 RegisterStaticTable(storage->mutable_package_list_table());
1154 RegisterStaticTable(storage->mutable_profiler_smaps_table());
1155
1156 RegisterStaticTable(storage->mutable_android_log_table());
1157 RegisterStaticTable(storage->mutable_android_dumpstate_table());
1158 RegisterStaticTable(storage->mutable_android_game_intervenion_list_table());
1159 RegisterStaticTable(storage->mutable_android_key_events_table());
1160 RegisterStaticTable(storage->mutable_android_motion_events_table());
1161 RegisterStaticTable(storage->mutable_android_input_event_dispatch_table());
1162
1163 RegisterStaticTable(storage->mutable_vulkan_memory_allocations_table());
1164
1165 RegisterStaticTable(storage->mutable_android_network_packets_table());
1166
1167 RegisterStaticTable(storage->mutable_v8_isolate_table());
1168 RegisterStaticTable(storage->mutable_v8_js_script_table());
1169 RegisterStaticTable(storage->mutable_v8_wasm_script_table());
1170 RegisterStaticTable(storage->mutable_v8_js_function_table());
1171 RegisterStaticTable(storage->mutable_v8_js_code_table());
1172 RegisterStaticTable(storage->mutable_v8_internal_code_table());
1173 RegisterStaticTable(storage->mutable_v8_wasm_code_table());
1174 RegisterStaticTable(storage->mutable_v8_regexp_code_table());
1175
1176 RegisterStaticTable(storage->mutable_jit_code_table());
1177 RegisterStaticTable(storage->mutable_jit_frame_table());
1178
1179 RegisterStaticTable(storage->mutable_etm_v4_configuration_table());
1180 RegisterStaticTable(storage->mutable_etm_v4_session_table());
1181 RegisterStaticTable(storage->mutable_etm_v4_trace_table());
1182 RegisterStaticTable(storage->mutable_elf_file_table());
1183 RegisterStaticTable(storage->mutable_file_table());
1184
1185 RegisterStaticTable(storage->mutable_spe_record_table());
1186 RegisterStaticTable(storage->mutable_mmap_record_table());
1187
1188 RegisterStaticTable(storage->mutable_inputmethod_clients_table());
1189 RegisterStaticTable(storage->mutable_inputmethod_manager_service_table());
1190 RegisterStaticTable(storage->mutable_inputmethod_service_table());
1191
1192 RegisterStaticTable(storage->mutable_surfaceflinger_layers_snapshot_table());
1193 RegisterStaticTable(storage->mutable_surfaceflinger_layer_table());
1194 RegisterStaticTable(storage->mutable_surfaceflinger_transactions_table());
1195
1196 RegisterStaticTable(storage->mutable_viewcapture_table());
1197 RegisterStaticTable(storage->mutable_viewcapture_view_table());
1198
1199 RegisterStaticTable(storage->mutable_windowmanager_table());
1200
1201 RegisterStaticTable(
1202 storage->mutable_window_manager_shell_transitions_table());
1203 RegisterStaticTable(
1204 storage->mutable_window_manager_shell_transition_handlers_table());
1205 RegisterStaticTable(
1206 storage->mutable_window_manager_shell_transition_protos_table());
1207
1208 RegisterStaticTable(storage->mutable_protolog_table());
1209
1210 RegisterStaticTable(storage->mutable_metadata_table());
1211 RegisterStaticTable(storage->mutable_cpu_table());
1212 RegisterStaticTable(storage->mutable_cpu_freq_table());
1213 RegisterStaticTable(storage->mutable_clock_snapshot_table());
1214
1215 RegisterStaticTable(storage->mutable_memory_snapshot_table());
1216 RegisterStaticTable(storage->mutable_process_memory_snapshot_table());
1217 RegisterStaticTable(storage->mutable_memory_snapshot_node_table());
1218 RegisterStaticTable(storage->mutable_memory_snapshot_edge_table());
1219
1220 RegisterStaticTable(storage->mutable_experimental_proto_path_table());
1221 RegisterStaticTable(storage->mutable_experimental_proto_content_table());
1222
1223 RegisterStaticTable(
1224 storage->mutable_experimental_missing_chrome_processes_table());
1225
1226 // Tables dynamically generated at query time.
1227 engine_->RegisterStaticTableFunction(
1228 std::make_unique<ExperimentalFlamegraph>(&context_));
1229 engine_->RegisterStaticTableFunction(
1230 std::make_unique<ExperimentalSliceLayout>(
1231 context_.storage->mutable_string_pool(), &storage->slice_table()));
1232 engine_->RegisterStaticTableFunction(std::make_unique<TableInfo>(
1233 context_.storage->mutable_string_pool(), engine_.get()));
1234 engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
1235 Ancestor::Type::kSlice, context_.storage.get()));
1236 engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
1237 Ancestor::Type::kStackProfileCallsite, context_.storage.get()));
1238 engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
1239 Ancestor::Type::kSliceByStack, context_.storage.get()));
1240 engine_->RegisterStaticTableFunction(std::make_unique<Descendant>(
1241 Descendant::Type::kSlice, context_.storage.get()));
1242 engine_->RegisterStaticTableFunction(std::make_unique<Descendant>(
1243 Descendant::Type::kSliceByStack, context_.storage.get()));
1244 engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
1245 ConnectedFlow::Mode::kDirectlyConnectedFlow, context_.storage.get()));
1246 engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
1247 ConnectedFlow::Mode::kPrecedingFlow, context_.storage.get()));
1248 engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
1249 ConnectedFlow::Mode::kFollowingFlow, context_.storage.get()));
1250 engine_->RegisterStaticTableFunction(
1251 std::make_unique<ExperimentalAnnotatedStack>(&context_));
1252 engine_->RegisterStaticTableFunction(
1253 std::make_unique<ExperimentalFlatSlice>(&context_));
1254 engine_->RegisterStaticTableFunction(std::make_unique<DfsWeightBounded>(
1255 context_.storage->mutable_string_pool()));
1256 engine_->RegisterStaticTableFunction(
1257 std::make_unique<WinscopeProtoToArgsWithDefaults>(
1258 context_.storage->mutable_string_pool(), engine_.get(), &context_));
1259
1260 // Value table aggregate functions.
1261 engine_->RegisterSqliteAggregateFunction<DominatorTree>(
1262 context_.storage->mutable_string_pool());
1263 engine_->RegisterSqliteAggregateFunction<StructuralTreePartition>(
1264 context_.storage->mutable_string_pool());
1265
1266 // Metrics.
1267 {
1268 auto status = RegisterAllProtoBuilderFunctions(&metrics_descriptor_pool_,
1269 &proto_fn_name_to_path_,
1270 engine_.get(), this);
1271 if (!status.ok()) {
1272 PERFETTO_FATAL("%s", status.c_message());
1273 }
1274 }
1275
1276 // Import prelude package.
1277 IncludeBeforeEofPrelude();
1278 if (notify_eof_called_) {
1279 IncludeAfterEofPrelude();
1280 }
1281
1282 for (const auto& metric : sql_metrics_) {
1283 if (metric.proto_field_name) {
1284 InsertIntoTraceMetricsTable(db, *metric.proto_field_name);
1285 }
1286 }
1287
1288 // Fill trace bounds table.
1289 BuildBoundsTable(db, GetTraceTimestampBoundsNs(*context_.storage));
1290
1291 // Reregister manually added stdlib packages.
1292 for (const auto& package : manually_registered_sql_packages_) {
1293 RegisterSqlPackage(package);
1294 }
1295 }
1296
IncludeBeforeEofPrelude()1297 void TraceProcessorImpl::IncludeBeforeEofPrelude() {
1298 auto result = engine_->Execute(SqlSource::FromTraceProcessorImplementation(
1299 "INCLUDE PERFETTO MODULE prelude.before_eof.*"));
1300 if (!result.status().ok()) {
1301 PERFETTO_FATAL("Failed to import prelude: %s", result.status().c_message());
1302 }
1303 }
1304
IncludeAfterEofPrelude()1305 void TraceProcessorImpl::IncludeAfterEofPrelude() {
1306 auto result = engine_->Execute(SqlSource::FromTraceProcessorImplementation(
1307 "INCLUDE PERFETTO MODULE prelude.after_eof.*"));
1308 if (!result.status().ok()) {
1309 PERFETTO_FATAL("Failed to import prelude: %s", result.status().c_message());
1310 }
1311 }
1312
IsRootMetricField(const std::string & metric_name)1313 bool TraceProcessorImpl::IsRootMetricField(const std::string& metric_name) {
1314 std::optional<uint32_t> desc_idx = metrics_descriptor_pool_.FindDescriptorIdx(
1315 ".perfetto.protos.TraceMetrics");
1316 if (!desc_idx.has_value())
1317 return false;
1318 const auto* field_idx =
1319 metrics_descriptor_pool_.descriptors()[*desc_idx].FindFieldByName(
1320 metric_name);
1321 return field_idx != nullptr;
1322 }
1323
1324 } // namespace perfetto::trace_processor
1325