1## Tracing Driver
2
3An experimental tracing backend that supports extremely low overhead tracing for JVM and Android
4apps; with the goal of supporting more platforms supported by the Kotlin Multiplatform ecosystem.
5
6The traces are captured using standard trace format defined by
7[Perfetto](https://perfetto.dev/docs/reference/trace-packet-proto). All tools that consume
8perfetto traces can continue being used. [ui.perfetto.dev](https://ui.perfetto.dev) can be used
9to visualize traces. Tools like
10[TraceProcessor](https://perfetto.dev/docs/analysis/trace-processor-python) can be used for
11analysing traces.
12
13## Usage
14
15To start recording traces, you need to create an instance of a
16[`TraceDriver`](src/commonMain/kotlin/androidx/tracing/driver/TraceDriver.kt).
17
18```kotlin
19val driver = TraceDriver(
20    // The trace sink. Determines where traces are stored.
21    // The library provides an implementation to a tracing sink out of the box.
22    // You can also write your own implementation of a TraceSink.
23    sink = JvmTraceSink(sequenceId = 1, baseDir = File("/path/to/trace/directory")),
24    // If injecting an instance of Driver, setting this to `false` means that no traces will be
25    // emitted to the sink. You don't have to change all the call sites where traces are captured.
26    isEnabled = true
27)
28```
29
30The `TraceDriver` provides a `context` which is of type
31[`TraceContext`](src/commonMain/kotlin/androidx/tracing/driver/TraceContext.kt).
32
33### Trace Context
34
35The `TraceContext` provides a way to create process and thread tracks. For more context on what
36tracks are, please refer
37to [the documentation](https://perfetto.dev/docs/instrumentation/track-events#tracks).
38
39### Process Tracks
40
41To create a [ProcessTrack](src/commonMain/kotlin/androidx/tracing/driver/ProcessTrack.kt) you can
42use the following API:
43
44```kotlin
45// driver.ProcessTrack(...) is an alias for driver.context.ProcessTrack(...)
46val process = driver.context.getOrCreateProcessTrack(
47    // The process id
48    id = 1,
49    // The name of the process
50    name = "processName"
51)
52```
53
54### Thread Tracks
55
56To create a [ThreadTrack](src/commonMain/kotlin/androidx/tracing/driver/ThreadTrack.kt), you can
57use a `ProcessTrack` instance :
58
59```kotlin
60val threadTrack = process.getOrCreateThreadTrack(
61    // The thread id
62    id = 10,
63    // The name of the thread
64    name = "threadName"
65)
66```
67
68### Tracing
69
70Once you have a track that you want to attach traces to, you can do:
71
72#### Basic
73
74```kotlin
75track.trace("traceSectionName") {
76    // The code that is being instrumented
77    doSomethingExpensive()
78}
79```
80
81#### Context Propagation
82
83The library also provides an implementation for tracing APIs that make use of Kotlin Coroutines
84to propagate the tracing context across multiple coroutines.
85
86```kotlin
87track.traceFlow("traceSectionName") {
88    // suspend block
89    // propagates flowId to inner coroutines automatically to do context propagation.
90}
91```
92
93For e.g.
94
95```kotlin
96suspend fun ProcessTrack.forkJoin(input: List<Int>) {
97    coroutineScope {
98        val batches = input.chunked(CHUNK_SIZE)
99        val jobs = mutableListOf<Deferred<List<Int>>()
100        batches.forEachIndexed { index, batch ->
101            jobs += async {
102                traceFlow("batch-$index") { fork(batch) }
103            }
104        }
105        val results = jobs.awaitAll()
106        return traceFlow("merge") {
107            merge(results)
108        }
109    }
110}
111```
112
113![Flows](images/flows.jpg "Context propagation with flows.")
114
115#### Counters
116
117You can also create tracks that emit counters as metrics. To create a counter you can use:
118
119```kotlin
120// The name of the counter.
121val counter = process.getOrCreateCounterTrack("MemoryUsage")
122```
123
124To emit metrics you can:
125
126```kotlin
127counter.setCounter(longValue)
128// Or
129counter.setCounter(doubleValue)
130```
131
132![Counters](images/counters.jpg "Count based metrics")
133
134For an end to end tracing example app, look at
135[`TracingDemoTest.kt`](src/jvmTest/kotlin/androidx/tracing/driver/TracingDemoTest.kt).
136
137### Flushing Traces
138
139Traces are flushed to the sink asynchronously. To force a flush, you can always call `context.flush()`.
140
141Prior to termination of the program, call `traceContext.close()` to finalize all traces to the sink.
142(A [TraceContext](src/commonMain/kotlin/androidx/tracing/driver/TraceContext.kt) is a `Closeable`).
143