blob: 8bb0430bdd5cffafb0810c67ed1f5b06a017b14e [file] [log] [blame] [view]
# Tracing: C and C++ macros
You can use these C and C++ macros to record tracing data after
you have set your component as a tracing provider. For more information,
see [Add tracing in your code](/docs/development/tracing/tutorial/add-tracing-in-code.md).
These macros are defined in
[`//zircon/system/ulib/trace/include/lib/trace/internal/event_common.h`](/zircon/system/ulib/trace/include/lib/trace/internal/event_common.h).
Important: This reference document is created manually and may be incomplete.
## Encoding macros {#encoding-macros}
When you want to record a `value` with tracing macros, it is important
that you properly encode each value. Use the respective macro based on
the data type that you want to record.
Note: C++ can infer most data types, but in the cases marked as required for C++,
you must use an encoding macro.
<table>
<tr>
<th>Macro</th>
<th>Description</th>
</tr>
<tr>
<td><code>TA_NULL</code></td>
<td><p><b>Optional for C++</b></p>
<p>A <code>NULL</code> value.</p>
<p>This macro does not take any arguments. You can use it as
<code>TA_NULL()</code>.</p>
<p>In C++, you can alternatively use <code>nullptr</code>.</p>
</td>
<tr>
<tr>
<td><code>TA_BOOL</code></td>
<td><p><b>Optional for C++</b></p>
<p>A boolean value.</p>
</td>
<tr>
<tr>
<td><code>TA_INT32</code></td>
<td><p><b>Optional for C++</b></p>
<p>A signed 32-bit integer value.</p>
</td>
<tr>
<tr>
<td><code>TA_UINT32</code></td>
<td><p><b>Optional for C++</b></p>
<p>An unsigned 32-bit integer value.</p>
</td>
<tr>
<tr>
<td><code>TA_INT64</code></td>
<td><p><b>Optional for C++</b></p>
<p>A signed 64-bit integer value.</p>
</td>
<tr>
<tr>
<td><code>TA_UINT64</code></td>
<td><p><b>Optional for C++</b></p>
<p>An unsigned 32-bit integer value.</p>
</td>
<tr>
<tr>
<td><code>TA_DOUBLE</code></td>
<td><p><b>Optional for C++</b></p>
<p>A double precision floating point value.</p>
</td>
<tr>
<tr>
<td><code>TA_CHAR_ARRAY</code></td>
<td><p><b>Required for C++</b></p>
<p>A character array with a length, which is copied rather than cached.</p>
<p>This macro takes two arguments. The first argument is a pointer to
the character array. The second argument is the length of the array.</p>
</td>
<tr>
<tr>
<td><code>TA_STRING</code></td>
<td><p><b>Optional for C++</b></p>
<p>A NULL terminated dynamic string, which is copied rather than cached.</p>
</td>
<tr>
<tr>
<td><code>TA_STRING_LITERAL</code></td>
<td><p><b>Required for C++</b></p>
<p>A NULL terminated dynamic string, which is cached.</p>
</td>
<tr>
<tr>
<td><code>TA_POINTER</code></td>
<td><p><b>Optional for C++</b></p>
<p>A pointer value that records the memory address
and not the target.</p>
</td>
<tr>
<tr>
<td><code>TA_KOID</code></td>
<td><p><b>Required for C++</b></p>
<p>A kernel object ID. For more information,
see <a href="/docs/reference/kernel_objects/objects.md">Zircon kernel objects
</a>.</p>
</td>
<tr>
</table>
### C++ notes
In C++, when you use a literal constant, type inference needs a hint
in order to get the size, signedness, and type right.
For example, is the value `77` a signed 32-bit integer? An unsigned 32-bit
integer? Or maybe even a 64-bit integer of some kind?
Type inference in the tracing macros works according to the standard C++ rules:
* `77` is a signed 32-bit integer, `TA_INT32`
* `77U` is an unsigned 32-bit integer, `TA_UINT32`
* `77L` is a signed 64-bit integer, `TA_INT64`
* `77LU` is an unsigned 64-bit integer, `TA_UINT64`
This also means that floating point needs to be explicitly noted if it's an
integer value.
For example:
* `77` is a `TA_INT32`.
* `77.` is a `TA_DOUBLE`.
If you are using constants, you should consider retaining the
encoding macros if you are expressing the values directly, or you should use
the appropriate `const` type. The following examples all do the same thing,
but show the use of a well defined type, a type macro, and a discouraged example.
* {Defined type}
```cpp
const int32_t my_id = 77; // well defined type
TRACE_INSTANT("category", "name", "int", my_id);
```
* {Type macro}
```cpp
#define MY_ID (TA_INT32(77)) // uses the typing macro
TRACE_INSTANT("category", "name", "int", MY_ID);
```
* {Discouraged}
```cpp
TRACE_INSTANT("category", "name", "int", 77); // discouraged
```
## TRACE_ENABLED {#TRACE_ENABLED}
```
Returns true if tracing is enabled.
Usage:
if (TRACE_ENABLED()) {
// do something possibly expensive only when tracing is enabled
}
```
## TRACE_CATEGORY_ENABLED {#TRACE_CATEGORY_ENABLED}
```
Returns true if tracing of the specified category has been enabled (which
implies that |TRACE_ENABLED()| is also true).
|category_literal| must be a null-terminated static string constant.
Usage:
if (TRACE_CATEGORY_ENABLED("category")) {
// do something possibly expensive only when tracing this category
}
```
## TRACE_NONCE {#TRACE_NONCE}
```
Returns a new unique 64-bit unsigned integer (within this process).
Each invocation returns a different non-zero value.
Useful for generating identifiers for async and flow events.
Usage:
trace_async_id_t async_id = TRACE_NONCE();
TRACE_ASYNC_BEGIN("category", "name", async_id);
// a little while later...
TRACE_ASYNC_END("category", "name", async_id);
```
## TRACE_INSTANT {#TRACE_INSTANT}
```
Writes an instant event representing a single moment in time (a probe).
0 to 15 arguments can be associated with the event, each of which is used
to annotate the moment with additional information.
|category_literal| and |name_literal| must be null-terminated static string constants.
|scope| is |TRACE_SCOPE_THREAD|, |TRACE_SCOPE_PROCESS|, or |TRACE_SCOPE_GLOBAL|.
|args| is the list of argument key/value pairs.
Usage:
TRACE_INSTANT("category", "name", TRACE_SCOPE_PROCESS, "x", TA_INT32(42));
```
## TRACE_COUNTER {#TRACE_COUNTER}
```
Writes a counter event with the specified id.
The arguments to this event are numeric samples are typically represented by
the visualizer as a stacked area chart. The id serves to distinguish multiple
instances of counters that share the same category and name within the
same process.
1 to 15 numeric arguments can be associated with the event, each of which is
interpreted as a distinct time series.
|category_literal| and |name_literal| must be null-terminated static string constants.
|counter_id| is the correlation id of the counter.
Must be unique for a given process, category, and name combination.
|args| is the list of argument key/value pairs.
Usage:
trace_counter_id_t counter_id = 555;
TRACE_COUNTER("category", "name", counter_id, "x", TA_INT32(42), "y", TA_DOUBLE(2.0))
```
## TRACE_DURATION {#TRACE_DURATION}
```
Writes a duration event that ends when the current scope exits.
Durations describe work that is happening synchronously on one thread.
They can be nested to represent a control flow stack.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the duration with additional information.
|category_literal| and |name_literal| must be null-terminated static string constants.
|args| is the list of argument key/value pairs.
Usage:
void function(int arg) {
TRACE_DURATION("category", "name", "arg", TA_INT32(arg));
// do something useful here
}
```
## TRACE_DURATION_BEGIN {#TRACE_DURATION_BEGIN}
```
Writes a duration begin event only.
This event must be matched by a duration end event with the same category and name.
Durations describe work that is happening synchronously on one thread.
They can be nested to represent a control flow stack.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the duration with additional information. The arguments provided
to matching duration begin and duration end events are combined together in
the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|args| is the list of argument key/value pairs.
Usage:
TRACE_DURATION_BEGIN("category", "name", "x", TA_INT32(42));
```
## TRACE_DURATION_END {#TRACE_DURATION_END}
```
Writes a duration end event only.
Durations describe work that is happening synchronously on one thread.
They can be nested to represent a control flow stack.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the duration with additional information. The arguments provided
to matching duration begin and duration end events are combined together in
the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|args| is the list of argument key/value pairs.
Usage:
TRACE_DURATION_END("category", "name", "x", TA_INT32(42));
```
## TRACE_ASYNC_BEGIN {#TRACE_ASYNC_BEGIN}
```
Writes an asynchronous begin event with the specified id.
This event may be followed by async instant events and must be matched by
an async end event with the same category, name, and id.
Asynchronous events describe work that is happening asynchronously and that
may span multiple threads. Asynchronous events do not nest. The id serves
to correlate the progress of distinct asynchronous operations that share
the same category and name within the same process.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the asynchronous operation with additional information. The
arguments provided to matching async begin, async instant, and async end
events are combined together in the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|async_id| is the correlation id of the asynchronous operation.
Must be unique for a given process, category, and name combination.
|args| is the list of argument key/value pairs.
Usage:
trace_async_id_t async_id = 555;
TRACE_ASYNC_BEGIN("category", "name", async_id, "x", TA_INT32(42));
```
## TRACE_ASYNC_INSTANT {#TRACE_ASYNC_INSTANT}
```
Writes an asynchronous instant event with the specified id.
Asynchronous events describe work that is happening asynchronously and that
may span multiple threads. Asynchronous events do not nest. The id serves
to correlate the progress of distinct asynchronous operations that share
the same category and name within the same process.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the asynchronous operation with additional information. The
arguments provided to matching async begin, async instant, and async end
events are combined together in the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|async_id| is the correlation id of the asynchronous operation.
Must be unique for a given process, category, and name combination.
|args| is the list of argument key/value pairs.
Usage:
trace_async_id_t async_id = 555;
TRACE_ASYNC_INSTANT("category", "name", async_id, "x", TA_INT32(42));
```
## TRACE_ASYNC_END {#TRACE_ASYNC_END}
```
Writes an asynchronous end event with the specified id.
Asynchronous events describe work that is happening asynchronously and that
may span multiple threads. Asynchronous events do not nest. The id serves
to correlate the progress of distinct asynchronous operations that share
the same category and name within the same process.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the asynchronous operation with additional information. The
arguments provided to matching async begin, async instant, and async end
events are combined together in the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|async_id| is the correlation id of the asynchronous operation.
Must be unique for a given process, category, and name combination.
|args| is the list of argument key/value pairs.
Usage:
trace_async_id_t async_id = 555;
TRACE_ASYNC_END("category", "name", async_id, "x", TA_INT32(42));
```
## TRACE_FLOW_BEGIN {#TRACE_FLOW_BEGIN}
```
Writes a flow begin event with the specified id.
This event may be followed by flow steps events and must be matched by
a flow end event with the same category, name, and id.
Flow events describe control flow handoffs between threads or across processes.
They are typically represented as arrows in a visualizer. Flow arrows are
from the end of the duration event that encloses the beginning of the flow
to the beginning of the duration event that encloses the next step or the
end of the flow. The id serves to correlate flows that share the same
category and name across processes.
This event must be enclosed in a duration event that represents where
the flow handoff occurs.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the flow with additional information. The arguments provided
to matching flow begin, flow step, and flow end events are combined together
in the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|flow_id| is the correlation id of the flow.
Must be unique for a given category and name combination.
|args| is the list of argument key/value pairs.
Usage:
trace_flow_id_t flow_id = 555;
TRACE_FLOW_BEGIN("category", "name", flow_id, "x", TA_INT32(42));
```
## TRACE_FLOW_STEP {#TRACE_FLOW_STEP}
```
Writes a flow step event with the specified id.
Flow events describe control flow handoffs between threads or across processes.
They are typically represented as arrows in a visualizer. Flow arrows are
from the end of the duration event that encloses the beginning of the flow
to the beginning of the duration event that encloses the next step or the
end of the flow. The id serves to correlate flows that share the same
category and name across processes.
This event must be enclosed in a duration event that represents where
the flow handoff occurs.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the flow with additional information. The arguments provided
to matching flow begin, flow step, and flow end events are combined together
in the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|flow_id| is the correlation id of the flow.
Must be unique for a given category and name combination.
|args| is the list of argument key/value pairs.
Usage:
trace_flow_id_t flow_id = 555;
TRACE_FLOW_STEP("category", "name", flow_id, "x", TA_INT32(42));
```
## TRACE_FLOW_END {#TRACE_FLOW_END}
```
Writes a flow end event with the specified id.
Flow events describe control flow handoffs between threads or across processes.
They are typically represented as arrows in a visualizer. Flow arrows are
from the end of the duration event that encloses the beginning of the flow
to the beginning of the duration event that encloses the next step or the
end of the flow. The id serves to correlate flows that share the same
category and name across processes.
This event must be enclosed in a duration event that represents where
the flow handoff occurs.
0 to 15 arguments can be associated with the event, each of which is used
to annotate the flow with additional information. The arguments provided
to matching flow begin, flow step, and flow end events are combined together
in the trace; it is not necessary to repeat them.
|category_literal| and |name_literal| must be null-terminated static string constants.
|flow_id| is the correlation id of the flow.
Must be unique for a given category and name combination.
|args| is the list of argument key/value pairs.
Usage:
trace_flow_id_t id = 555;
TRACE_FLOW_END("category", "name", flow_id, "x", TA_INT32(42));
```
## TRACE_BLOB_EVENT {#TRACE_BLOB_EVENT}
```
Writes a large blob record with the given blob data and metadata.
Here metadata includes timestamp, thread and process information, and arguments,
which is what most event records contain.
Blobs that exceed |TRACE_ENCODED_RECORD_MAX_TOTAL_LENGTH| will be silently
ignored, as will blobs that cannot fit within the remaining space in the
trace buffer.
|category_literal| and |name_literal| must be null-terminated static string constants.
|blob| is a pointer to the data.
|blob_size| is the size, in bytes, of the data.
```
## TRACE_BLOB_ATTACHMENT {#TRACE_BLOB_ATTACHMENT}
```
Writes a large blob record with the given blob data, with only a
category and name associated with the blob. This will not contain much
additional metadata. This means timestamp, thread and process information,
and arguments are not included with the record.
Blobs that exceed |TRACE_ENCODED_RECORD_MAX_TOTAL_LENGTH| will be silently
ignored, as will blobs that cannot fit within the remaining space in the
trace buffer.
|category_literal| and |name_literal| must be null-terminated static string constants.
|blob| is a pointer to the data.
|blob_size| is the size, in bytes, of the data.
```
## TRACE_KERNEL_OBJECT {#TRACE_KERNEL_OBJECT}
```
Writes a description of a kernel object indicated by |handle|,
including its koid, name, and the supplied arguments.
0 to 15 arguments can be associated with the record, each of which is used
to annotate the handle with additional information.
|handle| is the handle of the object being described.
|args| is the list of argument key/value pairs.
Usage:
zx_handle_t handle = ...;
TRACE_KERNEL_OBJECT(handle, "description", TA_STRING("some object"));
```
<!-- # Commented out for the time being
## TRACE_INSTANT {#trace_instant}
The `TRACE_INSTANT` macro records a trace with a single timestamp that is
scoped to a process, thread, or global.
### Arguments
```
TRACE_INSTANT("category", "name", SCOPE, "key", value);
```
This macro accepts the following arguments:
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Valid values</th>
</tr>
<tr>
<td><code>category</code></td>
<td><p><b>Required</b></p>
<p>Specifies the category of the trace event.</p>
<p>For example, a category could be: <code>demo</code></p>
<p>The category namespace is global to all components that are running,
so if there is another component that also uses <code>demo</code>, you may see trace
data from another trace provider.</p>
</td>
<td>Null terminated string.</td>
</tr>
<tr>
<td><code>name</code></td>
<td><p><b>Required</b></p>
<p>Specifies a description of the event data.</p>
<p>In many cases, you may use the same categories for various trace points,
but you can use the <code>name</code> to distinguish these various trace
points.</p>
</td>
<td>Null terminated string.</td>
</tr>
<tr>
<td><code>SCOPE</code></td>
<td><p><b>Required</b></p>
<p>Specifies if the trace is scoped to a process, thread, or globally
scoped.</p>
</td>
<td><p>Valid values are:</p>
<p><code>TRACE_SCOPE_PROCESS</code></p>
<p>The event is only relevant to
the process in which it occurred.</p>
<p><code>TRACE_SCOPE_THREAD</code></p>
<p>The event is only relevant to
the thread it occurred on.</p>
<p><code>TRACE_SCOPE_GLOBAL</code></p>
<p>The event is globally relevant.</p>
</td>
</tr>
<tr>
<td><code>key</code></td>
<td><p><b>Optional</b></p>
<p>The number of keys and values must match as they are used in pairs.</p>
<p>Specifies a key for the <code>value</code> that your trace provider
records.</p>
</td>
<td>Null terminated string.</td>
</tr>
<tr>
<td><code>value</code></td>
<td><p><b>Optional</b></p>
<p>The number of keys and values must match as they are used in pairs.</p>
<p>Specifies a value for the respective <code>key</code> of the event data.</p>
</td>
<td><p>This value may be <code>NULL</code>.</p>
<p>The values that you specify must be properly encoded values, see
<a href="#encoding-macros">Encoding macros</a>.</td>
</tr>
</table>
### Examples
#### No key and value pairs
In some cases, you may need to record trace data, but do not need to record
any key and value pairs:
```
TRACE_INSTANT("helloworld", "hello_world_test", TRACE_SCOPE_PROCESS);
```
#### Single key and value pair
In some cases, you may want to only record trace data for a single key and value pair:
```
TRACE_INSTANT("helloworld", "hello_world_test", TRACE_SCOPE_PROCESS, "message", TA_STRING("Hello, World!"));
```
#### Multiple key and value pairs
In some cases, you may want to only record trace data for a multiple key and value pairs:
```
TRACE_INSTANT("helloworld", "hello_world_test", TRACE_SCOPE_PROCESS, "message1", TA_STRING("First: Hello, World!"), "message2", TA_STRING("Second: Hello, World!"), "message3", TA_STRING("Third: Hello, World!"));
```
-->