blob: ed2b13ffd49d7df2c73376dbe4cac8737de4f541 [file]
/*
* Copyright (C) 2018 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 INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_
#define INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "perfetto/base/export.h"
#include "perfetto/base/status.h"
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/iterator.h"
#include "perfetto/trace_processor/metatrace_config.h"
#include "perfetto/trace_processor/summarizer.h"
#include "perfetto/trace_processor/trace_blob_view.h"
#include "perfetto/trace_processor/trace_processor_storage.h"
namespace perfetto::trace_processor {
namespace io {
class FileSystem;
} // namespace io
class PERFETTO_EXPORT_COMPONENT TraceProcessor_PlatformInterface {
public:
virtual ~TraceProcessor_PlatformInterface();
// Returns the filesystem exposed to Trace Processor. The returned object
// must outlive the TraceProcessor instance. Supplying a filesystem does not
// enable SQL file access unless Config::enable_sql_file_access is also set.
virtual io::FileSystem* GetFileSystem() { return nullptr; }
};
// Extends TraceProcessorStorage to support execution of SQL queries on loaded
// traces. See TraceProcessorStorage for parsing of trace files.
class PERFETTO_EXPORT_COMPONENT TraceProcessor : public TraceProcessorStorage {
public:
// For legacy API clients. Iterator used to be a nested class here. Many API
// clients depends on it at this point.
using Iterator = ::perfetto::trace_processor::Iterator;
using PlatformInterface = TraceProcessor_PlatformInterface;
// Creates a new instance of TraceProcessor. |platform| is optional and, when
// provided, must outlive the returned instance.
static std::unique_ptr<TraceProcessor> CreateInstance(const Config&);
static std::unique_ptr<TraceProcessor> CreateInstance(
const Config&,
PlatformInterface* platform);
~TraceProcessor() override;
// =================================================================
// | Trace loading related functionality starts here |
// =================================================================
// The entry point to push trace data into the processor. The trace format
// will be automatically discovered on the first push call. It is possible
// to make queries between two pushes.
// Returns the Ok status if parsing has been succeeding so far, and Error
// status if some unrecoverable error happened. If this happens, the
// TraceProcessor will ignore the following Parse() requests, drop data on the
// floor and return errors forever.
base::Status Parse(TraceBlobView) override = 0;
// Shorthand for Parse(TraceBlobView(TraceBlob(TakeOwnership(buf, size))).
// For compatibility with older API clients.
base::Status Parse(std::unique_ptr<uint8_t[]> buf, size_t size);
// Forces all data in the trace to be pushed to tables without buffering data
// in sorting queues. This is useful if queries need to be performed to
// compute post-processing data (e.g. deobfuscation, symbolization etc) which
// will be appended to the trace in a future call to Parse.
void Flush() override = 0;
// Calls Flush and finishes all of the actions required for parsing the trace.
// Calling this function multiple times is undefined behaviour.
base::Status NotifyEndOfFile() override = 0;
// =================================================================
// | PerfettoSQL related functionality starts here |
// =================================================================
// Executes the SQL on the loaded portion of the trace.
//
// Terminology: a *query* is a string of one or more semicolon-separated
// *statements*.
//
// More than one SQL statement can be passed to this function; all but the
// last will be fully executed by this function before retuning. The last
// statement will be executed and will yield rows as the caller calls Next()
// over the returned Iterator.
//
// See documentation of the Iterator class for an example on how to use
// the returned iterator.
virtual Iterator ExecuteQuery(const std::string& sql) = 0;
// ADVANCED: most users should use ExecuteQuery instead, which executes a
// whole query in one call. This function is only useful for the rare
// clients which need the result set of *every* statement in a query
// rather than just the last one (e.g. shells printing each result).
//
// Executes the next statement of |sql| starting at |*offset|, mirroring
// sqlite3_prepare_v2's pzTail model: callers loop, passing the same |sql|
// each time with |offset| carried over between calls. On success,
// |*offset| is advanced just past the executed statement and the returned
// Iterator yields the statement's rows. Returns std::nullopt once only
// whitespace/comments remain.
//
// |*offset| should be initialized to 0 and otherwise treated as an opaque
// cursor: pass values back unchanged rather than computing them. They are
// byte offsets into |sql| after the same normalization ExecuteQuery
// applies (e.g. non-breaking spaces replaced with spaces), so they may
// not correspond exactly to offsets into |sql| as passed.
//
// Errors are reported via the returned Iterator's Status(), with
// tracebacks referencing the full |sql| source; |*offset| is unchanged on
// error.
virtual std::optional<Iterator> ExecuteNextStatement(const std::string& sql,
uint32_t* offset) = 0;
// Registers SQL files with the associated path under the package named
// |sql_package.name|.
//
// For example, if you registered a package called "camera" with a file path
// "camera/cpu/metrics.sql" you can include it (run the file) using "INCLUDE
// PERFETTO MODULE camera.cpu.metrics". The first word of the string has to be
// a package name and there can be only one package registered with a given
// name.
virtual base::Status RegisterSqlPackage(SqlPackage) = 0;
// =================================================================
// | Trace summary related functionality starts here |
// =================================================================
// Creates a summary of the trace as defined by the `computation` and `specs`
// parameters.
//
// `computation` is a `TraceSummaryComputationSpec` struct which decides how
// the trace should be summarized. It does not contain any business logic
// itself, instead just referencing the contents of `specs`.
//
// Each entry in `specs` should point to an instance of the `TraceSummarySpec`
// proto with `spec_format` defining the file format of each specs. This
// function accepts a vector to make it easy to compute metrics in the common
// case of having many different `TraceSummarySpec` files, each with a subset
// of the summary to be computed (e.g. metrics shareded across multiple
// files).
//
// The result of computing the summary will be returned in `output` (with a
// schema specified by the `TraceSummary` proto) with `output_spec` defining
// the format that the data should be returned in.
//
// Conceptual note: this function is designed with a split in `computation`
// vs `specs` is to allow for `specs` to be stored as self-contained set of
// protos on the filesystem or in a git repo which are then referenced by the
// embedder of trace processor to actually decide which parts of the spec
// matter for a particular trace. This allows decoupling what should be
// computed from how that computation should happen.
//
// Implementation note: after this function returns, any or all of the
// referenced PerfettoSQL modules in any computed metrics will remain
// included. This behaviour is *not* considered part of the API and should not
// be relied on. It is likely this will change in the future.
virtual base::Status Summarize(
const TraceSummaryComputationSpec& computation,
const std::vector<TraceSummarySpecBytes>& specs,
std::vector<uint8_t>* output,
const TraceSummaryOutputSpec& output_spec) = 0;
// =================================================================
// | Metatracing related functionality starts here |
// =================================================================
// Enables "meta-tracing" of trace processor.
// Metatracing involves tracing trace processor itself to root-cause
// performace issues in trace processor. See |DisableAndReadMetatrace| for
// more information on the format of the metatrace.
using MetatraceConfig = metatrace::MetatraceConfig;
using MetatraceCategories = metatrace::MetatraceCategories;
virtual void EnableMetatrace(MetatraceConfig config = {}) = 0;
// Disables "meta-tracing" of trace processor and writes the trace as a
// sequence of |TracePackets| into |trace_proto| returning the status of this
// read.
virtual base::Status DisableAndReadMetatrace(
std::vector<uint8_t>* trace_proto) = 0;
// =================================================================
// | Advanced functionality starts here |
// =================================================================
// Sets/returns the name of the currently loaded trace or an empty string if
// no trace is fully loaded yet. This has no effect on the Trace Processor
// functionality and is used for UI purposes only.
// The returned name is NOT a path and will contain extra text w.r.t. the
// argument originally passed to SetCurrentTraceName(), e.g., "file (42 MB)".
virtual std::string GetCurrentTraceName() = 0;
virtual void SetCurrentTraceName(const std::string&) = 0;
// Registers the contents of a file.
// This method can be used to pass out of band data to the trace processor
// which can be used by importers to do some advanced processing. For example
// if you pass binaries these are used to decode ETM traces.
// Registering the same file twice will return an error.
virtual base::Status RegisterFileContent(const std::string& path,
TraceBlob content) = 0;
// Interrupts the current query. Typically used by Ctrl-C handler.
virtual void InterruptQuery() = 0;
// Restores Trace Processor to its pristine state. It preserves the built-in
// tables/views/functions created by the ingestion process. Returns the number
// of objects created in runtime that has been deleted.
// NOTE: No Iterators can active when called.
virtual size_t RestoreInitialTables() = 0;
// =================================================================
// | Trace-based metrics (v1) related functionality starts here |
// =================================================================
//
// WARNING: The metrics v1 system is "soft" deprecated: no new metrics are
// allowed but we still fully support any existing metrics written using this
// system.
//
// If possible, prefer using the metrics v2 methods above for any new
// usecases.
// Registers a metric at the given path which will run the specified SQL.
virtual base::Status RegisterMetric(const std::string& path,
const std::string& sql) = 0;
// Reads the FileDescriptorSet proto message given by |data| and |size| and
// adds any extensions to the metrics proto to allow them to be available as
// proto builder functions when computing metrics.
virtual base::Status ExtendMetricsProto(const uint8_t* data, size_t size) = 0;
// Behaves exactly as ExtendMetricsProto, except any FileDescriptor with
// filename matching a prefix in |skip_prefixes| is skipped.
virtual base::Status ExtendMetricsProto(
const uint8_t* data,
size_t size,
const std::vector<std::string>& skip_prefixes) = 0;
// Computes the given metrics on the loded portion of the trace. If
// successful, the output argument |metrics_proto| will be filled with the
// proto-encoded bytes for the message TraceMetrics in
// perfetto/metrics/metrics.proto.
virtual base::Status ComputeMetric(
const std::vector<std::string>& metric_names,
std::vector<uint8_t>* metrics_proto) = 0;
enum MetricResultFormat {
kProtoText = 0,
kJson = 1,
};
// Computes metrics as the ComputeMetric function above, but instead of
// producing proto encoded bytes, the output argument |metrics_string| is
// filled with the metric formatted in the requested |format|.
virtual base::Status ComputeMetricText(
const std::vector<std::string>& metric_names,
MetricResultFormat format,
std::string* metrics_string) = 0;
// Gets all the currently loaded proto descriptors used in metric computation.
// This includes all compiled-in binary descriptors, and all proto descriptors
// loaded by trace processor shell at runtime. The message is encoded as
// DescriptorSet, defined in perfetto/trace_processor/trace_processor.proto.
virtual std::vector<uint8_t> GetMetricDescriptors() = 0;
// =================================================================
// | EXPERIMENTAL: Export functionality starts here |
// =================================================================
//
// WARNING: This API is under active development and may change without
// notice. Do not depend on this interface in production code.
enum class ExportFormat {
// A standard SQLite database containing all SQL-visible Perfetto tables
// and views, including objects created at runtime. This format requires an
// ExportOutput which provides a file path.
kSqlite,
// A Perfetto-internal archive that can be loaded as input by a fresh Trace
// Processor instance from the same version. Loading it in a different
// version may work but is not guaranteed.
kPerfetto,
// A tar archive containing one standard Arrow file per statically
// registered table. Its representation has cross-version compatibility
// guarantees and is intended for external consumers, which should ignore
// unrecognized members. It cannot be loaded back into Trace Processor; use
// kPerfetto for that.
kArrowTar,
};
class PERFETTO_EXPORT_COMPONENT ExportOutput {
public:
ExportOutput();
virtual ~ExportOutput();
// Receives consecutive output chunks synchronously. A non-ok return aborts
// the export and is returned from Export().
virtual base::Status Write(const void* data, size_t size) = 0;
// An optional alternative to Write(). A format which needs random-access
// output may create or overwrite this file directly, in which case Write()
// is not called. Streaming formats may ignore this alternative.
virtual std::optional<std::string> GetFilePath() const;
};
// EXPERIMENTAL: Exports the contents of Trace Processor without
// materializing the complete output in memory. The exact contents exported
// are defined by |format|.
virtual base::Status Export(ExportFormat format, ExportOutput* output) = 0;
// =================================================================
// | EXPERIMENTAL: Summarizer related functionality starts here |
// =================================================================
//
// WARNING: This API is under active development and may change without
// notice. Do not depend on this interface in production code.
// EXPERIMENTAL: Creates a new Summarizer instance for managing lazy
// materialization of structured queries. On success, |out| is populated with
// the new instance and ownership is transferred to the caller.
virtual base::Status CreateSummarizer(std::unique_ptr<Summarizer>* out) = 0;
};
} // namespace perfetto::trace_processor
#endif // INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_