• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Common tasks
2
3The checklists below show how to achieve some common tasks in the codebase.
4
5## Add a new ftrace event
6
71. Find the `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`.
82. Copy the format file into the codebase at `src/traced/probes/ftrace/test/data/synthetic/events/EVENT_GROUP/EVENT_NAME/format`.
93. Add the event to [src/tools/ftrace_proto_gen/event_list](/src/tools/ftrace_proto_gen/event_list).
104. Run `tools/run_ftrace_proto_gen`. This will update `protos/perfetto/trace/ftrace/ftrace_event.proto` and `protos/perfetto/trace/ftrace/GROUP_NAME.proto`.
115. Run `tools/gen_all out/YOUR_BUILD_DIRECTORY`. This will update `src/traced/probes/ftrace/event_info.cc` and `protos/perfetto/trace/perfetto_trace.proto`.
126. If special handling in `trace_processor` is desired update [src/trace_processor/importers/ftrace/ftrace_parser.cc](/src/trace_processor/importers/ftrace/ftrace_parser.cc) to parse the event.
137. Upload and land your change as normal.
14
15Here is an [example change](https://android-review.googlesource.com/c/platform/external/perfetto/+/1290645) which added the `ion/ion_stat` event.
16
17## Contribute to SQL standard library
18
191. Add or edit an SQL file inside `perfetto/src/trace_processor/stdlib/`.
202. For a new file inside an existing module add the file to the corresponding `BUILD.gn`.
213. For a new module (subdirectory of `/stdlib/`), module name (directory name) has to be added to the list in `/stdlib/BUILD.gn`.
22
23Files 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.
24
25- Running the file cannot generate any data. There can be only `CREATE_FUNCTION`, `CREATE TABLE/VIEW` or `CREATE_VIEW_FUNCTION` inside.
26- The name of each table/view/function needs to start with `{module_name}_` or `{internal_}`. Views/tables are must be `[a-z_]`, while functions are `[A-Z_]`. When a module is imported (using the `IMPORT` function), objects prefixed with internal should not be used.
27  - The only exception is the `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.
28- Every non internal object has be prefixed with an SQL comment following a particular documentation schema e.g. similar to javadoc. The schema is a comment directly over the SQL which creates it, without empty lines. Any text is going to be parsed as markdown, so usage of markdown functionality (code, links, lists) is encouraged. Whitespaces in anything apart from descriptions are ignored, so comments can be formatted neatly. If the line with description exceeds 80 chars, description can be continued in following lines.
29  - **Table/view**: each has to have object description and list of columns.
30    - Description is any text above column comments.
31    - For each column there has to be a comment line `-- @column {col name} {col description}`.
32  - **Functions**: each has to have a function description, list of arguments (names, types, description) and description of return value in this order.
33    - Function description is any text above argument comments.
34    - For each argument there has to be a comment line `-- @arg {arg name} {arg type} {arg description}`. Arg name should follow `[a-z_]*`, arg type has to be exactly the same as specified in the function, so `[A-Z]*`.
35    - Return comment is `-- @ret {return type} {return description}`. Return type should be exactly the same as specified in the function, so `[A-Z]*`.
36  - **View functions**: each has to have a function description, list of arguments (names, types, description) and list of columns.
37    - Function description is any text above argument comments.
38    - For each argument there has to be a comment line `-- @arg {arg name} {arg type} {arg description}`. Arg name should follow `[a-z_]*`, arg type has to be exactly the same as specified in the function, so `[A-Z]*`.
39    - For each column there has to be a comment line `-- @column {col name} {col description}`.
40
41NOTE: Break lines outside of import description will be ignored.
42
43Example of properly formatted view in module `android`:
44```sql
45-- Count Binder transactions per process.
46--
47-- @column process_name  Name of the process that started the binder transaction.
48-- @column pid           PID of the process that started the binder transaction.
49-- @column slice_name    Name of the slice with binder transaction.
50-- @column event_count   Number of binder transactions in process in slice.
51CREATE VIEW android_binder_metrics_by_process AS
52SELECT
53  process.name AS process_name,
54  process.pid AS pid,
55  slice.name AS slice_name,
56  COUNT(*) AS event_count
57FROM slice
58INNER JOIN thread_track ON slice.track_id = thread_track.id
59INNER JOIN thread ON thread.utid = thread_track.utid
60INNER JOIN process ON thread.upid = process.upid
61WHERE
62  slice.name GLOB 'binder*'
63GROUP BY
64  process_name,
65  slice_name;
66```
67
68Example of function in module `common`:
69```sql
70-- Extracts an int value with the given name from the metadata table.
71--
72-- @arg name STRING The name of the metadata entry.
73-- @ret LONG int_value for the given name. NULL if there's no such entry.
74SELECT CREATE_FUNCTION(
75    'EXTRACT_INT_METADATA(name STRING)',
76    'LONG',
77    'SELECT int_value FROM metadata WHERE name = ($name)');
78```
79
80Example of view function in module `android`:
81```sql
82-- Given a launch id and GLOB for a slice name, returns columns for matching slices.
83--
84-- @arg launch_id INT         Id of launch.
85-- @arg slice_name STRING     Name of slice with launch.
86-- @column slice_name         Name of slice with launch.
87-- @column slice_ts INT       Timestamp of slice start.
88-- @column slice_dur INT      Duration of slice.
89-- @column thread_name STRING Name of thread with slice
90-- @column arg_set_id INT     Arg set id.
91SELECT CREATE_VIEW_FUNCTION(
92  'ANDROID_SLICES_FOR_LAUNCH_AND_SLICE_NAME(launch_id INT, slice_name STRING)',
93  'slice_name STRING, slice_ts INT, slice_dur INT, thread_name STRING, arg_set_id INT',
94  '
95    SELECT slice_name, slice_ts, slice_dur, thread_name, arg_set_id
96    FROM thread_slices_for_all_launches
97    WHERE launch_id = $launch_id AND slice_name GLOB $slice_name
98  '
99);
100```
101
102
103## {#new-metric} Add a new trace-based metric
104
1051. Create the proto file containing the metric in the [protos/perfetto/metrics](/protos/perfetto/metrics) folder. The appropriate` BUILD.gn` file should be updated as well.
1062. Import the proto in [protos/perfetto/metrics/metrics.proto](/protos/perfetto/metrics/metrics.proto) and add a field for the new message.
1073. Run `tools/gen_all out/YOUR_BUILD_DIRECTORY`. This will update the generated headers containing the descriptors for the proto.
108  * *Note: this step has to be performed any time any metric-related proto is modified.*
109  * If you don't see anything inside the `out/` directory you might have to
110  rerun `tools/setup_all_configs.py`.
1114. Add a new SQL file for the metric to [src/trace_processor/metrics](/src/trace_processor/metrics). The appropriate `BUILD.gn` file should be updated as well.
112  * To learn how to write new metrics, see the [trace-based metrics documentation](/docs/analysis/metrics.md).
1135. Build all targets in your out directory with `tools/ninja -C out/YOUR_BUILD_DIRECTORY`.
1146. Add a new diff test for the metric. This can be done by adding files to
115the `tests.*.py` files in a proper [test/trace_processor](/test/trace_processor) subfolder.
1161. Run the newly added test with `tools/diff_test_trace_processor.py <path to trace processor binary>`.
1172. Upload and land your change as normal.
118
119Here is an [example change](https://android-review.googlesource.com/c/platform/external/perfetto/+/1290643) which added the `time_in_state` metric.
120
121## Add a new trace processor table
122
1231. Create the new table in the appropriate header file in [src/trace_processor/tables](/src/trace_processor/tables) by copying one of the existing macro definitions.
124  * Make sure to understand whether a root or derived table is needed and copy the appropriate one. For more information see the [trace processor](/docs/analysis/trace-processor.md) documentation.
1252. Register the table with the trace processor in the constructor for the [TraceProcessorImpl class](/src/trace_processor/trace_processor_impl.cc).
1263. If also implementing ingestion of events into the table:
127  1. Modify the appropriate parser class in [src/trace_processor/importers](/src/trace_processor/importers) and add the code to add rows to the newly added table.
128  2. Add a new diff test for the added parsing code and table.
129  3. Run the newly added test with `tools/diff_test_trace_processor.py <path to trace processor shell binary>`.
1304. Upload and land your change as normal.
131
132## Adding new derived events
133
134As derived events depend on metrics, the initial steps are same as that of developing a metric (see above).
135
136NOTE: 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.
137
138To extend a metric with annotations:
139
1401. Create a new table or view with the name `<metric name>_event`.
141  * For example, for the [`android_startup`]() metric, we create a view named `android_startup_event`.
142  * Note that the trailing `_event` suffix in the table name is important.
143  * The schema required for this table is given below.
1442. List your metric in the `initialiseHelperViews` method of `trace_controller.ts`.
1453. Upload and land your change as normal.
146
147The schema of the `<metric name>_event` table/view is as follows:
148
149| Name         | Type     | Presence                              | Meaning                                                                                                                                                                                                                                     |
150| :----------- | -------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
151| `track_type` | `string` | Mandatory                             | 'slice' for slices, 'counter' for counters                                                                                                                                                                                                  |
152| `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.                                                                                                          |
153| `ts`         | `int64`  | Mandatory                             | The timestamp of the event (slice or counter)                                                                                                                                                                                               |
154| `dur`        | `int64`  | Mandatory for slice, NULL for counter | The duration of the slice                                                                                                                                                                                                                   |
155| `slice_name` | `string` | Mandatory for slice, NULL for counter | The name of the slice                                                                                                                                                                                                                       |
156| `value`      | `double` | Mandatory for counter, NULL for slice | The value of the counter                                                                                                                                                                                                                    |
157| `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. |
158
159#### Known issues:
160
161* Nested slices within the same track are not supported. We plan to support this
162  once we have a concrete usecase.
163* Tracks are always created in the global scope. We plan to extend this to
164  threads and processes in the near future with additional contexts added as
165  necessary.
166* Instant events are currently not supported in the UI but this will be
167  implemented in the near future. In trace processor, instants are always `0`
168  duration slices with special rendering on the UI side.
169* There is no way to tie newly added events back to the source events in the
170  trace which were used to generate them. This is not currently a priority but
171  something we may add in the future.
172