The checklists below show how to achieve some common tasks in the codebase.
format
file for your event. The location of the file depends where tracefs
is mounted but can often be found at /sys/kernel/debug/tracing/events/EVENT_GROUP/EVENT_NAME/format
.src/traced/probes/ftrace/test/data/synthetic/events/EVENT_GROUP/EVENT_NAME/format
.tools/run_ftrace_proto_gen
. This will update protos/perfetto/trace/ftrace/ftrace_event.proto
and protos/perfetto/trace/ftrace/GROUP_NAME.proto
.tools/gen_all out/YOUR_BUILD_DIRECTORY
. This will update src/traced/probes/ftrace/event_info.cc
and protos/perfetto/trace/perfetto_trace.proto
.trace_processor
is desired update src/trace_processor/importers/ftrace/ftrace_parser.cc to parse the event.Here is an example change which added the ion/ion_stat
event.
perfetto/src/trace_processor/stdlib/
.BUILD.gn
./stdlib/
), module name (directory name) has to be added to the list in /stdlib/BUILD.gn
.Files inside the standard library have to be formatted in a very specific way, as its structure is used to generate documentation. There are presubmit checks, but they are not infallible.
CREATE PERFETTO FUNCTION
, CREATE PERFETTO TABLE
and CREATE PERFETTO VIEW
statements inside.{module_name}_
or {internal_}
. The names of views/tables/functions are must be [a-z_]
. When a module is imported (using the IMPORT
function), objects prefixed with internal should not be used.common
module. The name of functions/views/tables inside should not be prefixed with common_
, as they are supposed to be module agnostic and widely used.CREATE PERFETTO {TABLE,VIEW}
statement.CREATE PERFETTO FUNCTION
statement.RETURNS
.CREATE PERFETTO FUNCTION
statement.NOTE: Break lines outside of import description will be ignored.
Example of properly formatted view in module android
:
-- Count Binder transactions per process. CREATE PERFETTO VIEW android_binder_metrics_by_process( -- Name of the process that started the binder transaction. process_name STRING, -- PID of the process that started the binder transaction. pid INT, -- Name of the slice with binder transaction. slice_name STRING, -- Number of binder transactions in process in slice. event_count INT ) AS SELECT process.name AS process_name, process.pid AS pid, slice.name AS slice_name, COUNT(*) AS event_count FROM slice INNER JOIN thread_track ON slice.track_id = thread_track.id INNER JOIN thread ON thread.utid = thread_track.utid INNER JOIN process ON thread.upid = process.upid WHERE slice.name GLOB 'binder*' GROUP BY process_name, slice_name;
Example of function in module common
:
-- Extracts an int value with the given name from the metadata table. CREATE PERFETTO FUNCTION extract_int_metadata( -- The name of the metadata entry. name STRING) -- int_value for the given name. NULL if there's no such entry. RETURNS LONG AS SELECT int_value FROM metadata WHERE name = ($name)
Example of table function in module android
:
-- Given a launch id and GLOB for a slice name, returns columns for matching slices. CREATE PERFETTO FUNCTION ANDROID_SLICES_FOR_LAUNCH_AND_SLICE_NAME( -- Id of launch. launch_id INT, -- Name of slice with launch. slice_name STRING ) RETURNS TABLE( -- Name of slice with launch. slice_name STRING, -- Timestamp of slice start. slice_ts INT, -- Duration of slice. slice_dur INT, -- Name of thread with slice. thread_name STRING, -- Arg set id. arg_set_id INT ) AS SELECT slice_name, slice_ts, slice_dur, thread_name, arg_set_id FROM thread_slices_for_all_launches WHERE launch_id = $launch_id AND slice_name GLOB $slice_name;
BUILD.gn
file should be updated as well.tools/gen_all out/YOUR_BUILD_DIRECTORY
. This will update the generated headers containing the descriptors for the proto.out/
directory you might have to rerun tools/setup_all_configs.py
.BUILD.gn
file should be updated as well.tools/ninja -C out/YOUR_BUILD_DIRECTORY
.tests.*.py
files in a proper test/trace_processor subfolder.tools/diff_test_trace_processor.py <path to trace processor binary>
.Here is an example change which added the time_in_state
metric.
tools/diff_test_trace_processor.py <path to trace processor shell binary>
.As derived events depend on metrics, the initial steps are same as that of developing a metric (see above).
NOTE: the metric can be just an empty proto message during prototyping or if no summarization is necessary. However, generally if an event is important enough to display in the UI, it should also be tracked in benchmarks as a metric.
To extend a metric with annotations:
<metric name>_event
.android_startup
metric, we create a view named android_startup_event
._event
suffix in the table name is important.initialiseHelperViews
method of trace_controller.ts
.The schema of the <metric name>_event
table/view is as follows:
Name | Type | Presence | Meaning |
---|---|---|---|
track_type | string | Mandatory | ‘slice’ for slices, ‘counter’ for counters |
track_name | string | Mandatory | Name of the track to display in the UI. Also the track identifier i.e. all events with same track_name appear on the same track. |
ts | int64 | Mandatory | The timestamp of the event (slice or counter) |
dur | int64 | Mandatory for slice, NULL for counter | The duration of the slice |
slice_name | string | Mandatory for slice, NULL for counter | The name of the slice |
value | double | Mandatory for counter, NULL for slice | The value of the counter |
group_name | string | Optional | Name of the track group under which the track appears. All tracks with the same group_name are placed under the same group by that name. Tracks that lack this field or have NULL value in this field are displayed without any grouping. |
0
duration slices with special rendering on the UI side.TRACE_PROCESSOR_CURRENT_API_VERSION
Generally you do not have to worry about version skew between the UI and the trace_processor
since they are built together at the same commit. However version skew can occur when using the --httpd
mode which allows a native trace_processor
instance to be used with the UI.
A common case is when the UI is more recent than trace_processor
and depends on a new table definition. With older versions of trace_processor
in --httpd
mode the UI crashes attempting to query a non-existant table. To avoid this we use a version number. If the version number trace_processor
reports is older than the one the UI was built with we prompt the user to update.
protos/perfetto/trace_processor/trace_processor.proto
TRACE_PROCESSOR_CURRENT_API_VERSION