blob: c09e8566935f3c3a6553581bc1ddd39191ddb3fe [file]
/*
* Copyright (C) 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_TRACE_PROCESSOR_PLUGINS_FLAMEGRAPH_FLAMEGRAPH_FUNCTION_H_
#define SRC_TRACE_PROCESSOR_PLUGINS_FLAMEGRAPH_FLAMEGRAPH_FUNCTION_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/core/tree/tree.h"
#include "src/trace_processor/perfetto_sql/engine/perfetto_sql_connection.h"
#include "src/trace_processor/plugins/flamegraph/flamegraph.h"
#include "src/trace_processor/sqlite/bindings/sqlite_function.h"
#include "src/trace_processor/sqlite/bindings/sqlite_module.h"
#include "src/trace_processor/sqlite/module_state_manager.h"
namespace perfetto::trace_processor {
struct FlamegraphRegexSpec {
std::string pattern;
bool case_insensitive = false;
};
struct FlamegraphFilterSpec {
enum class Kind {
kShowStack,
kHideStack,
kHideFrame,
};
Kind kind;
FlamegraphRegexSpec regex;
};
struct FlamegraphAggregateSpec {
flamegraph::Config::Aggregate aggregate;
std::string input_name;
std::string output_name;
};
// Query-specific configuration passed from the scalar config builder to the
// virtual table in the same SQLite statement.
struct FlamegraphQuery {
flamegraph::Config::View view = flamegraph::Config::View::kTopDown;
std::optional<FlamegraphRegexSpec> view_pattern;
std::vector<FlamegraphFilterSpec> filters;
std::vector<std::string> grouping_columns;
std::vector<std::string> value_columns;
std::vector<FlamegraphAggregateSpec> aggregate_columns;
};
// Builds the opaque argument consumed by a flamegraph virtual table call.
struct FlamegraphConfigFunction
: public sqlite::Function<FlamegraphConfigFunction> {
static constexpr char kName[] = "__intrinsic_flamegraph_config";
static constexpr int kArgCount = -1;
using UserData = StringPool;
static void Step(sqlite3_context*, int argc, sqlite3_value** argv);
};
// Create-only virtual table operator. The module argument is the immutable raw
// source table; calls on the created table provide only a FlamegraphQuery.
struct FlamegraphOperator : sqlite::Module<FlamegraphOperator> {
struct State {
StringPool* pool = nullptr;
core::Tree source;
std::vector<std::string> property_names;
std::vector<std::string> candidate_value_names;
double unfiltered_value = 0;
};
struct Context : sqlite::ModuleStateManager<FlamegraphOperator> {
Context(PerfettoSqlConnection* _connection, StringPool* _pool)
: sqlite::ModuleStateManager<FlamegraphOperator>(owned_store_),
connection(_connection),
pool(_pool) {}
PerfettoSqlConnection* connection;
StringPool* pool;
private:
sqlite::CommittedStateManager owned_store_;
};
struct Vtab : sqlite::Module<FlamegraphOperator>::Vtab {
sqlite::ModuleStateManager<FlamegraphOperator>::PerVtabState* state;
};
struct Cursor : sqlite::Module<FlamegraphOperator>::Cursor {
std::unique_ptr<core::Tree> result;
std::string value_column;
uint32_t row = 0;
bool stats = false;
};
static constexpr auto kType = kCreateOnly;
static constexpr bool kSupportsWrites = false;
static constexpr bool kDoesOverloadFunctions = false;
static int Create(sqlite3*,
void*,
int,
const char* const*,
sqlite3_vtab**,
char**);
static int Destroy(sqlite3_vtab*);
static int Connect(sqlite3*,
void*,
int,
const char* const*,
sqlite3_vtab**,
char**);
static int Disconnect(sqlite3_vtab*);
static int BestIndex(sqlite3_vtab*, sqlite3_index_info*);
static int Open(sqlite3_vtab*, sqlite3_vtab_cursor**);
static int Close(sqlite3_vtab_cursor*);
static int Filter(sqlite3_vtab_cursor*,
int,
const char*,
int,
sqlite3_value**);
static int Next(sqlite3_vtab_cursor*);
static int Eof(sqlite3_vtab_cursor*);
static int Column(sqlite3_vtab_cursor*, sqlite3_context*, int);
static int Rowid(sqlite3_vtab_cursor*, sqlite_int64*);
static int Begin(sqlite3_vtab*) { return SQLITE_OK; }
static int Sync(sqlite3_vtab*) { return SQLITE_OK; }
static int Commit(sqlite3_vtab*) { return SQLITE_OK; }
static int Rollback(sqlite3_vtab*) { return SQLITE_OK; }
static int Savepoint(sqlite3_vtab* table, int savepoint) {
Vtab* vtab = GetVtab(table);
sqlite::ModuleStateManager<FlamegraphOperator>::OnSavepoint(vtab->state,
savepoint);
return SQLITE_OK;
}
static int Release(sqlite3_vtab* table, int savepoint) {
Vtab* vtab = GetVtab(table);
sqlite::ModuleStateManager<FlamegraphOperator>::OnRelease(vtab->state,
savepoint);
return SQLITE_OK;
}
static int RollbackTo(sqlite3_vtab* table, int savepoint) {
Vtab* vtab = GetVtab(table);
sqlite::ModuleStateManager<FlamegraphOperator>::OnRollbackTo(vtab->state,
savepoint);
return SQLITE_OK;
}
static constexpr sqlite3_module kModule = CreateModule();
};
} // namespace perfetto::trace_processor
namespace perfetto::trace_processor::flamegraph {
void RegisterPlugin();
} // namespace perfetto::trace_processor::flamegraph
#endif // SRC_TRACE_PROCESSOR_PLUGINS_FLAMEGRAPH_FLAMEGRAPH_FUNCTION_H_