• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <chrono>
21 #include <cinttypes>
22 #include <cstddef>
23 #include <cstdint>
24 #include <limits>
25 #include <memory>
26 #include <optional>
27 #include <string>
28 #include <unordered_map>
29 #include <utility>
30 #include <vector>
31 
32 #include "perfetto/base/logging.h"
33 #include "perfetto/base/status.h"
34 #include "perfetto/base/time.h"
35 #include "perfetto/ext/base/flat_hash_map.h"
36 #include "perfetto/ext/base/small_vector.h"
37 #include "perfetto/ext/base/status_or.h"
38 #include "perfetto/ext/base/string_splitter.h"
39 #include "perfetto/ext/base/string_utils.h"
40 #include "perfetto/protozero/scattered_heap_buffer.h"
41 #include "perfetto/public/compiler.h"
42 #include "perfetto/trace_processor/basic_types.h"
43 #include "perfetto/trace_processor/iterator.h"
44 #include "perfetto/trace_processor/trace_blob_view.h"
45 #include "perfetto/trace_processor/trace_processor.h"
46 #include "src/trace_processor/importers/android_bugreport/android_bugreport_parser.h"
47 #include "src/trace_processor/importers/common/clock_tracker.h"
48 #include "src/trace_processor/importers/common/metadata_tracker.h"
49 #include "src/trace_processor/importers/common/trace_parser.h"
50 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
51 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
52 #include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
53 #include "src/trace_processor/importers/json/json_trace_parser_impl.h"
54 #include "src/trace_processor/importers/json/json_trace_tokenizer.h"
55 #include "src/trace_processor/importers/json/json_utils.h"
56 #include "src/trace_processor/importers/ninja/ninja_log_parser.h"
57 #include "src/trace_processor/importers/perf/perf_data_tokenizer.h"
58 #include "src/trace_processor/importers/perf/record_parser.h"
59 #include "src/trace_processor/importers/proto/additional_modules.h"
60 #include "src/trace_processor/importers/proto/content_analyzer.h"
61 #include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
62 #include "src/trace_processor/importers/zip/zip_trace_reader.h"
63 #include "src/trace_processor/iterator_impl.h"
64 #include "src/trace_processor/metrics/all_chrome_metrics.descriptor.h"
65 #include "src/trace_processor/metrics/all_webview_metrics.descriptor.h"
66 #include "src/trace_processor/metrics/metrics.descriptor.h"
67 #include "src/trace_processor/metrics/metrics.h"
68 #include "src/trace_processor/metrics/sql/amalgamated_sql_metrics.h"
69 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
70 #include "src/trace_processor/perfetto_sql/engine/table_pointer_module.h"
71 #include "src/trace_processor/perfetto_sql/intrinsics/functions/base64.h"
72 #include "src/trace_processor/perfetto_sql/intrinsics/functions/clock_functions.h"
73 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_function.h"
74 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_view_function.h"
75 #include "src/trace_processor/perfetto_sql/intrinsics/functions/dfs.h"
76 #include "src/trace_processor/perfetto_sql/intrinsics/functions/dominator_tree.h"
77 #include "src/trace_processor/perfetto_sql/intrinsics/functions/import.h"
78 #include "src/trace_processor/perfetto_sql/intrinsics/functions/layout_functions.h"
79 #include "src/trace_processor/perfetto_sql/intrinsics/functions/math.h"
80 #include "src/trace_processor/perfetto_sql/intrinsics/functions/pprof_functions.h"
81 #include "src/trace_processor/perfetto_sql/intrinsics/functions/sqlite3_str_split.h"
82 #include "src/trace_processor/perfetto_sql/intrinsics/functions/stack_functions.h"
83 #include "src/trace_processor/perfetto_sql/intrinsics/functions/structural_tree_partition.h"
84 #include "src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.h"
85 #include "src/trace_processor/perfetto_sql/intrinsics/functions/utils.h"
86 #include "src/trace_processor/perfetto_sql/intrinsics/functions/window_functions.h"
87 #include "src/trace_processor/perfetto_sql/intrinsics/operators/counter_mipmap_operator.h"
88 #include "src/trace_processor/perfetto_sql/intrinsics/operators/interval_intersect_operator.h"
89 #include "src/trace_processor/perfetto_sql/intrinsics/operators/slice_mipmap_operator.h"
90 #include "src/trace_processor/perfetto_sql/intrinsics/operators/span_join_operator.h"
91 #include "src/trace_processor/perfetto_sql/intrinsics/operators/window_operator.h"
92 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.h"
93 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.h"
94 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.h"
95 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs_weight_bounded.h"
96 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.h"
97 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_counter_dur.h"
98 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flamegraph.h"
99 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice.h"
100 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_sched_upid.h"
101 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout.h"
102 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/interval_intersect.h"
103 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/table_info.h"
104 #include "src/trace_processor/perfetto_sql/prelude/tables_views.h"
105 #include "src/trace_processor/perfetto_sql/stdlib/stdlib.h"
106 #include "src/trace_processor/sqlite/bindings/sqlite_aggregate_function.h"
107 #include "src/trace_processor/sqlite/bindings/sqlite_result.h"
108 #include "src/trace_processor/sqlite/scoped_db.h"
109 #include "src/trace_processor/sqlite/sql_source.h"
110 #include "src/trace_processor/sqlite/sql_stats_table.h"
111 #include "src/trace_processor/sqlite/stats_table.h"
112 #include "src/trace_processor/storage/metadata.h"
113 #include "src/trace_processor/storage/trace_storage.h"
114 #include "src/trace_processor/tp_metatrace.h"
115 #include "src/trace_processor/trace_processor_storage_impl.h"
116 #include "src/trace_processor/trace_reader_registry.h"
117 #include "src/trace_processor/types/trace_processor_context.h"
118 #include "src/trace_processor/types/variadic.h"
119 #include "src/trace_processor/util/descriptors.h"
120 #include "src/trace_processor/util/gzip_utils.h"
121 #include "src/trace_processor/util/protozero_to_json.h"
122 #include "src/trace_processor/util/protozero_to_text.h"
123 #include "src/trace_processor/util/regex.h"
124 #include "src/trace_processor/util/sql_modules.h"
125 #include "src/trace_processor/util/status_macros.h"
126 #include "src/trace_processor/util/trace_type.h"
127 
128 #include "protos/perfetto/common/builtin_clock.pbzero.h"
129 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
130 #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
131 #include "protos/perfetto/trace/trace.pbzero.h"
132 #include "protos/perfetto/trace/trace_packet.pbzero.h"
133 #include "protos/perfetto/trace_processor/metatrace_categories.pbzero.h"
134 
135 namespace perfetto::trace_processor {
136 namespace {
137 
138 template <typename SqlFunction, typename Ptr = typename SqlFunction::Context*>
RegisterFunction(PerfettoSqlEngine * engine,const char * name,int argc,Ptr context=nullptr,bool deterministic=true)139 void RegisterFunction(PerfettoSqlEngine* engine,
140                       const char* name,
141                       int argc,
142                       Ptr context = nullptr,
143                       bool deterministic = true) {
144   auto status = engine->RegisterStaticFunction<SqlFunction>(
145       name, argc, std::move(context), deterministic);
146   if (!status.ok())
147     PERFETTO_ELOG("%s", status.c_message());
148 }
149 
RegisterAllProtoBuilderFunctions(DescriptorPool * pool,PerfettoSqlEngine * engine,TraceProcessor * tp)150 void RegisterAllProtoBuilderFunctions(DescriptorPool* pool,
151                                       PerfettoSqlEngine* engine,
152                                       TraceProcessor* tp) {
153   for (uint32_t i = 0; i < pool->descriptors().size(); ++i) {
154     // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
155     // into a function name of the form (TraceMetrics_SubMetric).
156     const auto& desc = pool->descriptors()[i];
157     auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
158     std::replace(fn_name.begin(), fn_name.end(), '.', '_');
159     RegisterFunction<metrics::BuildProto>(
160         engine, fn_name.c_str(), -1,
161         std::make_unique<metrics::BuildProto::Context>(
162             metrics::BuildProto::Context{tp, pool, i}));
163   }
164 }
165 
BuildBoundsTable(sqlite3 * db,std::pair<int64_t,int64_t> bounds)166 void BuildBoundsTable(sqlite3* db, std::pair<int64_t, int64_t> bounds) {
167   char* error = nullptr;
168   sqlite3_exec(db, "DELETE FROM trace_bounds", nullptr, nullptr, &error);
169   if (error) {
170     PERFETTO_ELOG("Error deleting from bounds table: %s", error);
171     sqlite3_free(error);
172     return;
173   }
174 
175   base::StackString<1024> sql("INSERT INTO trace_bounds VALUES(%" PRId64
176                               ", %" PRId64 ")",
177                               bounds.first, bounds.second);
178   sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &error);
179   if (error) {
180     PERFETTO_ELOG("Error inserting bounds table: %s", error);
181     sqlite3_free(error);
182   }
183 }
184 
185 class ValueAtMaxTs : public SqliteAggregateFunction<ValueAtMaxTs> {
186  public:
187   static constexpr char kName[] = "VALUE_AT_MAX_TS";
188   static constexpr int kArgCount = 2;
189   struct Context {
190     bool initialized;
191     int value_type;
192 
193     int64_t max_ts;
194     int64_t int_value_at_max_ts;
195     double double_value_at_max_ts;
196   };
197 
Step(sqlite3_context * ctx,int,sqlite3_value ** argv)198   static void Step(sqlite3_context* ctx, int, sqlite3_value** argv) {
199     sqlite3_value* ts = argv[0];
200     sqlite3_value* value = argv[1];
201 
202     // Note that sqlite3_aggregate_context zeros the memory for us so all the
203     // variables of the struct should be zero.
204     auto* fn_ctx = reinterpret_cast<Context*>(
205         sqlite3_aggregate_context(ctx, sizeof(Context)));
206 
207     // For performance reasons, we only do the check for the type of ts and
208     // value on the first call of the function.
209     if (PERFETTO_UNLIKELY(!fn_ctx->initialized)) {
210       if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
211         return sqlite::result::Error(
212             ctx, "VALUE_AT_MAX_TS: ts passed was not an integer");
213       }
214 
215       fn_ctx->value_type = sqlite3_value_type(value);
216       if (fn_ctx->value_type != SQLITE_INTEGER &&
217           fn_ctx->value_type != SQLITE_FLOAT) {
218         return sqlite::result::Error(
219             ctx, "VALUE_AT_MAX_TS: value passed was not an integer or float");
220       }
221 
222       fn_ctx->max_ts = std::numeric_limits<int64_t>::min();
223       fn_ctx->initialized = true;
224     }
225 
226     // On dcheck builds however, we check every passed ts and value.
227 #if PERFETTO_DCHECK_IS_ON()
228     if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
229       return sqlite::result::Error(
230           ctx, "VALUE_AT_MAX_TS: ts passed was not an integer");
231     }
232     if (sqlite3_value_type(value) != fn_ctx->value_type) {
233       return sqlite::result::Error(
234           ctx, "VALUE_AT_MAX_TS: value type is inconsistent");
235     }
236 #endif
237 
238     int64_t ts_int = sqlite3_value_int64(ts);
239     if (PERFETTO_LIKELY(fn_ctx->max_ts <= ts_int)) {
240       fn_ctx->max_ts = ts_int;
241 
242       if (fn_ctx->value_type == SQLITE_INTEGER) {
243         fn_ctx->int_value_at_max_ts = sqlite3_value_int64(value);
244       } else {
245         fn_ctx->double_value_at_max_ts = sqlite3_value_double(value);
246       }
247     }
248   }
249 
Final(sqlite3_context * ctx)250   static void Final(sqlite3_context* ctx) {
251     auto* fn_ctx = static_cast<Context*>(sqlite3_aggregate_context(ctx, 0));
252     if (!fn_ctx) {
253       sqlite::result::Null(ctx);
254       return;
255     }
256     if (fn_ctx->value_type == SQLITE_INTEGER) {
257       sqlite::result::Long(ctx, fn_ctx->int_value_at_max_ts);
258     } else {
259       sqlite::result::Double(ctx, fn_ctx->double_value_at_max_ts);
260     }
261   }
262 };
263 
RegisterValueAtMaxTsFunction(PerfettoSqlEngine & engine)264 void RegisterValueAtMaxTsFunction(PerfettoSqlEngine& engine) {
265   base::Status status =
266       engine.RegisterSqliteAggregateFunction<ValueAtMaxTs>(nullptr);
267   if (!status.ok()) {
268     PERFETTO_ELOG("Error initializing VALUE_AT_MAX_TS");
269   }
270 }
271 
SanitizeMetricMountPaths(const std::vector<std::string> & mount_paths)272 std::vector<std::string> SanitizeMetricMountPaths(
273     const std::vector<std::string>& mount_paths) {
274   std::vector<std::string> sanitized;
275   for (const auto& path : mount_paths) {
276     if (path.empty())
277       continue;
278     sanitized.push_back(path);
279     if (path.back() != '/')
280       sanitized.back().append("/");
281   }
282   return sanitized;
283 }
284 
InsertIntoTraceMetricsTable(sqlite3 * db,const std::string & metric_name)285 void InsertIntoTraceMetricsTable(sqlite3* db, const std::string& metric_name) {
286   char* insert_sql = sqlite3_mprintf(
287       "INSERT INTO trace_metrics(name) VALUES('%q')", metric_name.c_str());
288   char* insert_error = nullptr;
289   sqlite3_exec(db, insert_sql, nullptr, nullptr, &insert_error);
290   sqlite3_free(insert_sql);
291   if (insert_error) {
292     PERFETTO_ELOG("Error registering table: %s", insert_error);
293     sqlite3_free(insert_error);
294   }
295 }
296 
TraceTypeToString(TraceType trace_type)297 const char* TraceTypeToString(TraceType trace_type) {
298   switch (trace_type) {
299     case kUnknownTraceType:
300       return "unknown";
301     case kProtoTraceType:
302       return "proto";
303     case kJsonTraceType:
304       return "json";
305     case kFuchsiaTraceType:
306       return "fuchsia";
307     case kSystraceTraceType:
308       return "systrace";
309     case kGzipTraceType:
310       return "gzip";
311     case kCtraceTraceType:
312       return "ctrace";
313     case kNinjaLogTraceType:
314       return "ninja_log";
315     case kZipFile:
316       return "zip";
317     case kPerfDataTraceType:
318       return "perf_data";
319   }
320   PERFETTO_FATAL("For GCC");
321 }
322 
GetStdlibModules()323 sql_modules::NameToModule GetStdlibModules() {
324   sql_modules::NameToModule modules;
325   for (const auto& file_to_sql : stdlib::kFileToSql) {
326     std::string import_key = sql_modules::GetIncludeKey(file_to_sql.path);
327     std::string module = sql_modules::GetModuleName(import_key);
328     modules.Insert(module, {}).first->push_back({import_key, file_to_sql.sql});
329   }
330   return modules;
331 }
332 
InitializePreludeTablesViews(sqlite3 * db)333 void InitializePreludeTablesViews(sqlite3* db) {
334   for (const auto& file_to_sql : prelude::tables_views::kFileToSql) {
335     char* errmsg_raw = nullptr;
336     int err = sqlite3_exec(db, file_to_sql.sql, nullptr, nullptr, &errmsg_raw);
337     ScopedSqliteString errmsg(errmsg_raw);
338     if (err != SQLITE_OK) {
339       PERFETTO_FATAL("Failed to initialize prelude %s", errmsg_raw);
340     }
341   }
342 }
343 
344 }  // namespace
345 
TraceProcessorImpl(const Config & cfg)346 TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
347     : TraceProcessorStorageImpl(cfg), config_(cfg) {
348   context_.reader_registry->RegisterTraceReader<FuchsiaTraceTokenizer>(
349       kFuchsiaTraceType);
350   context_.fuchsia_record_parser =
351       std::make_unique<FuchsiaTraceParser>(&context_);
352 
353   context_.reader_registry->RegisterTraceReader<SystraceTraceParser>(
354       kSystraceTraceType);
355   context_.reader_registry->RegisterTraceReader<NinjaLogParser>(
356       kNinjaLogTraceType);
357 
358   context_.reader_registry
359       ->RegisterTraceReader<perf_importer::PerfDataTokenizer>(
360           kPerfDataTraceType);
361   context_.perf_record_parser =
362       std::make_unique<perf_importer::RecordParser>(&context_);
363 
364   if (util::IsGzipSupported()) {
365     context_.reader_registry->RegisterTraceReader<GzipTraceParser>(
366         kGzipTraceType);
367     context_.reader_registry->RegisterTraceReader<GzipTraceParser>(
368         kCtraceTraceType);
369     context_.reader_registry->RegisterTraceReader<ZipTraceReader>(kZipFile);
370   }
371 
372   if (json::IsJsonSupported()) {
373     context_.reader_registry->RegisterTraceReader<JsonTraceTokenizer>(
374         kJsonTraceType);
375     context_.json_trace_parser =
376         std::make_unique<JsonTraceParserImpl>(&context_);
377   }
378 
379   if (context_.config.analyze_trace_proto_content) {
380     context_.content_analyzer =
381         std::make_unique<ProtoContentAnalyzer>(&context_);
382   }
383 
384   // Add metrics to descriptor pool
385   const std::vector<std::string> sanitized_extension_paths =
386       SanitizeMetricMountPaths(config_.skip_builtin_metric_paths);
387   std::vector<std::string> skip_prefixes;
388   skip_prefixes.reserve(sanitized_extension_paths.size());
389   for (const auto& path : sanitized_extension_paths) {
390     skip_prefixes.push_back(kMetricProtoRoot + path);
391   }
392   pool_.AddFromFileDescriptorSet(kMetricsDescriptor.data(),
393                                  kMetricsDescriptor.size(), skip_prefixes);
394   pool_.AddFromFileDescriptorSet(kAllChromeMetricsDescriptor.data(),
395                                  kAllChromeMetricsDescriptor.size(),
396                                  skip_prefixes);
397   pool_.AddFromFileDescriptorSet(kAllWebviewMetricsDescriptor.data(),
398                                  kAllWebviewMetricsDescriptor.size(),
399                                  skip_prefixes);
400 
401   RegisterAdditionalModules(&context_);
402   InitPerfettoSqlEngine();
403 
404   sqlite_objects_post_constructor_initialization_ =
405       engine_->SqliteRegisteredObjectCount();
406 
407   bool skip_all_sql = std::find(config_.skip_builtin_metric_paths.begin(),
408                                 config_.skip_builtin_metric_paths.end(),
409                                 "") != config_.skip_builtin_metric_paths.end();
410   if (!skip_all_sql) {
411     for (const auto& file_to_sql : sql_metrics::kFileToSql) {
412       if (base::StartsWithAny(file_to_sql.path, sanitized_extension_paths))
413         continue;
414       RegisterMetric(file_to_sql.path, file_to_sql.sql);
415     }
416   }
417 }
418 
419 TraceProcessorImpl::~TraceProcessorImpl() = default;
420 
Parse(TraceBlobView blob)421 base::Status TraceProcessorImpl::Parse(TraceBlobView blob) {
422   bytes_parsed_ += blob.size();
423   return TraceProcessorStorageImpl::Parse(std::move(blob));
424 }
425 
GetCurrentTraceName()426 std::string TraceProcessorImpl::GetCurrentTraceName() {
427   if (current_trace_name_.empty())
428     return "";
429   auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
430   return current_trace_name_ + size;
431 }
432 
SetCurrentTraceName(const std::string & name)433 void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
434   current_trace_name_ = name;
435 }
436 
Flush()437 void TraceProcessorImpl::Flush() {
438   TraceProcessorStorageImpl::Flush();
439 
440   context_.metadata_tracker->SetMetadata(
441       metadata::trace_size_bytes,
442       Variadic::Integer(static_cast<int64_t>(bytes_parsed_)));
443   const StringId trace_type_id =
444       context_.storage->InternString(TraceTypeToString(context_.trace_type));
445   context_.metadata_tracker->SetMetadata(metadata::trace_type,
446                                          Variadic::String(trace_type_id));
447   BuildBoundsTable(engine_->sqlite_engine()->db(),
448                    context_.storage->GetTraceTimestampBoundsNs());
449 }
450 
NotifyEndOfFile()451 void TraceProcessorImpl::NotifyEndOfFile() {
452   if (notify_eof_called_) {
453     PERFETTO_ELOG(
454         "NotifyEndOfFile should only be called once. Try calling Flush instead "
455         "if trying to commit the contents of the trace to tables.");
456     return;
457   }
458   notify_eof_called_ = true;
459 
460   if (current_trace_name_.empty())
461     current_trace_name_ = "Unnamed trace";
462 
463   // Last opportunity to flush all pending data.
464   Flush();
465 
466   TraceProcessorStorageImpl::NotifyEndOfFile();
467   context_.storage->ShrinkToFitTables();
468 
469   // Rebuild the bounds table once everything has been completed: we do this
470   // so that if any data was added to tables in
471   // TraceProcessorStorageImpl::NotifyEndOfFile, this will be counted in
472   // trace bounds: this is important for parsers like ninja which wait until
473   // the end to flush all their data.
474   BuildBoundsTable(engine_->sqlite_engine()->db(),
475                    context_.storage->GetTraceTimestampBoundsNs());
476 
477   TraceProcessorStorageImpl::DestroyContext();
478 }
479 
RestoreInitialTables()480 size_t TraceProcessorImpl::RestoreInitialTables() {
481   // We should always have at least as many objects now as we did in the
482   // constructor.
483   uint64_t registered_count_before = engine_->SqliteRegisteredObjectCount();
484   PERFETTO_CHECK(registered_count_before >=
485                  sqlite_objects_post_constructor_initialization_);
486 
487   InitPerfettoSqlEngine();
488 
489   // The registered count should now be the same as it was in the constructor.
490   uint64_t registered_count_after = engine_->SqliteRegisteredObjectCount();
491   PERFETTO_CHECK(registered_count_after ==
492                  sqlite_objects_post_constructor_initialization_);
493   return static_cast<size_t>(registered_count_before - registered_count_after);
494 }
495 
ExecuteQuery(const std::string & sql)496 Iterator TraceProcessorImpl::ExecuteQuery(const std::string& sql) {
497   PERFETTO_TP_TRACE(metatrace::Category::API_TIMELINE, "EXECUTE_QUERY");
498 
499   uint32_t sql_stats_row =
500       context_.storage->mutable_sql_stats()->RecordQueryBegin(
501           sql, base::GetWallTimeNs().count());
502   std::string non_breaking_sql = base::ReplaceAll(sql, "\u00A0", " ");
503   base::StatusOr<PerfettoSqlEngine::ExecutionResult> result =
504       engine_->ExecuteUntilLastStatement(
505           SqlSource::FromExecuteQuery(std::move(non_breaking_sql)));
506   std::unique_ptr<IteratorImpl> impl(
507       new IteratorImpl(this, std::move(result), sql_stats_row));
508   return Iterator(std::move(impl));
509 }
510 
InterruptQuery()511 void TraceProcessorImpl::InterruptQuery() {
512   if (!engine_->sqlite_engine()->db())
513     return;
514   query_interrupted_.store(true);
515   sqlite3_interrupt(engine_->sqlite_engine()->db());
516 }
517 
IsRootMetricField(const std::string & metric_name)518 bool TraceProcessorImpl::IsRootMetricField(const std::string& metric_name) {
519   std::optional<uint32_t> desc_idx =
520       pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
521   if (!desc_idx.has_value())
522     return false;
523   const auto* field_idx =
524       pool_.descriptors()[*desc_idx].FindFieldByName(metric_name);
525   return field_idx != nullptr;
526 }
527 
RegisterSqlModule(SqlModule sql_module)528 base::Status TraceProcessorImpl::RegisterSqlModule(SqlModule sql_module) {
529   sql_modules::RegisteredModule new_module;
530   std::string name = sql_module.name;
531   if (engine_->FindModule(name) && !sql_module.allow_module_override) {
532     return base::ErrStatus(
533         "Module '%s' is already registered. Choose a different name.\n"
534         "If you want to replace the existing module using trace processor "
535         "shell, you need to pass the --dev flag and use "
536         "--override-sql-module "
537         "to pass the module path.",
538         name.c_str());
539   }
540   for (auto const& name_and_sql : sql_module.files) {
541     if (sql_modules::GetModuleName(name_and_sql.first) != name) {
542       return base::ErrStatus(
543           "File import key doesn't match the module name. First part of "
544           "import "
545           "key should be module name. Import key: %s, module name: %s.",
546           name_and_sql.first.c_str(), name.c_str());
547     }
548     new_module.include_key_to_file.Insert(name_and_sql.first,
549                                           {name_and_sql.second, false});
550   }
551   engine_->RegisterModule(name, std::move(new_module));
552   return base::OkStatus();
553 }
554 
RegisterMetric(const std::string & path,const std::string & sql)555 base::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
556                                                 const std::string& sql) {
557   // Check if the metric with the given path already exists and if it does,
558   // just update the SQL associated with it.
559   auto it = std::find_if(
560       sql_metrics_.begin(), sql_metrics_.end(),
561       [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
562   if (it != sql_metrics_.end()) {
563     it->sql = sql;
564     return base::OkStatus();
565   }
566 
567   auto sep_idx = path.rfind('/');
568   std::string basename =
569       sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
570 
571   auto sql_idx = basename.rfind(".sql");
572   if (sql_idx == std::string::npos) {
573     return base::ErrStatus("Unable to find .sql extension for metric");
574   }
575   auto no_ext_name = basename.substr(0, sql_idx);
576 
577   metrics::SqlMetricFile metric;
578   metric.path = path;
579   metric.sql = sql;
580 
581   if (IsRootMetricField(no_ext_name)) {
582     metric.proto_field_name = no_ext_name;
583     metric.output_table_name = no_ext_name + "_output";
584 
585     auto field_it_and_inserted =
586         proto_field_to_sql_metric_path_.emplace(*metric.proto_field_name, path);
587     if (!field_it_and_inserted.second) {
588       // We already had a metric with this field name in the map. However, if
589       // this was the case, we should have found the metric in
590       // |path_to_sql_metric_file_| above if we are simply overriding the
591       // metric. Return an error since this means we have two different SQL
592       // files which are trying to output the same metric.
593       const auto& prev_path = field_it_and_inserted.first->second;
594       PERFETTO_DCHECK(prev_path != path);
595       return base::ErrStatus(
596           "RegisterMetric Error: Metric paths %s (which is already "
597           "registered) "
598           "and %s are both trying to output the proto field %s",
599           prev_path.c_str(), path.c_str(), metric.proto_field_name->c_str());
600     }
601   }
602 
603   if (metric.proto_field_name) {
604     InsertIntoTraceMetricsTable(engine_->sqlite_engine()->db(),
605                                 *metric.proto_field_name);
606   }
607   sql_metrics_.emplace_back(metric);
608   return base::OkStatus();
609 }
610 
ExtendMetricsProto(const uint8_t * data,size_t size)611 base::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
612                                                     size_t size) {
613   return ExtendMetricsProto(data, size, /*skip_prefixes*/ {});
614 }
615 
ExtendMetricsProto(const uint8_t * data,size_t size,const std::vector<std::string> & skip_prefixes)616 base::Status TraceProcessorImpl::ExtendMetricsProto(
617     const uint8_t* data,
618     size_t size,
619     const std::vector<std::string>& skip_prefixes) {
620   RETURN_IF_ERROR(pool_.AddFromFileDescriptorSet(data, size, skip_prefixes));
621   RegisterAllProtoBuilderFunctions(&pool_, engine_.get(), this);
622   return base::OkStatus();
623 }
624 
ComputeMetric(const std::vector<std::string> & metric_names,std::vector<uint8_t> * metrics_proto)625 base::Status TraceProcessorImpl::ComputeMetric(
626     const std::vector<std::string>& metric_names,
627     std::vector<uint8_t>* metrics_proto) {
628   auto opt_idx = pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
629   if (!opt_idx.has_value())
630     return base::Status("Root metrics proto descriptor not found");
631 
632   const auto& root_descriptor = pool_.descriptors()[opt_idx.value()];
633   return metrics::ComputeMetrics(engine_.get(), metric_names, sql_metrics_,
634                                  pool_, root_descriptor, metrics_proto);
635 }
636 
ComputeMetricText(const std::vector<std::string> & metric_names,TraceProcessor::MetricResultFormat format,std::string * metrics_string)637 base::Status TraceProcessorImpl::ComputeMetricText(
638     const std::vector<std::string>& metric_names,
639     TraceProcessor::MetricResultFormat format,
640     std::string* metrics_string) {
641   std::vector<uint8_t> metrics_proto;
642   base::Status status = ComputeMetric(metric_names, &metrics_proto);
643   if (!status.ok())
644     return status;
645   switch (format) {
646     case TraceProcessor::MetricResultFormat::kProtoText:
647       *metrics_string = protozero_to_text::ProtozeroToText(
648           pool_, ".perfetto.protos.TraceMetrics",
649           protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
650           protozero_to_text::kIncludeNewLines);
651       break;
652     case TraceProcessor::MetricResultFormat::kJson:
653       *metrics_string = protozero_to_json::ProtozeroToJson(
654           pool_, ".perfetto.protos.TraceMetrics",
655           protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
656           protozero_to_json::kPretty | protozero_to_json::kInlineErrors |
657               protozero_to_json::kInlineAnnotations);
658       break;
659   }
660   return status;
661 }
662 
GetMetricDescriptors()663 std::vector<uint8_t> TraceProcessorImpl::GetMetricDescriptors() {
664   return pool_.SerializeAsDescriptorSet();
665 }
666 
EnableMetatrace(MetatraceConfig config)667 void TraceProcessorImpl::EnableMetatrace(MetatraceConfig config) {
668   metatrace::Enable(config);
669 }
670 
InitPerfettoSqlEngine()671 void TraceProcessorImpl::InitPerfettoSqlEngine() {
672   engine_.reset(new PerfettoSqlEngine(context_.storage->mutable_string_pool()));
673   sqlite3* db = engine_->sqlite_engine()->db();
674   sqlite3_str_split_init(db);
675 
676   // Register SQL functions only used in local development instances.
677   if (config_.enable_dev_features) {
678     RegisterFunction<WriteFile>(engine_.get(), "WRITE_FILE", 2);
679   }
680   RegisterFunction<Glob>(engine_.get(), "glob", 2);
681   RegisterFunction<Hash>(engine_.get(), "HASH", -1);
682   RegisterFunction<Base64Encode>(engine_.get(), "BASE64_ENCODE", 1);
683   RegisterFunction<Demangle>(engine_.get(), "DEMANGLE", 1);
684   RegisterFunction<SourceGeq>(engine_.get(), "SOURCE_GEQ", -1);
685   RegisterFunction<TablePtrBind>(engine_.get(), "__intrinsic_table_ptr_bind",
686                                  -1);
687   RegisterFunction<ExportJson>(engine_.get(), "EXPORT_JSON", 1,
688                                context_.storage.get(), false);
689   RegisterFunction<ExtractArg>(engine_.get(), "EXTRACT_ARG", 2,
690                                context_.storage.get());
691   RegisterFunction<AbsTimeStr>(engine_.get(), "ABS_TIME_STR", 1,
692                                context_.clock_converter.get());
693   RegisterFunction<Reverse>(engine_.get(), "REVERSE", 1);
694   RegisterFunction<ToMonotonic>(engine_.get(), "TO_MONOTONIC", 1,
695                                 context_.clock_converter.get());
696   RegisterFunction<ToRealtime>(engine_.get(), "TO_REALTIME", 1,
697                                context_.clock_converter.get());
698   RegisterFunction<ToTimecode>(engine_.get(), "TO_TIMECODE", 1);
699   RegisterFunction<CreateFunction>(engine_.get(), "CREATE_FUNCTION", 3,
700                                    engine_.get());
701   RegisterFunction<CreateViewFunction>(engine_.get(), "CREATE_VIEW_FUNCTION", 3,
702                                        engine_.get());
703   RegisterFunction<ExperimentalMemoize>(engine_.get(), "EXPERIMENTAL_MEMOIZE",
704                                         1, engine_.get());
705   RegisterFunction<Import>(
706       engine_.get(), "IMPORT", 1,
707       std::make_unique<Import::Context>(Import::Context{engine_.get()}));
708   RegisterFunction<ToFtrace>(
709       engine_.get(), "TO_FTRACE", 1,
710       std::make_unique<ToFtrace::Context>(ToFtrace::Context{
711           context_.storage.get(), SystraceSerializer(&context_)}));
712 
713   if constexpr (regex::IsRegexSupported()) {
714     RegisterFunction<Regex>(engine_.get(), "regexp", 2);
715   }
716   // Old style function registration.
717   // TODO(lalitm): migrate this over to using RegisterFunction once aggregate
718   // functions are supported.
719   RegisterValueAtMaxTsFunction(*engine_);
720   {
721     base::Status status = RegisterLastNonNullFunction(*engine_);
722     if (!status.ok())
723       PERFETTO_ELOG("%s", status.c_message());
724   }
725   {
726     base::Status status = RegisterStackFunctions(engine_.get(), &context_);
727     if (!status.ok())
728       PERFETTO_ELOG("%s", status.c_message());
729   }
730   {
731     base::Status status = PprofFunctions::Register(*engine_, &context_);
732     if (!status.ok())
733       PERFETTO_ELOG("%s", status.c_message());
734   }
735   {
736     base::Status status = RegisterLayoutFunctions(*engine_);
737     if (!status.ok())
738       PERFETTO_ELOG("%s", status.c_message());
739   }
740   {
741     base::Status status = RegisterMathFunctions(*engine_);
742     if (!status.ok())
743       PERFETTO_ELOG("%s", status.c_message());
744   }
745   {
746     base::Status status = RegisterBase64Functions(*engine_);
747     if (!status.ok())
748       PERFETTO_ELOG("%s", status.c_message());
749   }
750 
751   TraceStorage* storage = context_.storage.get();
752 
753   // Operator tables.
754   engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
755       "span_join",
756       std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
757   engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
758       "span_left_join",
759       std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
760   engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
761       "span_outer_join",
762       std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
763   engine_->sqlite_engine()->RegisterVirtualTableModule<WindowOperatorModule>(
764       "window", std::make_unique<WindowOperatorModule::Context>());
765   engine_->sqlite_engine()->RegisterVirtualTableModule<CounterMipmapOperator>(
766       "__intrinsic_counter_mipmap",
767       std::make_unique<CounterMipmapOperator::Context>(engine_.get()));
768   engine_->sqlite_engine()->RegisterVirtualTableModule<SliceMipmapOperator>(
769       "__intrinsic_slice_mipmap",
770       std::make_unique<SliceMipmapOperator::Context>(engine_.get()));
771   engine_->sqlite_engine()
772       ->RegisterVirtualTableModule<IntervalIntersectOperator>(
773           "__intrinsic_ii_with_interval_tree",
774           std::make_unique<IntervalIntersectOperator::Context>(engine_.get()));
775 
776   // Initalize the tables and views in the prelude.
777   InitializePreludeTablesViews(db);
778 
779   // Register stdlib modules.
780   auto stdlib_modules = GetStdlibModules();
781   for (auto module_it = stdlib_modules.GetIterator(); module_it; ++module_it) {
782     base::Status status =
783         RegisterSqlModule({module_it.key(), module_it.value(), false});
784     if (!status.ok())
785       PERFETTO_ELOG("%s", status.c_message());
786   }
787 
788   // Register metrics functions.
789   {
790     base::Status status =
791         engine_->RegisterSqliteAggregateFunction<metrics::RepeatedField>(
792             nullptr);
793     if (!status.ok())
794       PERFETTO_ELOG("%s", status.c_message());
795   }
796 
797   RegisterFunction<metrics::NullIfEmpty>(engine_.get(), "NULL_IF_EMPTY", 1);
798   RegisterFunction<metrics::UnwrapMetricProto>(engine_.get(),
799                                                "UNWRAP_METRIC_PROTO", 2);
800   RegisterFunction<metrics::RunMetric>(
801       engine_.get(), "RUN_METRIC", -1,
802       std::make_unique<metrics::RunMetric::Context>(
803           metrics::RunMetric::Context{engine_.get(), &sql_metrics_}));
804 
805   // Legacy tables.
806   engine_->sqlite_engine()->RegisterVirtualTableModule<SqlStatsModule>(
807       "sqlstats", storage);
808   engine_->sqlite_engine()->RegisterVirtualTableModule<StatsModule>("stats",
809                                                                     storage);
810   engine_->sqlite_engine()->RegisterVirtualTableModule<TablePointerModule>(
811       "__intrinsic_table_ptr", nullptr);
812 
813   // New style db-backed tables.
814   // Note: if adding a table here which might potentially contain many rows
815   // (O(rows in sched/slice/counter)), then consider calling ShrinkToFit on
816   // that table in TraceStorage::ShrinkToFitTables.
817   RegisterStaticTable(storage->machine_table());
818   RegisterStaticTable(storage->arg_table());
819   RegisterStaticTable(storage->raw_table());
820   RegisterStaticTable(storage->ftrace_event_table());
821   RegisterStaticTable(storage->thread_table());
822   RegisterStaticTable(storage->process_table());
823   RegisterStaticTable(storage->filedescriptor_table());
824 
825   RegisterStaticTable(storage->slice_table());
826   RegisterStaticTable(storage->flow_table());
827   RegisterStaticTable(storage->sched_slice_table());
828   RegisterStaticTable(storage->spurious_sched_wakeup_table());
829   RegisterStaticTable(storage->thread_state_table());
830   RegisterStaticTable(storage->gpu_slice_table());
831 
832   RegisterStaticTable(storage->track_table());
833   RegisterStaticTable(storage->thread_track_table());
834   RegisterStaticTable(storage->process_track_table());
835   RegisterStaticTable(storage->cpu_track_table());
836   RegisterStaticTable(storage->gpu_track_table());
837   RegisterStaticTable(storage->uid_track_table());
838   RegisterStaticTable(storage->gpu_work_period_track_table());
839 
840   RegisterStaticTable(storage->counter_table());
841 
842   RegisterStaticTable(storage->counter_track_table());
843   RegisterStaticTable(storage->process_counter_track_table());
844   RegisterStaticTable(storage->thread_counter_track_table());
845   RegisterStaticTable(storage->cpu_counter_track_table());
846   RegisterStaticTable(storage->irq_counter_track_table());
847   RegisterStaticTable(storage->softirq_counter_track_table());
848   RegisterStaticTable(storage->gpu_counter_track_table());
849   RegisterStaticTable(storage->gpu_counter_group_table());
850   RegisterStaticTable(storage->perf_counter_track_table());
851   RegisterStaticTable(storage->energy_counter_track_table());
852   RegisterStaticTable(storage->linux_device_track_table());
853   RegisterStaticTable(storage->uid_counter_track_table());
854   RegisterStaticTable(storage->energy_per_uid_counter_track_table());
855 
856   RegisterStaticTable(storage->heap_graph_object_table());
857   RegisterStaticTable(storage->heap_graph_reference_table());
858   RegisterStaticTable(storage->heap_graph_class_table());
859 
860   RegisterStaticTable(storage->symbol_table());
861   RegisterStaticTable(storage->heap_profile_allocation_table());
862   RegisterStaticTable(storage->cpu_profile_stack_sample_table());
863   RegisterStaticTable(storage->perf_session_table());
864   RegisterStaticTable(storage->perf_sample_table());
865   RegisterStaticTable(storage->stack_profile_callsite_table());
866   RegisterStaticTable(storage->stack_profile_mapping_table());
867   RegisterStaticTable(storage->stack_profile_frame_table());
868   RegisterStaticTable(storage->package_list_table());
869   RegisterStaticTable(storage->profiler_smaps_table());
870 
871   RegisterStaticTable(storage->android_log_table());
872   RegisterStaticTable(storage->android_dumpstate_table());
873   RegisterStaticTable(storage->android_game_intervention_list_table());
874   RegisterStaticTable(storage->android_key_events_table());
875   RegisterStaticTable(storage->android_motion_events_table());
876   RegisterStaticTable(storage->android_input_event_dispatch_table());
877 
878   RegisterStaticTable(storage->vulkan_memory_allocations_table());
879 
880   RegisterStaticTable(storage->graphics_frame_slice_table());
881 
882   RegisterStaticTable(storage->expected_frame_timeline_slice_table());
883   RegisterStaticTable(storage->actual_frame_timeline_slice_table());
884 
885   RegisterStaticTable(storage->android_network_packets_table());
886 
887   RegisterStaticTable(storage->v8_isolate_table());
888   RegisterStaticTable(storage->v8_js_script_table());
889   RegisterStaticTable(storage->v8_wasm_script_table());
890   RegisterStaticTable(storage->v8_js_function_table());
891   RegisterStaticTable(storage->v8_js_code_table());
892   RegisterStaticTable(storage->v8_internal_code_table());
893   RegisterStaticTable(storage->v8_wasm_code_table());
894   RegisterStaticTable(storage->v8_regexp_code_table());
895 
896   RegisterStaticTable(storage->jit_code_table());
897   RegisterStaticTable(storage->jit_frame_table());
898 
899   RegisterStaticTable(storage->inputmethod_clients_table());
900   RegisterStaticTable(storage->inputmethod_manager_service_table());
901   RegisterStaticTable(storage->inputmethod_service_table());
902 
903   RegisterStaticTable(storage->surfaceflinger_layers_snapshot_table());
904   RegisterStaticTable(storage->surfaceflinger_layer_table());
905   RegisterStaticTable(storage->surfaceflinger_transactions_table());
906 
907   RegisterStaticTable(storage->viewcapture_table());
908 
909   RegisterStaticTable(storage->window_manager_shell_transitions_table());
910   RegisterStaticTable(
911       storage->window_manager_shell_transition_handlers_table());
912 
913   RegisterStaticTable(storage->protolog_table());
914 
915   RegisterStaticTable(storage->metadata_table());
916   RegisterStaticTable(storage->cpu_table());
917   RegisterStaticTable(storage->cpu_freq_table());
918   RegisterStaticTable(storage->clock_snapshot_table());
919 
920   RegisterStaticTable(storage->memory_snapshot_table());
921   RegisterStaticTable(storage->process_memory_snapshot_table());
922   RegisterStaticTable(storage->memory_snapshot_node_table());
923   RegisterStaticTable(storage->memory_snapshot_edge_table());
924 
925   RegisterStaticTable(storage->experimental_proto_path_table());
926   RegisterStaticTable(storage->experimental_proto_content_table());
927 
928   RegisterStaticTable(storage->experimental_missing_chrome_processes_table());
929 
930   // Tables dynamically generated at query time.
931   engine_->RegisterStaticTableFunction(
932       std::make_unique<ExperimentalFlamegraph>(&context_));
933   engine_->RegisterStaticTableFunction(
934       std::make_unique<ExperimentalCounterDur>(storage->counter_table()));
935   engine_->RegisterStaticTableFunction(
936       std::make_unique<ExperimentalSliceLayout>(
937           context_.storage->mutable_string_pool(), &storage->slice_table()));
938   engine_->RegisterStaticTableFunction(std::make_unique<TableInfo>(
939       context_.storage->mutable_string_pool(), engine_.get()));
940   engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
941       Ancestor::Type::kSlice, context_.storage.get()));
942   engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
943       Ancestor::Type::kStackProfileCallsite, context_.storage.get()));
944   engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
945       Ancestor::Type::kSliceByStack, context_.storage.get()));
946   engine_->RegisterStaticTableFunction(std::make_unique<Descendant>(
947       Descendant::Type::kSlice, context_.storage.get()));
948   engine_->RegisterStaticTableFunction(std::make_unique<Descendant>(
949       Descendant::Type::kSliceByStack, context_.storage.get()));
950   engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
951       ConnectedFlow::Mode::kDirectlyConnectedFlow, context_.storage.get()));
952   engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
953       ConnectedFlow::Mode::kPrecedingFlow, context_.storage.get()));
954   engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
955       ConnectedFlow::Mode::kFollowingFlow, context_.storage.get()));
956   engine_->RegisterStaticTableFunction(std::make_unique<ExperimentalSchedUpid>(
957       storage->sched_slice_table(), storage->thread_table()));
958   engine_->RegisterStaticTableFunction(
959       std::make_unique<ExperimentalAnnotatedStack>(&context_));
960   engine_->RegisterStaticTableFunction(
961       std::make_unique<ExperimentalFlatSlice>(&context_));
962   engine_->RegisterStaticTableFunction(std::make_unique<IntervalIntersect>(
963       context_.storage->mutable_string_pool()));
964   engine_->RegisterStaticTableFunction(std::make_unique<DfsWeightBounded>(
965       context_.storage->mutable_string_pool()));
966 
967   // Value table aggregate functions.
968   engine_->RegisterSqliteAggregateFunction<Dfs>(
969       context_.storage->mutable_string_pool());
970   engine_->RegisterSqliteAggregateFunction<DominatorTree>(
971       context_.storage->mutable_string_pool());
972   engine_->RegisterSqliteAggregateFunction<StructuralTreePartition>(
973       context_.storage->mutable_string_pool());
974 
975   // Metrics.
976   RegisterAllProtoBuilderFunctions(&pool_, engine_.get(), this);
977 
978   for (const auto& metric : sql_metrics_) {
979     if (metric.proto_field_name) {
980       InsertIntoTraceMetricsTable(db, *metric.proto_field_name);
981     }
982   }
983 
984   // Import prelude module.
985   {
986     auto result = engine_->Execute(SqlSource::FromTraceProcessorImplementation(
987         "INCLUDE PERFETTO MODULE prelude.*"));
988     if (!result.status().ok()) {
989       PERFETTO_FATAL("Failed to import prelude: %s",
990                      result.status().c_message());
991     }
992   }
993 
994   // Fill trace bounds table.
995   BuildBoundsTable(db, context_.storage->GetTraceTimestampBoundsNs());
996 }
997 
998 namespace {
999 
1000 class StringInterner {
1001  public:
StringInterner(protos::pbzero::PerfettoMetatrace & event,base::FlatHashMap<std::string,uint64_t> & interned_strings)1002   StringInterner(protos::pbzero::PerfettoMetatrace& event,
1003                  base::FlatHashMap<std::string, uint64_t>& interned_strings)
1004       : event_(event), interned_strings_(interned_strings) {}
1005 
~StringInterner()1006   ~StringInterner() {
1007     for (const auto& interned_string : new_interned_strings_) {
1008       auto* interned_string_proto = event_.add_interned_strings();
1009       interned_string_proto->set_iid(interned_string.first);
1010       interned_string_proto->set_value(interned_string.second);
1011     }
1012   }
1013 
InternString(const std::string & str)1014   uint64_t InternString(const std::string& str) {
1015     uint64_t new_iid = interned_strings_.size();
1016     auto insert_result = interned_strings_.Insert(str, new_iid);
1017     if (insert_result.second) {
1018       new_interned_strings_.emplace_back(new_iid, str);
1019     }
1020     return *insert_result.first;
1021   }
1022 
1023  private:
1024   protos::pbzero::PerfettoMetatrace& event_;
1025   base::FlatHashMap<std::string, uint64_t>& interned_strings_;
1026 
1027   base::SmallVector<std::pair<uint64_t, std::string>, 16> new_interned_strings_;
1028 };
1029 
1030 }  // namespace
1031 
DisableAndReadMetatrace(std::vector<uint8_t> * trace_proto)1032 base::Status TraceProcessorImpl::DisableAndReadMetatrace(
1033     std::vector<uint8_t>* trace_proto) {
1034   protozero::HeapBuffered<protos::pbzero::Trace> trace;
1035 
1036   {
1037     uint64_t realtime_timestamp = static_cast<uint64_t>(
1038         std::chrono::system_clock::now().time_since_epoch() /
1039         std::chrono::nanoseconds(1));
1040     uint64_t boottime_timestamp = metatrace::TraceTimeNowNs();
1041     auto* clock_snapshot = trace->add_packet()->set_clock_snapshot();
1042     {
1043       auto* realtime_clock = clock_snapshot->add_clocks();
1044       realtime_clock->set_clock_id(
1045           protos::pbzero::BuiltinClock::BUILTIN_CLOCK_REALTIME);
1046       realtime_clock->set_timestamp(realtime_timestamp);
1047     }
1048     {
1049       auto* boottime_clock = clock_snapshot->add_clocks();
1050       boottime_clock->set_clock_id(
1051           protos::pbzero::BuiltinClock::BUILTIN_CLOCK_BOOTTIME);
1052       boottime_clock->set_timestamp(boottime_timestamp);
1053     }
1054   }
1055 
1056   base::FlatHashMap<std::string, uint64_t> interned_strings;
1057   metatrace::DisableAndReadBuffer([&trace, &interned_strings](
1058                                       metatrace::Record* record) {
1059     auto* packet = trace->add_packet();
1060     packet->set_timestamp(record->timestamp_ns);
1061     auto* evt = packet->set_perfetto_metatrace();
1062 
1063     StringInterner interner(*evt, interned_strings);
1064 
1065     evt->set_event_name_iid(interner.InternString(record->event_name));
1066     evt->set_event_duration_ns(record->duration_ns);
1067     evt->set_thread_id(1);  // Not really important, just required for the ui.
1068 
1069     if (record->args_buffer_size == 0)
1070       return;
1071 
1072     base::StringSplitter s(
1073         record->args_buffer, record->args_buffer_size, '\0',
1074         base::StringSplitter::EmptyTokenMode::ALLOW_EMPTY_TOKENS);
1075     for (; s.Next();) {
1076       auto* arg_proto = evt->add_args();
1077       arg_proto->set_key_iid(interner.InternString(s.cur_token()));
1078 
1079       bool has_next = s.Next();
1080       PERFETTO_CHECK(has_next);
1081       arg_proto->set_value_iid(interner.InternString(s.cur_token()));
1082     }
1083   });
1084   *trace_proto = trace.SerializeAsArray();
1085   return base::OkStatus();
1086 }
1087 
1088 }  // namespace perfetto::trace_processor
1089