xref: /aosp_15_r20/external/perfetto/docs/analysis/trace-processor.md (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker# Trace Processor (C++)
2*6dbdd20aSAndroid Build Coastguard Worker
3*6dbdd20aSAndroid Build Coastguard Worker_The Trace Processor is a C++ library
4*6dbdd20aSAndroid Build Coastguard Worker([/src/trace_processor](/src/trace_processor)) that ingests traces encoded in a
5*6dbdd20aSAndroid Build Coastguard Workerwide variety of formats and exposes an SQL interface for querying trace events
6*6dbdd20aSAndroid Build Coastguard Workercontained in a consistent set of tables. It also has other features including
7*6dbdd20aSAndroid Build Coastguard Workercomputation of summary metrics, annotating the trace with user-friendly
8*6dbdd20aSAndroid Build Coastguard Workerdescriptions and deriving new events from the contents of the trace._
9*6dbdd20aSAndroid Build Coastguard Worker
10*6dbdd20aSAndroid Build Coastguard Worker![Trace processor block diagram](/docs/images/trace-processor.png)
11*6dbdd20aSAndroid Build Coastguard Worker
12*6dbdd20aSAndroid Build Coastguard Worker## Quickstart
13*6dbdd20aSAndroid Build Coastguard Worker
14*6dbdd20aSAndroid Build Coastguard WorkerThe [quickstart](/docs/quickstart/trace-analysis.md) provides a quick overview
15*6dbdd20aSAndroid Build Coastguard Workeron how to run SQL queries against traces using trace processor.
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker## Introduction
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard WorkerEvents in a trace are optimized for fast, low-overhead recording. Therefore
20*6dbdd20aSAndroid Build Coastguard Workertraces need significant data processing to extract meaningful information from
21*6dbdd20aSAndroid Build Coastguard Workerthem. This is compounded by the number of legacy formats which are still in use and
22*6dbdd20aSAndroid Build Coastguard Workerneed to be supported in trace analysis tools.
23*6dbdd20aSAndroid Build Coastguard Worker
24*6dbdd20aSAndroid Build Coastguard WorkerThe trace processor abstracts this complexity by parsing traces, extracting the
25*6dbdd20aSAndroid Build Coastguard Workerdata inside, and exposing it in a set of database tables which can be queried
26*6dbdd20aSAndroid Build Coastguard Workerwith SQL.
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard WorkerFeatures of the trace processor include:
29*6dbdd20aSAndroid Build Coastguard Worker
30*6dbdd20aSAndroid Build Coastguard Worker* Execution of SQL queries on a custom, in-memory, columnar database backed by
31*6dbdd20aSAndroid Build Coastguard Worker  the SQLite query engine.
32*6dbdd20aSAndroid Build Coastguard Worker* Metrics subsystem which allows computation of summarized view of the trace
33*6dbdd20aSAndroid Build Coastguard Worker  (e.g. CPU or memory usage of a process, time taken for app startup etc.).
34*6dbdd20aSAndroid Build Coastguard Worker* Annotating events in the trace with user-friendly descriptions, providing
35*6dbdd20aSAndroid Build Coastguard Worker  context and explanation of events to newer users.
36*6dbdd20aSAndroid Build Coastguard Worker* Creation of new events derived from the contents of the trace.
37*6dbdd20aSAndroid Build Coastguard Worker
38*6dbdd20aSAndroid Build Coastguard WorkerThe formats supported by trace processor include:
39*6dbdd20aSAndroid Build Coastguard Worker
40*6dbdd20aSAndroid Build Coastguard Worker* Perfetto native protobuf format
41*6dbdd20aSAndroid Build Coastguard Worker* Linux ftrace
42*6dbdd20aSAndroid Build Coastguard Worker* Android systrace
43*6dbdd20aSAndroid Build Coastguard Worker* Chrome JSON (including JSON embedding Android systrace text)
44*6dbdd20aSAndroid Build Coastguard Worker* Fuchsia binary format
45*6dbdd20aSAndroid Build Coastguard Worker* [Ninja](https://ninja-build.org/) logs (the build system)
46*6dbdd20aSAndroid Build Coastguard Worker
47*6dbdd20aSAndroid Build Coastguard WorkerThe trace processor is embedded in a wide variety of trace analysis tools, including:
48*6dbdd20aSAndroid Build Coastguard Worker
49*6dbdd20aSAndroid Build Coastguard Worker* [trace_processor](/docs/analysis/trace-processor.md), a standalone binary
50*6dbdd20aSAndroid Build Coastguard Worker   providing a shell interface (and the reference embedder).
51*6dbdd20aSAndroid Build Coastguard Worker* [Perfetto UI](https://ui.perfetto.dev), in the form of a WebAssembly module.
52*6dbdd20aSAndroid Build Coastguard Worker* [Android GPU Inspector](https://gpuinspector.dev/).
53*6dbdd20aSAndroid Build Coastguard Worker* [Android Studio](https://developer.android.com/studio/).
54*6dbdd20aSAndroid Build Coastguard Worker
55*6dbdd20aSAndroid Build Coastguard Worker## Concepts
56*6dbdd20aSAndroid Build Coastguard Worker
57*6dbdd20aSAndroid Build Coastguard WorkerThe trace processor has some foundational terminology and concepts which are
58*6dbdd20aSAndroid Build Coastguard Workerused in the rest of documentation.
59*6dbdd20aSAndroid Build Coastguard Worker
60*6dbdd20aSAndroid Build Coastguard Worker### Events
61*6dbdd20aSAndroid Build Coastguard Worker
62*6dbdd20aSAndroid Build Coastguard WorkerIn the most general sense, a trace is simply a collection of timestamped
63*6dbdd20aSAndroid Build Coastguard Worker"events". Events can have associated metadata and context which allows them to
64*6dbdd20aSAndroid Build Coastguard Workerbe interpreted and analyzed.
65*6dbdd20aSAndroid Build Coastguard Worker
66*6dbdd20aSAndroid Build Coastguard WorkerEvents form the foundation of trace processor and are one of two types: slices
67*6dbdd20aSAndroid Build Coastguard Workerand counters.
68*6dbdd20aSAndroid Build Coastguard Worker
69*6dbdd20aSAndroid Build Coastguard Worker#### Slices
70*6dbdd20aSAndroid Build Coastguard Worker
71*6dbdd20aSAndroid Build Coastguard Worker![Examples of slices](/docs/images/slices.png)
72*6dbdd20aSAndroid Build Coastguard Worker
73*6dbdd20aSAndroid Build Coastguard WorkerA slice refers to an interval of time with some data describing what was
74*6dbdd20aSAndroid Build Coastguard Workerhappening in that interval. Some example of slices include:
75*6dbdd20aSAndroid Build Coastguard Worker
76*6dbdd20aSAndroid Build Coastguard Worker* Scheduling slices for each CPU
77*6dbdd20aSAndroid Build Coastguard Worker* Atrace slices on Android
78*6dbdd20aSAndroid Build Coastguard Worker* Userspace slices from Chrome
79*6dbdd20aSAndroid Build Coastguard Worker
80*6dbdd20aSAndroid Build Coastguard Worker#### Counters
81*6dbdd20aSAndroid Build Coastguard Worker
82*6dbdd20aSAndroid Build Coastguard Worker![Examples of counters](/docs/images/counters.png)
83*6dbdd20aSAndroid Build Coastguard Worker
84*6dbdd20aSAndroid Build Coastguard WorkerA counter is a continuous value which varies over time. Some examples of
85*6dbdd20aSAndroid Build Coastguard Workercounters include:
86*6dbdd20aSAndroid Build Coastguard Worker
87*6dbdd20aSAndroid Build Coastguard Worker* CPU frequency for each CPU core
88*6dbdd20aSAndroid Build Coastguard Worker* RSS memory events - both from the kernel and polled from /proc/stats
89*6dbdd20aSAndroid Build Coastguard Worker* atrace counter events from Android
90*6dbdd20aSAndroid Build Coastguard Worker* Chrome counter events
91*6dbdd20aSAndroid Build Coastguard Worker
92*6dbdd20aSAndroid Build Coastguard Worker### Tracks
93*6dbdd20aSAndroid Build Coastguard Worker
94*6dbdd20aSAndroid Build Coastguard WorkerA track is a named partition of events of the same type and the same associated
95*6dbdd20aSAndroid Build Coastguard Workercontext. For example:
96*6dbdd20aSAndroid Build Coastguard Worker
97*6dbdd20aSAndroid Build Coastguard Worker* Scheduling slices have one track for each CPU
98*6dbdd20aSAndroid Build Coastguard Worker* Sync userspace slice have one track for each thread which emitted an event
99*6dbdd20aSAndroid Build Coastguard Worker* Async userspace slices have one track for each “cookie” linking a set of async
100*6dbdd20aSAndroid Build Coastguard Worker  events
101*6dbdd20aSAndroid Build Coastguard Worker
102*6dbdd20aSAndroid Build Coastguard WorkerThe most intuitive way to think of a track is to imagine how they would be drawn
103*6dbdd20aSAndroid Build Coastguard Workerin a UI; if all the events are in a single row, they belong to the same track.
104*6dbdd20aSAndroid Build Coastguard WorkerFor example, all the scheduling events for CPU 5 are on the same track:
105*6dbdd20aSAndroid Build Coastguard Worker
106*6dbdd20aSAndroid Build Coastguard Worker![CPU slices track](/docs/images/cpu-slice-track.png)
107*6dbdd20aSAndroid Build Coastguard Worker
108*6dbdd20aSAndroid Build Coastguard WorkerTracks can be split into various types based on the type of event they contain
109*6dbdd20aSAndroid Build Coastguard Workerand the context they are associated with. Examples include:
110*6dbdd20aSAndroid Build Coastguard Worker
111*6dbdd20aSAndroid Build Coastguard Worker* Global tracks are not associated to any context and contain slices
112*6dbdd20aSAndroid Build Coastguard Worker* Thread tracks are associated to a single thread and contain slices
113*6dbdd20aSAndroid Build Coastguard Worker* Counter tracks are not associated to any context and contain counters
114*6dbdd20aSAndroid Build Coastguard Worker* CPU counter tracks are associated to a single CPU and contain counters
115*6dbdd20aSAndroid Build Coastguard Worker
116*6dbdd20aSAndroid Build Coastguard Worker### Thread and process identifiers
117*6dbdd20aSAndroid Build Coastguard Worker
118*6dbdd20aSAndroid Build Coastguard WorkerThe handling of threads and processes needs special care when considered in the
119*6dbdd20aSAndroid Build Coastguard Workercontext of tracing; identifiers for threads and processes (e.g. `pid`/`tgid` and
120*6dbdd20aSAndroid Build Coastguard Worker`tid` in Android/macOS/Linux) can be reused by the operating system over the
121*6dbdd20aSAndroid Build Coastguard Workercourse of a trace. This means they cannot be relied upon as a unique identifier
122*6dbdd20aSAndroid Build Coastguard Workerwhen querying tables in trace processor.
123*6dbdd20aSAndroid Build Coastguard Worker
124*6dbdd20aSAndroid Build Coastguard WorkerTo solve this problem, the trace processor uses `utid` (_unique_ tid) for
125*6dbdd20aSAndroid Build Coastguard Workerthreads and `upid` (_unique_ pid) for processes. All references to threads and
126*6dbdd20aSAndroid Build Coastguard Workerprocesses (e.g. in CPU scheduling data, thread tracks) uses `utid` and `upid`
127*6dbdd20aSAndroid Build Coastguard Workerinstead of the system identifiers.
128*6dbdd20aSAndroid Build Coastguard Worker
129*6dbdd20aSAndroid Build Coastguard Worker## Writing Queries
130*6dbdd20aSAndroid Build Coastguard Worker
131*6dbdd20aSAndroid Build Coastguard Worker### Context using tracks
132*6dbdd20aSAndroid Build Coastguard Worker
133*6dbdd20aSAndroid Build Coastguard WorkerA common question when querying tables in trace processor is: "how do I obtain
134*6dbdd20aSAndroid Build Coastguard Workerthe process or thread for a slice?". Phrased more generally, the question is
135*6dbdd20aSAndroid Build Coastguard Worker"how do I get the context for an event?".
136*6dbdd20aSAndroid Build Coastguard Worker
137*6dbdd20aSAndroid Build Coastguard WorkerIn trace processor, any context associated with all events on a track is found
138*6dbdd20aSAndroid Build Coastguard Workeron the associated `track` tables.
139*6dbdd20aSAndroid Build Coastguard Worker
140*6dbdd20aSAndroid Build Coastguard WorkerFor example, to obtain the `utid` of any thread which emitted a `measure` slice
141*6dbdd20aSAndroid Build Coastguard Worker
142*6dbdd20aSAndroid Build Coastguard Worker```sql
143*6dbdd20aSAndroid Build Coastguard WorkerSELECT utid
144*6dbdd20aSAndroid Build Coastguard WorkerFROM slice
145*6dbdd20aSAndroid Build Coastguard WorkerJOIN thread_track ON thread_track.id = slice.track_id
146*6dbdd20aSAndroid Build Coastguard WorkerWHERE slice.name = 'measure'
147*6dbdd20aSAndroid Build Coastguard Worker```
148*6dbdd20aSAndroid Build Coastguard Worker
149*6dbdd20aSAndroid Build Coastguard WorkerSimilarly, to obtain the `upid`s of any process which has a `mem.swap` counter
150*6dbdd20aSAndroid Build Coastguard Workergreater than 1000
151*6dbdd20aSAndroid Build Coastguard Worker
152*6dbdd20aSAndroid Build Coastguard Worker```sql
153*6dbdd20aSAndroid Build Coastguard WorkerSELECT upid
154*6dbdd20aSAndroid Build Coastguard WorkerFROM counter
155*6dbdd20aSAndroid Build Coastguard WorkerJOIN process_counter_track ON process_counter_track.id = counter.track_id
156*6dbdd20aSAndroid Build Coastguard WorkerWHERE process_counter_track.name = 'mem.swap' AND value > 1000
157*6dbdd20aSAndroid Build Coastguard Worker```
158*6dbdd20aSAndroid Build Coastguard Worker
159*6dbdd20aSAndroid Build Coastguard Worker### Thread and process tables
160*6dbdd20aSAndroid Build Coastguard Worker
161*6dbdd20aSAndroid Build Coastguard WorkerWhile obtaining `utid`s and `upid`s are a step in the right direction, generally
162*6dbdd20aSAndroid Build Coastguard Workerusers want the original `tid`, `pid`, and process/thread names.
163*6dbdd20aSAndroid Build Coastguard Worker
164*6dbdd20aSAndroid Build Coastguard WorkerThe `thread` and `process` tables map `utid`s and `upid`s to threads and
165*6dbdd20aSAndroid Build Coastguard Workerprocesses respectively. For example, to lookup the thread with `utid` 10
166*6dbdd20aSAndroid Build Coastguard Worker
167*6dbdd20aSAndroid Build Coastguard Worker```sql
168*6dbdd20aSAndroid Build Coastguard WorkerSELECT tid, name
169*6dbdd20aSAndroid Build Coastguard WorkerFROM thread
170*6dbdd20aSAndroid Build Coastguard WorkerWHERE utid = 10
171*6dbdd20aSAndroid Build Coastguard Worker```
172*6dbdd20aSAndroid Build Coastguard Worker
173*6dbdd20aSAndroid Build Coastguard WorkerThe `thread` and `process` tables can also be joined with the associated track
174*6dbdd20aSAndroid Build Coastguard Workertables directly to jump directly from the slice or counter to the information
175*6dbdd20aSAndroid Build Coastguard Workerabout processes and threads.
176*6dbdd20aSAndroid Build Coastguard Worker
177*6dbdd20aSAndroid Build Coastguard WorkerFor example, to get a list of all the threads which emitted a `measure` slice
178*6dbdd20aSAndroid Build Coastguard Worker
179*6dbdd20aSAndroid Build Coastguard Worker```sql
180*6dbdd20aSAndroid Build Coastguard WorkerSELECT thread.name AS thread_name
181*6dbdd20aSAndroid Build Coastguard WorkerFROM slice
182*6dbdd20aSAndroid Build Coastguard WorkerJOIN thread_track ON slice.track_id = thread_track.id
183*6dbdd20aSAndroid Build Coastguard WorkerJOIN thread USING(utid)
184*6dbdd20aSAndroid Build Coastguard WorkerWHERE slice.name = 'measure'
185*6dbdd20aSAndroid Build Coastguard WorkerGROUP BY thread_name
186*6dbdd20aSAndroid Build Coastguard Worker```
187*6dbdd20aSAndroid Build Coastguard Worker
188*6dbdd20aSAndroid Build Coastguard Worker## Helper functions
189*6dbdd20aSAndroid Build Coastguard WorkerHelper functions are functions built into C++ which reduce the amount of
190*6dbdd20aSAndroid Build Coastguard Workerboilerplate which needs to be written in SQL.
191*6dbdd20aSAndroid Build Coastguard Worker
192*6dbdd20aSAndroid Build Coastguard Worker### Extract args
193*6dbdd20aSAndroid Build Coastguard Worker`EXTRACT_ARG` is a helper function which retreives a property of an
194*6dbdd20aSAndroid Build Coastguard Workerevent (e.g. slice or counter) from the `args` table.
195*6dbdd20aSAndroid Build Coastguard Worker
196*6dbdd20aSAndroid Build Coastguard WorkerIt takes an `arg_set_id` and `key` as input and returns the value looked
197*6dbdd20aSAndroid Build Coastguard Workerup in the `args` table.
198*6dbdd20aSAndroid Build Coastguard Worker
199*6dbdd20aSAndroid Build Coastguard WorkerFor example, to retrieve the `prev_comm` field for `sched_switch` events in
200*6dbdd20aSAndroid Build Coastguard Workerthe `ftrace_event` table.
201*6dbdd20aSAndroid Build Coastguard Worker```sql
202*6dbdd20aSAndroid Build Coastguard WorkerSELECT EXTRACT_ARG(arg_set_id, 'prev_comm')
203*6dbdd20aSAndroid Build Coastguard WorkerFROM ftrace_event
204*6dbdd20aSAndroid Build Coastguard WorkerWHERE name = 'sched_switch'
205*6dbdd20aSAndroid Build Coastguard Worker```
206*6dbdd20aSAndroid Build Coastguard Worker
207*6dbdd20aSAndroid Build Coastguard WorkerBehind the scenes, the above query would desugar to the following:
208*6dbdd20aSAndroid Build Coastguard Worker```sql
209*6dbdd20aSAndroid Build Coastguard WorkerSELECT
210*6dbdd20aSAndroid Build Coastguard Worker  (
211*6dbdd20aSAndroid Build Coastguard Worker    SELECT string_value
212*6dbdd20aSAndroid Build Coastguard Worker    FROM args
213*6dbdd20aSAndroid Build Coastguard Worker    WHERE key = 'prev_comm' AND args.arg_set_id = raw.arg_set_id
214*6dbdd20aSAndroid Build Coastguard Worker  )
215*6dbdd20aSAndroid Build Coastguard WorkerFROM ftrace_event
216*6dbdd20aSAndroid Build Coastguard WorkerWHERE name = 'sched_switch'
217*6dbdd20aSAndroid Build Coastguard Worker```
218*6dbdd20aSAndroid Build Coastguard Worker
219*6dbdd20aSAndroid Build Coastguard WorkerNOTE: while convinient, `EXTRACT_ARG` can inefficient compared to a `JOIN`
220*6dbdd20aSAndroid Build Coastguard Workerwhen working with very large tables; a function call is required for every
221*6dbdd20aSAndroid Build Coastguard Workerrow which will be slower than the batch filters/sorts used by `JOIN`.
222*6dbdd20aSAndroid Build Coastguard Worker
223*6dbdd20aSAndroid Build Coastguard Worker## Operator tables
224*6dbdd20aSAndroid Build Coastguard WorkerSQL queries are usually sufficient to retrieve data from trace processor.
225*6dbdd20aSAndroid Build Coastguard WorkerSometimes though, certain constructs can be difficult to express pure SQL.
226*6dbdd20aSAndroid Build Coastguard Worker
227*6dbdd20aSAndroid Build Coastguard WorkerIn these situations, trace processor has special "operator tables" which solve
228*6dbdd20aSAndroid Build Coastguard Workera particular problem in C++ but expose an SQL interface for queries to take
229*6dbdd20aSAndroid Build Coastguard Workeradvantage of.
230*6dbdd20aSAndroid Build Coastguard Worker
231*6dbdd20aSAndroid Build Coastguard Worker### Span join
232*6dbdd20aSAndroid Build Coastguard WorkerSpan join is a custom operator table which computes the intersection of
233*6dbdd20aSAndroid Build Coastguard Workerspans of time from two tables or views. A span in this concept is a row in a
234*6dbdd20aSAndroid Build Coastguard Workertable/view which contains a "ts" (timestamp) and "dur" (duration) columns.
235*6dbdd20aSAndroid Build Coastguard Worker
236*6dbdd20aSAndroid Build Coastguard WorkerA column (called the *partition*) can optionally be specified which divides the
237*6dbdd20aSAndroid Build Coastguard Workerrows from each table into partitions before computing the intersection.
238*6dbdd20aSAndroid Build Coastguard Worker
239*6dbdd20aSAndroid Build Coastguard Worker![Span join block diagram](/docs/images/span-join.png)
240*6dbdd20aSAndroid Build Coastguard Worker
241*6dbdd20aSAndroid Build Coastguard Worker```sql
242*6dbdd20aSAndroid Build Coastguard Worker-- Get all the scheduling slices
243*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIEW sp_sched AS
244*6dbdd20aSAndroid Build Coastguard WorkerSELECT ts, dur, cpu, utid
245*6dbdd20aSAndroid Build Coastguard WorkerFROM sched;
246*6dbdd20aSAndroid Build Coastguard Worker
247*6dbdd20aSAndroid Build Coastguard Worker-- Get all the cpu frequency slices
248*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIEW sp_frequency AS
249*6dbdd20aSAndroid Build Coastguard WorkerSELECT
250*6dbdd20aSAndroid Build Coastguard Worker  ts,
251*6dbdd20aSAndroid Build Coastguard Worker  lead(ts) OVER (PARTITION BY track_id ORDER BY ts) - ts as dur,
252*6dbdd20aSAndroid Build Coastguard Worker  cpu,
253*6dbdd20aSAndroid Build Coastguard Worker  value as freq
254*6dbdd20aSAndroid Build Coastguard WorkerFROM counter
255*6dbdd20aSAndroid Build Coastguard WorkerJOIN cpu_counter_track ON counter.track_id = cpu_counter_track.id
256*6dbdd20aSAndroid Build Coastguard WorkerWHERE cpu_counter_track.name = 'cpufreq';
257*6dbdd20aSAndroid Build Coastguard Worker
258*6dbdd20aSAndroid Build Coastguard Worker-- Create the span joined table which combines cpu frequency with
259*6dbdd20aSAndroid Build Coastguard Worker-- scheduling slices.
260*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIRTUAL TABLE sched_with_frequency
261*6dbdd20aSAndroid Build Coastguard WorkerUSING SPAN_JOIN(sp_sched PARTITIONED cpu, sp_frequency PARTITIONED cpu);
262*6dbdd20aSAndroid Build Coastguard Worker
263*6dbdd20aSAndroid Build Coastguard Worker-- This span joined table can be queried as normal and has the columns from both
264*6dbdd20aSAndroid Build Coastguard Worker-- tables.
265*6dbdd20aSAndroid Build Coastguard WorkerSELECT ts, dur, cpu, utid, freq
266*6dbdd20aSAndroid Build Coastguard WorkerFROM sched_with_frequency;
267*6dbdd20aSAndroid Build Coastguard Worker```
268*6dbdd20aSAndroid Build Coastguard Worker
269*6dbdd20aSAndroid Build Coastguard WorkerNOTE: A partition can be specified on neither, either or both tables. If
270*6dbdd20aSAndroid Build Coastguard Workerspecified on both, the same column name has to be specified on each table.
271*6dbdd20aSAndroid Build Coastguard Worker
272*6dbdd20aSAndroid Build Coastguard WorkerWARNING: An important restriction on span joined tables is that spans from
273*6dbdd20aSAndroid Build Coastguard Workerthe same table in the same partition *cannot* overlap. For performance
274*6dbdd20aSAndroid Build Coastguard Workerreasons, span join does not attempt to detect and error out in this situation;
275*6dbdd20aSAndroid Build Coastguard Workerinstead, incorrect rows will silently be produced.
276*6dbdd20aSAndroid Build Coastguard Worker
277*6dbdd20aSAndroid Build Coastguard WorkerWARNING: Partitions mush be integers. Importantly, string partitions are *not*
278*6dbdd20aSAndroid Build Coastguard Workersupported; note that strings *can* be converted to integers by
279*6dbdd20aSAndroid Build Coastguard Workerapplying the `HASH` function to the string column.
280*6dbdd20aSAndroid Build Coastguard Worker
281*6dbdd20aSAndroid Build Coastguard WorkerLeft and outer span joins are also supported; both function analogously to
282*6dbdd20aSAndroid Build Coastguard Workerthe left and outer joins from SQL.
283*6dbdd20aSAndroid Build Coastguard Worker```sql
284*6dbdd20aSAndroid Build Coastguard Worker-- Left table partitioned + right table unpartitioned.
285*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIRTUAL TABLE left_join
286*6dbdd20aSAndroid Build Coastguard WorkerUSING SPAN_LEFT_JOIN(table_a PARTITIONED a, table_b);
287*6dbdd20aSAndroid Build Coastguard Worker
288*6dbdd20aSAndroid Build Coastguard Worker-- Both tables unpartitioned.
289*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIRTUAL TABLE outer_join
290*6dbdd20aSAndroid Build Coastguard WorkerUSING SPAN_OUTER_JOIN(table_x, table_y);
291*6dbdd20aSAndroid Build Coastguard Worker```
292*6dbdd20aSAndroid Build Coastguard Worker
293*6dbdd20aSAndroid Build Coastguard WorkerNOTE: there is a subtlety if the partitioned table is empty and is
294*6dbdd20aSAndroid Build Coastguard Workereither a) part of an outer join b) on the right side of a left join.
295*6dbdd20aSAndroid Build Coastguard WorkerIn this case, *no* slices will be emitted even if the other table is
296*6dbdd20aSAndroid Build Coastguard Workernon-empty. This approach was decided as being the most natural
297*6dbdd20aSAndroid Build Coastguard Workerafter considering how span joins are used in practice.
298*6dbdd20aSAndroid Build Coastguard Worker
299*6dbdd20aSAndroid Build Coastguard Worker### Ancestor slice
300*6dbdd20aSAndroid Build Coastguard Workerancestor_slice is a custom operator table that takes a
301*6dbdd20aSAndroid Build Coastguard Worker[slice table's id column](/docs/analysis/sql-tables.autogen#slice) and computes
302*6dbdd20aSAndroid Build Coastguard Workerall slices on the same track that are direct parents above that id (i.e. given
303*6dbdd20aSAndroid Build Coastguard Workera slice id it will return as rows all slices that can be found by following
304*6dbdd20aSAndroid Build Coastguard Workerthe parent_id column to the top slice (depth = 0)).
305*6dbdd20aSAndroid Build Coastguard Worker
306*6dbdd20aSAndroid Build Coastguard WorkerThe returned format is the same as the
307*6dbdd20aSAndroid Build Coastguard Worker[slice table](/docs/analysis/sql-tables.autogen#slice)
308*6dbdd20aSAndroid Build Coastguard Worker
309*6dbdd20aSAndroid Build Coastguard WorkerFor example, the following finds the top level slice given a bunch of slices of
310*6dbdd20aSAndroid Build Coastguard Workerinterest.
311*6dbdd20aSAndroid Build Coastguard Worker
312*6dbdd20aSAndroid Build Coastguard Worker```sql
313*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIEW interesting_slices AS
314*6dbdd20aSAndroid Build Coastguard WorkerSELECT id, ts, dur, track_id
315*6dbdd20aSAndroid Build Coastguard WorkerFROM slice WHERE name LIKE "%interesting slice name%";
316*6dbdd20aSAndroid Build Coastguard Worker
317*6dbdd20aSAndroid Build Coastguard WorkerSELECT
318*6dbdd20aSAndroid Build Coastguard Worker  *
319*6dbdd20aSAndroid Build Coastguard WorkerFROM
320*6dbdd20aSAndroid Build Coastguard Worker  interesting_slices LEFT JOIN
321*6dbdd20aSAndroid Build Coastguard Worker  ancestor_slice(interesting_slices.id) AS ancestor ON ancestor.depth = 0
322*6dbdd20aSAndroid Build Coastguard Worker```
323*6dbdd20aSAndroid Build Coastguard Worker
324*6dbdd20aSAndroid Build Coastguard Worker### Ancestor slice by stack
325*6dbdd20aSAndroid Build Coastguard Workerancestor_slice_by_stack is a custom operator table that takes a
326*6dbdd20aSAndroid Build Coastguard Worker[slice table's stack_id column](/docs/analysis/sql-tables.autogen#slice) and
327*6dbdd20aSAndroid Build Coastguard Workerfinds all slice ids with that stack_id, then, for each id it computes
328*6dbdd20aSAndroid Build Coastguard Workerall the ancestor slices similarly to
329*6dbdd20aSAndroid Build Coastguard Worker[ancestor_slice](/docs/analysis/trace-processor#ancestor-slice).
330*6dbdd20aSAndroid Build Coastguard Worker
331*6dbdd20aSAndroid Build Coastguard WorkerThe returned format is the same as the
332*6dbdd20aSAndroid Build Coastguard Worker[slice table](/docs/analysis/sql-tables.autogen#slice)
333*6dbdd20aSAndroid Build Coastguard Worker
334*6dbdd20aSAndroid Build Coastguard WorkerFor example, the following finds the top level slice of all slices with the
335*6dbdd20aSAndroid Build Coastguard Workergiven name.
336*6dbdd20aSAndroid Build Coastguard Worker
337*6dbdd20aSAndroid Build Coastguard Worker```sql
338*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIEW interesting_stack_ids AS
339*6dbdd20aSAndroid Build Coastguard WorkerSELECT stack_id
340*6dbdd20aSAndroid Build Coastguard WorkerFROM slice WHERE name LIKE "%interesting slice name%";
341*6dbdd20aSAndroid Build Coastguard Worker
342*6dbdd20aSAndroid Build Coastguard WorkerSELECT
343*6dbdd20aSAndroid Build Coastguard Worker  *
344*6dbdd20aSAndroid Build Coastguard WorkerFROM
345*6dbdd20aSAndroid Build Coastguard Worker  interesting_stack_ids LEFT JOIN
346*6dbdd20aSAndroid Build Coastguard Worker  ancestor_slice_by_stack(interesting_stack_ids.stack_id) AS ancestor
347*6dbdd20aSAndroid Build Coastguard Worker  ON ancestor.depth = 0
348*6dbdd20aSAndroid Build Coastguard Worker```
349*6dbdd20aSAndroid Build Coastguard Worker
350*6dbdd20aSAndroid Build Coastguard Worker### Descendant slice
351*6dbdd20aSAndroid Build Coastguard Workerdescendant_slice is a custom operator table that takes a
352*6dbdd20aSAndroid Build Coastguard Worker[slice table's id column](/docs/analysis/sql-tables.autogen#slice) and
353*6dbdd20aSAndroid Build Coastguard Workercomputes all slices on the same track that are nested under that id (i.e.
354*6dbdd20aSAndroid Build Coastguard Workerall slices that are on the same track at the same time frame with a depth
355*6dbdd20aSAndroid Build Coastguard Workergreater than the given slice's depth.
356*6dbdd20aSAndroid Build Coastguard Worker
357*6dbdd20aSAndroid Build Coastguard WorkerThe returned format is the same as the
358*6dbdd20aSAndroid Build Coastguard Worker[slice table](/docs/analysis/sql-tables.autogen#slice)
359*6dbdd20aSAndroid Build Coastguard Worker
360*6dbdd20aSAndroid Build Coastguard WorkerFor example, the following finds the number of slices under each slice of
361*6dbdd20aSAndroid Build Coastguard Workerinterest.
362*6dbdd20aSAndroid Build Coastguard Worker
363*6dbdd20aSAndroid Build Coastguard Worker```sql
364*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIEW interesting_slices AS
365*6dbdd20aSAndroid Build Coastguard WorkerSELECT id, ts, dur, track_id
366*6dbdd20aSAndroid Build Coastguard WorkerFROM slice WHERE name LIKE "%interesting slice name%";
367*6dbdd20aSAndroid Build Coastguard Worker
368*6dbdd20aSAndroid Build Coastguard WorkerSELECT
369*6dbdd20aSAndroid Build Coastguard Worker  *
370*6dbdd20aSAndroid Build Coastguard Worker  (
371*6dbdd20aSAndroid Build Coastguard Worker    SELECT
372*6dbdd20aSAndroid Build Coastguard Worker      COUNT(*) AS total_descendants
373*6dbdd20aSAndroid Build Coastguard Worker    FROM descendant_slice(interesting_slice.id)
374*6dbdd20aSAndroid Build Coastguard Worker  )
375*6dbdd20aSAndroid Build Coastguard WorkerFROM interesting_slices
376*6dbdd20aSAndroid Build Coastguard Worker```
377*6dbdd20aSAndroid Build Coastguard Worker
378*6dbdd20aSAndroid Build Coastguard Worker### Descendant slice by stack
379*6dbdd20aSAndroid Build Coastguard Workerdescendant_slice_by_stack is a custom operator table that takes a
380*6dbdd20aSAndroid Build Coastguard Worker[slice table's stack_id column](/docs/analysis/sql-tables.autogen#slice) and
381*6dbdd20aSAndroid Build Coastguard Workerfinds all slice ids with that stack_id, then, for each id it computes
382*6dbdd20aSAndroid Build Coastguard Workerall the descendant slices similarly to
383*6dbdd20aSAndroid Build Coastguard Worker[descendant_slice](/docs/analysis/trace-processor#descendant-slice).
384*6dbdd20aSAndroid Build Coastguard Worker
385*6dbdd20aSAndroid Build Coastguard WorkerThe returned format is the same as the
386*6dbdd20aSAndroid Build Coastguard Worker[slice table](/docs/analysis/sql-tables.autogen#slice)
387*6dbdd20aSAndroid Build Coastguard Worker
388*6dbdd20aSAndroid Build Coastguard WorkerFor example, the following finds the next level descendant of all slices with
389*6dbdd20aSAndroid Build Coastguard Workerthe given name.
390*6dbdd20aSAndroid Build Coastguard Worker
391*6dbdd20aSAndroid Build Coastguard Worker```sql
392*6dbdd20aSAndroid Build Coastguard WorkerCREATE VIEW interesting_stacks AS
393*6dbdd20aSAndroid Build Coastguard WorkerSELECT stack_id, depth
394*6dbdd20aSAndroid Build Coastguard WorkerFROM slice WHERE name LIKE "%interesting slice name%";
395*6dbdd20aSAndroid Build Coastguard Worker
396*6dbdd20aSAndroid Build Coastguard WorkerSELECT
397*6dbdd20aSAndroid Build Coastguard Worker  *
398*6dbdd20aSAndroid Build Coastguard WorkerFROM
399*6dbdd20aSAndroid Build Coastguard Worker  interesting_stacks LEFT JOIN
400*6dbdd20aSAndroid Build Coastguard Worker  descendant_slice_by_stack(interesting_stacks.stack_id) AS descendant
401*6dbdd20aSAndroid Build Coastguard Worker  ON descendant.depth = interesting_stacks.depth + 1
402*6dbdd20aSAndroid Build Coastguard Worker```
403*6dbdd20aSAndroid Build Coastguard Worker
404*6dbdd20aSAndroid Build Coastguard Worker### Connected/Following/Preceding flows
405*6dbdd20aSAndroid Build Coastguard Worker
406*6dbdd20aSAndroid Build Coastguard WorkerDIRECTLY_CONNECTED_FLOW, FOLLOWING_FLOW and PRECEDING_FLOW are custom operator
407*6dbdd20aSAndroid Build Coastguard Workertables that take a
408*6dbdd20aSAndroid Build Coastguard Worker[slice table's id column](/docs/analysis/sql-tables.autogen#slice) and collect
409*6dbdd20aSAndroid Build Coastguard Workerall entries of [flow table](/docs/analysis/sql-tables.autogen#flow), that are
410*6dbdd20aSAndroid Build Coastguard Workerdirectly or indirectly connected to the given starting slice.
411*6dbdd20aSAndroid Build Coastguard Worker
412*6dbdd20aSAndroid Build Coastguard Worker`DIRECTLY_CONNECTED_FLOW(start_slice_id)` - contains all entries of
413*6dbdd20aSAndroid Build Coastguard Worker[flow table](/docs/analysis/sql-tables.autogen#flow) that are present in any
414*6dbdd20aSAndroid Build Coastguard Workerchain of kind: `flow[0] -> flow[1] -> ... -> flow[n]`, where
415*6dbdd20aSAndroid Build Coastguard Worker`flow[i].slice_out = flow[i+1].slice_in` and `flow[0].slice_out = start_slice_id
416*6dbdd20aSAndroid Build Coastguard WorkerOR start_slice_id = flow[n].slice_in`.
417*6dbdd20aSAndroid Build Coastguard Worker
418*6dbdd20aSAndroid Build Coastguard WorkerNOTE: Unlike the following/preceding flow functions, this function will not
419*6dbdd20aSAndroid Build Coastguard Workerinclude flows connected to ancestors or descendants while searching for flows
420*6dbdd20aSAndroid Build Coastguard Workerfrom a slice. It only includes the slices in the directly connected chain.
421*6dbdd20aSAndroid Build Coastguard Worker
422*6dbdd20aSAndroid Build Coastguard Worker`FOLLOWING_FLOW(start_slice_id)` - contains all flows which can be reached from
423*6dbdd20aSAndroid Build Coastguard Workera given slice via recursively following from flow's outgoing slice to its
424*6dbdd20aSAndroid Build Coastguard Workerincoming one and from a reached slice to its child. The return table contains
425*6dbdd20aSAndroid Build Coastguard Workerall entries of [flow table](/docs/analysis/sql-tables.autogen#flow) that are
426*6dbdd20aSAndroid Build Coastguard Workerpresent in any chain of kind: `flow[0] -> flow[1] -> ... -> flow[n]`, where
427*6dbdd20aSAndroid Build Coastguard Worker`flow[i+1].slice_out IN DESCENDANT_SLICE(flow[i].slice_in) OR
428*6dbdd20aSAndroid Build Coastguard Workerflow[i+1].slice_out = flow[i].slice_in` and `flow[0].slice_out IN
429*6dbdd20aSAndroid Build Coastguard WorkerDESCENDANT_SLICE(start_slice_id) OR flow[0].slice_out = start_slice_id`.
430*6dbdd20aSAndroid Build Coastguard Worker
431*6dbdd20aSAndroid Build Coastguard Worker`PRECEDING_FLOW(start_slice_id)` - contains all flows which can be reached from
432*6dbdd20aSAndroid Build Coastguard Workera given slice via recursively following from flow's incoming slice to its
433*6dbdd20aSAndroid Build Coastguard Workeroutgoing one and from a reached slice to its parent. The return table contains
434*6dbdd20aSAndroid Build Coastguard Workerall entries of [flow table](/docs/analysis/sql-tables.autogen#flow) that are
435*6dbdd20aSAndroid Build Coastguard Workerpresent in any chain of kind: `flow[n] -> flow[n-1] -> ... -> flow[0]`, where
436*6dbdd20aSAndroid Build Coastguard Worker`flow[i].slice_in IN ANCESTOR_SLICE(flow[i+1].slice_out) OR flow[i].slice_in =
437*6dbdd20aSAndroid Build Coastguard Workerflow[i+1].slice_out` and `flow[0].slice_in IN ANCESTOR_SLICE(start_slice_id) OR
438*6dbdd20aSAndroid Build Coastguard Workerflow[0].slice_in = start_slice_id`.
439*6dbdd20aSAndroid Build Coastguard Worker
440*6dbdd20aSAndroid Build Coastguard Worker```sql
441*6dbdd20aSAndroid Build Coastguard Worker--number of following flows for each slice
442*6dbdd20aSAndroid Build Coastguard WorkerSELECT (SELECT COUNT(*) FROM FOLLOWING_FLOW(slice_id)) as following FROM slice;
443*6dbdd20aSAndroid Build Coastguard Worker```
444*6dbdd20aSAndroid Build Coastguard Worker
445*6dbdd20aSAndroid Build Coastguard Worker## Metrics
446*6dbdd20aSAndroid Build Coastguard Worker
447*6dbdd20aSAndroid Build Coastguard WorkerTIP: To see how to add to add a new metric to trace processor, see the checklist
448*6dbdd20aSAndroid Build Coastguard Worker[here](/docs/contributing/common-tasks.md#new-metric).
449*6dbdd20aSAndroid Build Coastguard Worker
450*6dbdd20aSAndroid Build Coastguard WorkerThe metrics subsystem is a significant part of trace processor and thus is
451*6dbdd20aSAndroid Build Coastguard Workerdocumented on its own [page](/docs/analysis/metrics.md).
452*6dbdd20aSAndroid Build Coastguard Worker
453*6dbdd20aSAndroid Build Coastguard Worker## Python API
454*6dbdd20aSAndroid Build Coastguard WorkerThe trace processor's C++ library is also exposed through Python. This
455*6dbdd20aSAndroid Build Coastguard Workeris documented on a [separate page](/docs/analysis/trace-processor-python.md).
456*6dbdd20aSAndroid Build Coastguard Worker
457*6dbdd20aSAndroid Build Coastguard Worker## Testing
458*6dbdd20aSAndroid Build Coastguard Worker
459*6dbdd20aSAndroid Build Coastguard WorkerTrace processor is mainly tested in two ways:
460*6dbdd20aSAndroid Build Coastguard Worker1. Unit tests of low-level building blocks
461*6dbdd20aSAndroid Build Coastguard Worker2. "Diff" tests which parse traces and check the output of queries
462*6dbdd20aSAndroid Build Coastguard Worker
463*6dbdd20aSAndroid Build Coastguard Worker### Unit tests
464*6dbdd20aSAndroid Build Coastguard WorkerUnit testing trace processor is the same as in other parts of Perfetto and
465*6dbdd20aSAndroid Build Coastguard Workerother C++ projects. However, unlike the rest of Perfetto, unit testing is
466*6dbdd20aSAndroid Build Coastguard Workerrelatively light in trace processor.
467*6dbdd20aSAndroid Build Coastguard Worker
468*6dbdd20aSAndroid Build Coastguard WorkerWe have discovered over time that unit tests are generally too brittle
469*6dbdd20aSAndroid Build Coastguard Workerwhen dealing with code which parses traces leading to painful, mechanical
470*6dbdd20aSAndroid Build Coastguard Workerchanges being needed when refactorings happen.
471*6dbdd20aSAndroid Build Coastguard Worker
472*6dbdd20aSAndroid Build Coastguard WorkerBecause of this, we choose to focus on diff tests for most areas (e.g.
473*6dbdd20aSAndroid Build Coastguard Workerparsing events, testing schema of tables, testing metrics etc.) and only
474*6dbdd20aSAndroid Build Coastguard Workeruse unit testing for the low-level building blocks on which the rest of
475*6dbdd20aSAndroid Build Coastguard Workertrace processor is built.
476*6dbdd20aSAndroid Build Coastguard Worker
477*6dbdd20aSAndroid Build Coastguard Worker### Diff tests
478*6dbdd20aSAndroid Build Coastguard WorkerDiff tests are essentially integration tests for trace processor and the
479*6dbdd20aSAndroid Build Coastguard Workermain way trace processor is tested.
480*6dbdd20aSAndroid Build Coastguard Worker
481*6dbdd20aSAndroid Build Coastguard WorkerEach diff test takes as input a) a trace file b) a query file *or* a metric
482*6dbdd20aSAndroid Build Coastguard Workername. It runs `trace_processor_shell` to parse the trace and then executes
483*6dbdd20aSAndroid Build Coastguard Workerthe query/metric. The result is then compared to a 'golden' file and any
484*6dbdd20aSAndroid Build Coastguard Workerdifference is highlighted.
485*6dbdd20aSAndroid Build Coastguard Worker
486*6dbdd20aSAndroid Build Coastguard WorkerAll diff tests are organized under [test/trace_processor](/test/trace_processor)
487*6dbdd20aSAndroid Build Coastguard Workerin `tests{_category name}.py` files as methods of a class in each file
488*6dbdd20aSAndroid Build Coastguard Workerand are run by the script
489*6dbdd20aSAndroid Build Coastguard Worker[`tools/diff_test_trace_processor.py`](/tools/diff_test_trace_processor.py).
490*6dbdd20aSAndroid Build Coastguard WorkerTo add a new test its enough to add a new method starting with `test_` in suitable
491*6dbdd20aSAndroid Build Coastguard Workerpython tests file.
492*6dbdd20aSAndroid Build Coastguard Worker
493*6dbdd20aSAndroid Build Coastguard WorkerMethods can't take arguments and have to return `DiffTestBlueprint`:
494*6dbdd20aSAndroid Build Coastguard Worker```python
495*6dbdd20aSAndroid Build Coastguard Workerclass DiffTestBlueprint:
496*6dbdd20aSAndroid Build Coastguard Worker  trace: Union[Path, Json, Systrace, TextProto]
497*6dbdd20aSAndroid Build Coastguard Worker  query: Union[str, Path, Metric]
498*6dbdd20aSAndroid Build Coastguard Worker  out: Union[Path, Json, Csv, TextProto]
499*6dbdd20aSAndroid Build Coastguard Worker```
500*6dbdd20aSAndroid Build Coastguard Worker*Trace* and *Out*: For every type apart from `Path`, contents of the object will be treated as
501*6dbdd20aSAndroid Build Coastguard Workerfile contents so it has to follow the same rules.
502*6dbdd20aSAndroid Build Coastguard Worker
503*6dbdd20aSAndroid Build Coastguard Worker*Query*: For metric tests it is enough to provide the metric name. For query tests there
504*6dbdd20aSAndroid Build Coastguard Workercan be a raw SQL statement, for example `"SELECT * FROM SLICE"` or path to an `.sql` file.
505*6dbdd20aSAndroid Build Coastguard Worker
506*6dbdd20aSAndroid Build Coastguard Worker
507*6dbdd20aSAndroid Build Coastguard Worker
508*6dbdd20aSAndroid Build Coastguard WorkerNOTE: `trace_processor_shell` and associated proto descriptors needs to be
509*6dbdd20aSAndroid Build Coastguard Workerbuilt before running `tools/diff_test_trace_processor.py`. The easiest way
510*6dbdd20aSAndroid Build Coastguard Workerto do this is to run `tools/ninja -C <out directory>` both initially and on
511*6dbdd20aSAndroid Build Coastguard Workerevery change to trace processor code or builtin metrics.
512*6dbdd20aSAndroid Build Coastguard Worker
513*6dbdd20aSAndroid Build Coastguard Worker#### Choosing where to add diff tests
514*6dbdd20aSAndroid Build Coastguard Worker`diff_tests/` folder contains four directories corresponding to different
515*6dbdd20aSAndroid Build Coastguard Workerareas of trace processor.
516*6dbdd20aSAndroid Build Coastguard Worker1. __stdlib__: Tests focusing on testing Perfetto Standard Library, both
517*6dbdd20aSAndroid Build Coastguard Worker   prelude and the regular modules. The subdirectories in this folder
518*6dbdd20aSAndroid Build Coastguard Worker   should generally correspond to directories in `perfetto_sql/stdlib`.
519*6dbdd20aSAndroid Build Coastguard Worker2. __parser__: Tests focusing on ensuring that different trace files are
520*6dbdd20aSAndroid Build Coastguard Worker   parsed correctly and the corresponding built-in tables are populated.
521*6dbdd20aSAndroid Build Coastguard Worker3. __metrics__: Tests focusing on testing metrics located in
522*6dbdd20aSAndroid Build Coastguard Worker   `trace_processor/metrics/sql`. This organisation is mostly historical
523*6dbdd20aSAndroid Build Coastguard Worker   and code (and corresponding tests) is expected to move to `stdlib` over time.
524*6dbdd20aSAndroid Build Coastguard Worker4. __syntax__: Tests focusing on testing the core syntax of PerfettoSQL
525*6dbdd20aSAndroid Build Coastguard Worker   (i.e. `CREATE PERFETTO TABLE` or `CREATE PERFETTO FUNCTION`).
526*6dbdd20aSAndroid Build Coastguard Worker
527*6dbdd20aSAndroid Build Coastguard Worker__Scenario__: A new stdlib module `foo/bar.sql` is being added.
528*6dbdd20aSAndroid Build Coastguard Worker
529*6dbdd20aSAndroid Build Coastguard Worker_Answer_: Add the test to the `stdlib/foo/bar_tests.py` file.
530*6dbdd20aSAndroid Build Coastguard Worker
531*6dbdd20aSAndroid Build Coastguard Worker__Scenario__: A new event is being parsed, the focus of the test is to ensure
532*6dbdd20aSAndroid Build Coastguard Workerthe event is being parsed correctly.
533*6dbdd20aSAndroid Build Coastguard Worker
534*6dbdd20aSAndroid Build Coastguard Worker_Answer_: Add the test in one of the `parser` subdirectories. Prefer adding a
535*6dbdd20aSAndroid Build Coastguard Workertest to an existing related directory (i.e. `sched`, `power`) if one exists.
536*6dbdd20aSAndroid Build Coastguard Worker
537*6dbdd20aSAndroid Build Coastguard Worker__Scenario__: A new metric is being added and the focus of the test is to
538*6dbdd20aSAndroid Build Coastguard Workerensure the metric is being correctly computed.
539*6dbdd20aSAndroid Build Coastguard Worker
540*6dbdd20aSAndroid Build Coastguard Worker_Answer_: Add the test in one of the `metrics` subdirectories. Prefer adding a
541*6dbdd20aSAndroid Build Coastguard Workertest to an existing related directory if one exists. Also consider adding the
542*6dbdd20aSAndroid Build Coastguard Workercode in question to stdlib.
543*6dbdd20aSAndroid Build Coastguard Worker
544*6dbdd20aSAndroid Build Coastguard Worker__Scenario__: A new dynamic table is being added and the focus of the test is to
545*6dbdd20aSAndroid Build Coastguard Workerensure the dynamic table is being correctly computed...
546*6dbdd20aSAndroid Build Coastguard Worker
547*6dbdd20aSAndroid Build Coastguard Worker_Answer_: Add the test to the `stdlib/dynamic_tables` folder
548*6dbdd20aSAndroid Build Coastguard Worker
549*6dbdd20aSAndroid Build Coastguard Worker__Scenario__: The interals of trace processor are being modified and the test
550*6dbdd20aSAndroid Build Coastguard Workeris to ensure the trace processor is correctly filtering/sorting important
551*6dbdd20aSAndroid Build Coastguard Workerbuilt-in tables.
552*6dbdd20aSAndroid Build Coastguard Worker
553*6dbdd20aSAndroid Build Coastguard Worker_Answer_: Add the test to the `parser/core_tables` folder.
554