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 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 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 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 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 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