# UI Plugins

UI plugins allow developers to add new visualizations and analysis tools
directly into the Perfetto interface. By leveraging a rich set of extension
points, plugins can tailor Perfetto to specific use cases.

This guide provides comprehensive instructions on how to create and contribute
UI plugins to Perfetto.

If this is your first time contributing to Perfetto, please first follow
[Perfetto getting started](getting-started) and then
[UI getting started](ui-getting-started).

> Note: All plugins are currently in-tree, that is they're located in the open
> source Perfetto codebase and served along with the public build of Perfetto
> located at https://ui.perfetto.dev. If you wish to add closed-source plugins,
> you will need to fork and host your own version of Perfetto. There is no way,
> currently, to side-load closed-source plugins.

The plugins that start with 'com.example'
[here](https://github.com/google/perfetto/tree/main/ui/src/plugins) provide live
examples of the features listed in this doc, so please do take a look at those
if one is present for your particular feature.

The public plugin API, which you'll be using in this doc, can be browsed
[here](https://github.com/google/perfetto/tree/main/ui/src/public).

## Getting started

Copy the skeleton plugin:

```sh
cp -r ui/src/plugins/com.example.Skeleton ui/src/plugins/<your-plugin-name>
```

Now edit `ui/src/plugins/<your-plugin-name>/index.ts`. Search for all instances
of `SKELETON: <instruction>` in the file and follow the instructions.

Notes on naming:

- Plugins should be prefixed with the reversed components of a domain name you
  control. For example if `example.com` is your domain your plugin should be
  named `com.example.Foo`.
- Avoid including the term 'plugin' in the name.
- The `pluginId` and directory name must match.
- The prefix `dev.perfetto.` is reserved for plugins maintained by the core
  Perfetto team.

### Start the dev server

```sh
ui/run-dev-server
```

Now navigate to [localhost:10000](http://localhost:10000/)

### Enabling your plugin

- Navigate to the plugins page:
  [localhost:10000/#!/plugins](http://localhost:10000/#!/plugins).
- Ctrl-F for your plugin name and enable it.
- Enabling/disabling plugins requires a restart of the UI, so refresh the page
  to start your plugin.

You can request for your plugin to be enabled by default. Follow the
[default plugins](#default-plugins) section for this.

### Adding Styles

To add custom styles to your plugin, create a `styles.scss` file in your
plugin's directory, next to your `index.ts` file.

`ui/src/plugins/<your-plugin-name>/styles.scss`

The build system will automatically detect this file and include it in the main
stylesheet. You can use any standard SCSS syntax in this file.

For example, to change the background color of a component in your plugin:

```scss
.pf-my-plugin-component {
  background-color: blue;
}
```

All class names should be prefixed with `pf-` to avoid conflicts with other
libraries.

It's recommended to scope your styles to your plugin to avoid conflicts with
other plugins or the core UI. A good practice is to wrap your plugin's UI in a
container with a unique class name.

### Upload your plugin for review

- Update `ui/src/plugins/<your-plugin-name>/OWNERS` to include your email.
- Follow the [Contributing](./getting-started#contributing) instructions to
  upload your PR to Github.
- Once uploaded add `stevegolton@google.com` as a reviewer for your PR.

## Plugin lifecycle

`onActivate` is called once when the app first starts up, passing in the `App`
object. This object can be used to register core extensions such as pages,
commands and sidebar links, which will be available before a trace is loaded.

When the user loads a trace the plugin class is instantiated and `onTraceLoad`
is called passing in the `Trace` object. This object can be used to register
extensions which are scoped to the lifetime of that particular trace such as
tracks, tabs and workspaces.

All extensions that can be registered on the app object can also be registered
on the trace object, but these extensions only last for the lifetime of the
trace. For example, a command registered on the trace object will only be
available while that trace is loaded, and will disappear when switching traces.
Typically, if this is done in the `onTraceLoad()` hook then the extension is
re-registered automatically with every new trace that is loaded.

> Note: Don't put any code the main body of the plugin file as there is no
> guarantee the core will be set up by that point. Instead, wait for the core to
> call the plugin either via `onActivate` or `onTraceLoad`.

To demonstrate the lifecycle of a plugin, let's examine a minimal plugin that
implements the key lifecycle hooks and logs to the terminal:

```ts
export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyPlugin';

  static onActivate(app: App): void {
    // Called once on app startup
    console.log('MyPlugin::onActivate()', app.pluginId);
    // Note: It's rare that plugins would need this hook as most plugins are
    // interested in trace details. Thus, this function can usually be omitted.
  }

  constructor(trace: Trace) {
    // Called each time a trace is loaded
    console.log('MyPlugin::constructor()', trace.traceInfo.traceTitle);
  }

  async onTraceLoad(trace: Trace): Promise<void> {
    // Called each time a trace is loaded
    console.log('MyPlugin::onTraceLoad()', trace.traceInfo.traceTitle);
    // Note this function returns a promise, so any any async calls should be
    // completed before this promise resolves as the app using this promise for
    // timing and plugin synchronization.
  }
}
```

Run this plugin with devtools to see the log messages in the console, which
should give you a feel for the plugin lifecycle. Try opening a few traces one
after another.

## Performance

`onActivate()` and `onTraceLoad()` should generally complete as quickly as
possible, however sometimes `onTraceLoad()` may need to perform async operations
on trace processor such as performing queries and/or creating views and tables.
Thus, `onTraceLoad()` should return a promise (or you can simply make it an
async function). When this promise resolves it tells the core that the plugin is
fully initialized.

> Note: It's important that any async operations done in onTraceLoad() are
> awaited so that all async operations are completed by the time the promise is
> resolved. This is so that plugins can be properly timed and synchronized.

```ts
// GOOD
async onTraceLoad(trace: Trace) {
  await trace.engine.query(...);
}

// BAD
async onTraceLoad(trace: Trace) {
  // Note the missing await!
  trace.engine.query(...);
}
```

## Plugin API

For more detailed information and documentation please consult the API source in
[ui/src/public/](https://github.com/google/perfetto/blob/main/ui/src/public) or
one of the many example plugins (that start with `com.example.*`) in
[ui/src/plugins/](https://github.com/google/perfetto/blob/main/ui/src/plugins).

### Getting the trace object from the app object

When a trace is loaded, `app.trace` will return the current trace object, or
undefined if no trace is loaded.

### Querying the trace

As soon as the plugin obtains a trace, it can execute queries against it using
the trace's `engine` property.

```ts
const result = await trace.engine.query('select * from slice');
const schema = {id: NUM, ts: LONG, dur: LONG, name: STR};
for (const iter = result.iter(schema); iter.valid(); iter.next()) {
  console.log(iter.id, iter.ts, iter.dur, iter.name);
}
```

Typically queries returns a list of rows, which can be iterated through like in
the example.

The schema:

- Informs the engine what types we expect the columns to have and what
  JavaScript type to convert each column to. An error is thrown if the returned
  typed cannot be coerced into the desired one.
- Informs typescript what types to expect at compile time, the `iter` object
  assumes the same type as that of the schema.

> Note: The problem with JavaScript numbers. A javascript number type is
> actually a double precision float, and thus can only represent integers up to
> 2^53-1. Trace processor can represent 64 bit integers, so when converting to
> js numbers, we can lost precision. THis is a problem for large numbers such as
> timestamps and durations.

The possible schema types are as follows:

- `NUM`: Represents a numeric value. Converts to JavaScript `number`.
- `STR`: Represents a string value. Converts to JavaScript `string`.
- `LONG`: Represents a large integer value (64-bit). Converts to JavaScript
  `bigint`.
- `BLOB`: Represents binary data (Binary Large Object). Converts to JavaScript
  `Uint8Array`.
- `NUM_NULL`: Represents a numeric value that can also be `null`. Converts to
  JavaScript `number | null`.
- `STR_NULL`: Represents a string value that can also be `null`. Converts to
  JavaScript `string | null`.
- `LONG_NULL`: Represents a large integer value (64-bit) that can also be
  `null`. Converts to JavaScript `bigint | null`.
- `BLOB_NULL`: Represents binary data that can also be `null`. Converts to
  JavaScript `Uint8Array | null`.
- `UNKNOWN`: Represents a column where the specific type is not strictly defined
  or can be `null`. It's often used as a base type from which nullable types
  extend. When not specified, all integer values will be converted to a bigint.

### Selections

Plugins can programmatically control what is selected in the Perfetto UI. This
is primarily done using methods available on the `trace.selection` object.

You typically want to select an entity to find out more information about that
entity, which is displayed in the current selection panel. Selections are
usually invoked by the user, but can be controlled programmatically too.

You can always access the current selection details via
`trace.selection.selection`. This object has a `kind` property (e.g.,
'track_event', 'area', 'note', 'empty') and other properties specific to the
type of selection. The optional `SelectionOpts` object can be passed to
selection methods to influence UI behaviors like automatically scrolling to the
selection or switching to the "Current Selection" tab.

#### Selection Options (`SelectionOpts`)

The `SelectionOpts` object can be passed to most selection methods to customize
the UI's response to a new selection. It has the following optional properties:

- `switchToCurrentSelectionTab?: boolean`: If `true` (the default), the UI will
  automatically switch to the "Current Selection" tab in the details panel. Set
  to `false` to keep the current tab active.
- `scrollToSelection?: boolean`: If `true`, the timeline will attempt to scroll
  to bring the newly selected item into view. The default is `false`.

#### Selecting a Track Event (event, slice, counter sample, etc)

To select an individual event on a track:

```ts
trace.selection.selectTrackEvent('my.track', 123);
```

#### Selecting an Area (Time Range)

To select a specific time range, potentially across multiple tracks. The `Area`
object requires `start` (time), `end` (time), and an array of `trackUris`
(string[]).

```ts
trace.selection.selectArea({
  start: Time.fromRaw(123n), // Time in nanoseconds (bigint)
  end: Time.fromRaw(456n), // Time in nanoseconds (bigint)
  trackUris: ['track.foo', 'track.bar'], // Array of track URIs to include
});
```

#### Selecting an Entire Track

Selecting an entire track highlights it in the timeline and displays track
details in the drawer.

```ts
trace.selection.selectTrack('my.track');
```

#### Selecting an Event via SQL Table and ID

If you have an event's ID from a specific SQL table (e.g., `slice` table) but
not its direct track URI, Perfetto can attempt to resolve and select it. Certain
tracks do directly represent rows in the well known tables but it's up to the
plugin developers whether or not these are wired up properly.

```ts
trace.selection.selectSqlEvent('slice', 123);
```

#### Clearing the Current Selection

To deselect whatever is currently selected in the UI:

```ts
trace.selection.clearSelection();
```

### Pinning Tracks

A common task for plugins are to pin certain interesting tracks (usually as a
result of a command).

This can be achieved by finding the appropriate track in the workspace and
calling its `pin()` method. This will pin it to the top of its parent workspace.

```ts
trace.workspace
  .flatTracks()
  .find((t) => t.name.startsWith('foo'))
  .forEach((t) => t.pin());
```

### Workspaces

Workspaces are the primary containers for organizing and displaying tracks in
the Perfetto UI. They allow users to manage different views of trace data, save
track layouts, and switch between them. Plugins can interact with workspaces to
add, remove, and arrange tracks, as well as create and manage custom workspaces.

The main interfaces and classes related to workspaces are `WorkspaceManager`,
`Workspace`, and `TrackNode`. These are typically accessed via
`trace.workspaces` (for the manager) and `trace.workspace` (for the current
active workspace) once a trace is loaded.

#### Workspace Manager (`trace.workspaces`)

The `WorkspaceManager` provides an overview and control over all available
workspaces. It's accessible via `trace.workspaces`.

Key methods and properties:

- `currentWorkspace: Workspace`: A read-only property that refers to the
  currently active workspace. This is the same instance as `trace.workspace`.
- `all: ReadonlyArray<Workspace>`: A read-only array of all workspaces currently
  loaded.
- `createEmptyWorkspace(displayName: string): Workspace`: Creates a new, empty
  workspace with the given display name and returns it. This new workspace is
  not automatically switched to.
- `switchWorkspace(workspace: Workspace): void`: Switches the UI to display the
  provided workspace.

**Example: Creating and Switching to a New Workspace**

```ts
// Assuming 'trace' is the Trace object
const newWorkspace =
  trace.workspaces.createEmptyWorkspace('My Custom Analysis');
trace.workspaces.switchWorkspace(newWorkspace);
console.log(`Switched to workspace: ${newWorkspace.title}`);
```

#### Workspace (`trace.workspace` or an instance from `WorkspaceManager`)

A `Workspace` object represents a single layout of tracks, including a main
track area and a pinned track area.

Key properties:

- `id: string`: A unique, session-specific ID for the workspace.
- `title: string`: A human-readable title for the workspace (e.g.,
  "<untitled-workspace>" by default, or the name provided to
  `createEmptyWorkspace`). Can be modified.
- `userEditable: boolean`: Indicates if the user can modify this workspace
  (default is `true`).
- `pinnedTracksNode: TrackNode`: A special `TrackNode` that acts as the root for
  pinned tracks. Tracks added here appear in the pinned area at the top of the
  timeline.
- `tracks: TrackNode`: The main root `TrackNode` for the workspace. All regular
  tracks and track groups are children of this node.
- `pinnedTracks: ReadonlyArray<TrackNode>`: A convenience getter for the
  children of `pinnedTracksNode`.
- `children: ReadonlyArray<TrackNode>`: A convenience getter for the children of
  the main `tracks` node.

Key methods:

- `clear(): void`: Removes all tracks from both the main track area and the
  pinned area.
- `pinTrack(track: TrackNode): void`: Adds a lightweight clone (containing
  `uri`, `name`, `removable` properties) of the given `TrackNode` to the pinned
  tracks area.
- `unpinTrack(track: TrackNode): void`: Removes a track (matched by `uri`) from
  the pinned tracks area.
- `hasPinnedTrack(track: TrackNode): boolean`: Checks if a track with the same
  `uri` as the given `track` is currently pinned.
- `getTrackById(id: string): TrackNode | undefined`: Finds a `TrackNode` (in
  either main or pinned areas) by its unique `id`. This is an O(1) operation.
- `getTrackByUri(uri: string): TrackNode | undefined`: Finds a `TrackNode` (in
  the main tracks area) by its `uri`.
- Track manipulation methods (delegated to the main `tracks` node):
  - `addChildInOrder(child: TrackNode): Result`
  - `addChildLast(child: TrackNode): Result`
  - `addChildFirst(child: TrackNode): Result`
  - `addChildBefore(child: TrackNode, referenceNode: TrackNode): Result`
  - `addChildAfter(child: TrackNode, referenceNode: TrackNode): Result`
  - `removeChild(child: TrackNode): void`
- `flatTracksOrdered: ReadonlyArray<TrackNode>`: Returns a flattened list of all
  descendant nodes in the main track area, in depth-first order.
- `flatTracks: ReadonlyArray<TrackNode>`: Returns a flattened list of all
  descendant nodes in the main track area, in no particular order (more
  efficient if order doesn't matter).

#### Track Node (`TrackNode`)

`TrackNode` is the fundamental building block for structuring tracks within a
workspace. A `TrackNode` can represent an individual track (if it has a `uri`
pointing to a `TrackRenderer`) or a group of tracks (if it has children).

**Creating a `TrackNode`:**

```ts
import {TrackNode} from '../../public'; // Adjust path as needed

// Node for an actual track
const myRenderableTrackNode = new TrackNode({
  name: 'My Slice Track',
  uri: 'plugin.id#mySliceTrackUri', // URI of a registered Track
  sortOrder: 100,
  removable: true,
});

// Node for a group
const myGroupNode = new TrackNode({
  name: 'My Analysis Group',
  sortOrder: 50,
  collapsed: false, // Start expanded
});
```

**`TrackNodeArgs` (Constructor Arguments):**

When creating a `TrackNode`, you can pass an optional object with the following
properties (defined in [`TrackNodeArgs`]):

- `name: string`: Human-readable name/title for the node.
- `uri: string`: If this node represents a renderable track, this is the URI of
  the registered `TrackRenderer`.
- `headless: boolean` (default `false`): If `true`, the node's own header/shell
  is not displayed, and its children are rendered as if they are direct children
  of this node's parent. Useful for logical grouping without visual nesting.
- `sortOrder: number`: A number used for ordering nodes when `addChildInOrder`
  is called. Higher numbers typically appear first (or as per specific parent
  implementation).
- `collapsed: boolean` (default `true`): Whether the node should start in a
  collapsed state (children hidden).
- `isSummary: boolean` (default `false`): If `true`, this track acts as a
  summary for its children. It gets special styling and behavior (e.g., sticky
  when expanded).
- `removable: boolean` (default `false`): If `true`, a close button is shown,
  allowing users to remove this node from the workspace.

**Key `TrackNode` Properties:**

- `id: string`: A unique, session-specific ID for this node instance.
- `parent: TrackNode | undefined`: The parent `TrackNode`.
- `workspace: Workspace | undefined`: The `Workspace` this node belongs to, if
  any.
- `children: ReadonlyArray<TrackNode>`: An ordered list of child `TrackNode`s.
- `hasChildren: boolean`: True if the node has children.
- `expanded: boolean` / `collapsed: boolean`: Current expansion state.
- `isPinned: boolean`: True if this node (or one with the same URI) is in the
  workspace's pinned area.
- `fullPath: ReadonlyArray<string>`: An array of names from the root node to
  this node, representing its path in the hierarchy.

**Key `TrackNode` Methods:**

- **Hierarchy Management:**
  - `addChildInOrder(child: TrackNode): Result`
  - `addChildLast(child: TrackNode): Result`
  - `addChildFirst(child: TrackNode): Result`
  - `addChildBefore(child: TrackNode, referenceNode: TrackNode): Result`
  - `addChildAfter(child: TrackNode, referenceNode: TrackNode): Result`
  - `removeChild(child: TrackNode): void`: Removes a direct child.
  - `remove(): void`: Removes this node from its parent and unpins it from the
    workspace.
  - `clear(): void`: Removes all children of this node.
- **State & Appearance:**
  - `pin(): void`: Pins this track in its workspace.
  - `unpin(): void`: Unpins this track.
  - `expand(): void`
  - `collapse(): void`
  - `toggleCollapsed(): void`
  - `reveal(): void`: Expands all ancestor nodes to make this node visible.
- **Traversal & Querying:**
  - `getTrackById(id: string): TrackNode | undefined`: Finds a descendant node
    by its `id` (O(1)).
  - `getTrackByUri(uri: string): TrackNode | undefined`: Finds a descendant node
    by its `uri` (O(1)).
  - `flatTracksOrdered: ReadonlyArray<TrackNode>`: Flattened list of all
    descendants (depth-first).
  - `flatTracks: ReadonlyArray<TrackNode>`: Flattened list of all descendants
    (unordered, faster).
- `clone(deep = false): TrackNode`: Creates a copy of this node. If `deep` is
  true, children are also cloned.

**Example: Building a Track Hierarchy**

```ts
// Assuming 'trace' is the Trace object and 'workspace' is trace.workspace

const parentGroup = new TrackNode({name: 'CPU Analysis'});
workspace.addChildLast(parentGroup);

const cpu0FreqTrack = new TrackNode({
  name: 'CPU 0 Frequency',
  uri: 'perfetto.CpuFrequency#cpu0', // Example URI
  sortOrder: 10,
});
parentGroup.addChildInOrder(cpu0FreqTrack);

const cpu1FreqTrack = new TrackNode({
  name: 'CPU 1 Frequency',
  uri: 'perfetto.CpuFrequency#cpu1', // Example URI
  sortOrder: 20,
});
parentGroup.addChildInOrder(cpu1FreqTrack);

parentGroup.expand(); // Show the CPU frequency tracks
cpu0FreqTrack.pin(); // Pin CPU 0 frequency track
```

This structure allows plugins to dynamically build complex and organized track
layouts tailored to specific analysis tasks. Remember to register your actual
`TrackRenderer`s using `trace.tracks.registerTrack` before creating `TrackNode`s
that reference their URIs.

### Commands

Commands are user issuable shortcuts for actions in the UI. They are typically
invoked by the user via the command palette which can be opened by pressing
`Ctrl+Shift+P` (or `Cmd+Shift+P` on Mac), or by typing a `>` into the omnibox,
but can also be invoked programmatically.

#### Registering Commands

To add a command, the `CommandManager` (available as `app.commands` or
`trace.commands`) provides the `registerCommand` method for this purpose.

```ts
registerCommand(command: {
  id: string;
  name: string;
  callback: (...args: any[]) => any;
  defaultHotkey?: Hotkey
}): void;
```

Registers a new command. Takes a `Command` object which looks like this:

- `id`: A unique string which identifies this command. The `id` should be
  prefixed with the plugin id followed by a `#`. All command `id`s must be
  unique system-wide.
- `name`: A human readable name for the command, which is shown in the command
  palette.
- `callback`: The callback which actually performs the action.
- `defaultHotkey`: An optional default hotkey for this command.

See
[hotkey.ts](https://github.com/google/perfetto/blob/main/ui/src/base/hotkeys.ts)
for the available hotkey keys and modifiers.

> Note: This is referred to as the 'default' hotkey because we are reserving the
> right to add a feature in the future where users can modify their hotkeys.

**Example**

```ts
appOrTrace.commands.registerCommand({
  id: `${app.pluginId}#sayHello`,
  name: 'Say hello',
  callback: () => console.log('Hello, world!'),
});
```

Notes on naming:

- Commands should have ids with the pattern `<pluginId>#doSomething`
- Commands ids should be prefixed with the id of the plugin which provides them.
- Command names should have the form "Verb something something", and should be
  in normal sentence case. I.e. don't capitalize the first letter of each word.
  - Good: "Pin janky frame timeline tracks"
  - Bad: "Tracks are Displayed if Janky"

#### Invoking Commands

Besides registering their own commands, plugins can also invoke any existing
command by its ID. This allows plugins to trigger actions provided by other
plugins or by the Perfetto core. The `CommandManager` (available as
`app.commands` or `trace.commands`) provides the `runCommand` method for this
purpose.

```ts
runCommand(commandId: string, ...args: any[]): any;
```

Executes the command identified by `commandId`, passing any additional arguments
to the command's callback. It returns a Promise that resolves with the result of
the command's callback, if any.

- Args
  - `commandId`: The id of the command to run.
  - `...args`: Passed directly to the command callback.
- Returns
  - `any`: Whatever is returned from the command callback.

**Example:**

```ts
// PluginA
appOrTrace.commands.registerCommand({
  id: 'PluginA#increment',
  name: 'Increment',
  callback: (num) => num + 1,
});

// PluginB
try {
  const result = appOrTrace.commands.runCommand('PluginA#increment', 1);
  // result should be 2
} catch (e) {
  console.error(`Failed to run command: ${(e as Error).message}`);
}
```

Plugins can discover command IDs by looking at other plugins' registrations or
by referring to documentation for core commands.

Examples:

- [com.example.ExampleSimpleCommand](https://github.com/google/perfetto/blob/main/ui/src/plugins/com.example.ExampleSimpleCommand/index.ts).
- [perfetto.CoreCommands](https://github.com/google/perfetto/blob/main/ui/src/core_plugins/commands/index.ts).
- [com.example.ExampleState](https://github.com/google/perfetto/blob/main/ui/src/plugins/com.example.ExampleState/index.ts).

### Tracks

In order to add a new track to the timeline, you'll need to create two entities:

- A track which controls what the track looks like and how it fetches data from
  trace processor.
- A track node, which is a pointer to a track object and controls where the
  track appears in a workspace.

Tracks are the main way timeseries data is added to the UI.

To add a track use `trace.tracks.registerTrack`.

```ts
registerTrack(track: {
  uri: string;
  track: TrackRenderer;
  description?: string | (() => m.Children);
  subtitle?: string;
  tags?: TrackTags;
  chips?: ReadonlyArray<string>;
}): void;
```

Registers a new track with Perfetto. Pass a `Track` object which includes:

- `uri`: Unique id for this track.
- `track`: Track renderer - describes how this track loads data and renders it
  to the canvas.
- `description`: A human readable description or help text for this track.
- `subtitle`: Shown underneath the track title.
- `tags`: Arbitrary key-value pairs.
- `chipd`: A list of strings displayed to the right of the track title.

Track renderers are powerful but complex so it's strongly advised not to create
your own. Instead, by far the easiest way to get started with tracks is to use
the `createQuerySliceTrack` and `createQueryCounterTrack` helpers.

**Example:**

```ts
import {createQuerySliceTrack} from '../../components/tracks/query_slice_track';

// ~~ snip ~~

const uri = `${trace.pluginId}#MyTrack`;

// Create a new track renderer based on a query
const renderer = await createQuerySliceTrack({
  trace,
  uri,
  data: {
    sqlSource: 'select * from slice where track_id = 123',
  },
});

// Register the track renderer with the core
trace.tracks.registerTrack({uri, renderer});

// Create a track node that references the track using its uri
const trackNode = new TrackNode({uri, name: 'My Track'});

// Add the track node to the current workspace
trace.workspace.addChildInOrder(trackNode);
```

See
[the source](https://github.com/google/perfetto/blob/main/ui/src/components/tracks/query_slice_track.ts)
for detailed usage.

You can also add a counter track using `createQueryCounterTrack` which works in
a similar way.

```ts
import {createQueryCounterTrack} from '../../components/tracks/query_counter_track';

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyPlugin';
  async onTraceLoad(trace: Trace) {
    const title = 'My Counter Track';
    const uri = `${trace.pluginId}#MyCounterTrack`;
    const query = 'select * from counter where track_id = 123';

    // Create a new track renderer based on a query
    const renderer = await createQueryCounterTrack({
      trace,
      uri,
      data: {
        sqlSource: query,
      },
    });

    // Register the track renderer with the core
    trace.tracks.registerTrack({uri, title, renderer});

    // Create a track node that references the track using its uri
    const trackNode = new TrackNode({uri, title});

    // Add the track node to the current workspace
    trace.workspace.addChildInOrder(trackNode);
  }
}
```

See
[the source](https://github.com/google/perfetto/blob/main/ui/src/components/tracks/query_counter_track.ts)
for detailed usage.

### Track Descriptions / Help Text

If a `description` property is provided when registering a track, any
`TrackNode` that references that track will display a help button in its shell.
When clicked, a popup appears containing the content of the `description`.

The `description` can be either a simple string or a function that returns
Mithril vnodes. Using a function is useful for embedding rich content, such as
hyperlinks, into the popup.

For example:

```ts
ctx.tracks.registerTrack({
  description: () => {
    return m('', [
      `Shows which threads were running on CPU ${cpu.toString()} over time.`,
      m('br'),
      m(
        Anchor,
        {
          href: 'https://perfetto.dev/docs/data-sources/cpu-scheduling',
          target: '_blank',
          icon: Icons.ExternalLink,
        },
        'Documentation',
      ),
    ]);
  },
  // ...
});
```

The `description` property is part of the `Track` registration rather than the
`TrackNode` because `TrackNode`s must be serializable to JSON, and functions
(which `description` can be) are not.

This has an implication for track groups. If you want to add help text to a
`TrackNode` that only serves as a group and has no renderable `Track` associated
with it, you must register a "dummy" track for it. This dummy track can have an
empty renderer but will carry the `description`.

```ts
const uri = `com.example.Tracks#GroupWithHelpText`;

trace.tracks.registerTrack({
  uri,
  renderer: {
    // Empty track renderer
    render: () => {},
  },
  description: () => [
    'This is a group track with some help text.',
    m('br'),
    'Use Mithril vnodes for formatting.',
  ],
});

// Now create the group node referencing the dummy track's URI.
const groupNode = new TrackNode({uri, name: 'Group with Help Text'});
```

Example:
https://github.com/google/perfetto/blob/main/ui/src/plugins/com.example.Tracks/index.ts

#### Grouping Tracks

Any track can have children. Just add child nodes any `TrackNode` object using
its `addChildXYZ()` methods. Nested tracks are rendered as a collapsible tree.

```ts
const group = new TrackNode({title: 'Group'});
trace.workspace.addChildInOrder(group);
group.addChildLast(new TrackNode({title: 'Child Track A'}));
group.addChildLast(new TrackNode({title: 'Child Track B'}));
group.addChildLast(new TrackNode({title: 'Child Track C'}));
```

Tracks nodes with children can be collapsed and expanded manually by the user at
runtime, or programmatically using their `expand()` and `collapse()` methods. By
default tracks are collapsed, so to have tracks automatically expanded on
startup you'll need to call `expand()` after adding the track node.

```ts
group.expand();
```

![Nested tracks](../images/ui-plugins/nested_tracks.png)

Summary tracks are behave slightly differently to ordinary tracks. Summary
tracks:

- Are rendered with a light blue background when collapsed, dark blue when
  expanded.
- Stick to the top of the viewport when scrolling.
- Area selections made on the track apply to child tracks instead of the summary
  track itself.

To create a summary track, set the `isSummary: true` option in its initializer
list at creation time or set its `isSummary` property to true after creation.

```ts
const group = new TrackNode({title: 'Group', isSummary: true});
// ~~~ or ~~~
group.isSummary = true;
```

![Summary track](../images/ui-plugins/summary_track.png)

Examples

- [com.example.ExampleNestedTracks](https://github.com/google/perfetto/blob/main/ui/src/plugins/com.example.ExampleNestedTracks/index.ts).

#### Track Ordering

Tracks can be manually reordered using the `addChildXYZ()` functions available
on the track node api, including `addChildFirst()`, `addChildLast()`,
`addChildBefore()`, and `addChildAfter()`.

See
[the workspace source](https://github.com/google/perfetto/blob/main/ui/src/public/workspace.ts)
for detailed usage.

However, when several plugins add tracks to the same node or the workspace, no
single plugin has complete control over the sorting of child nodes within this
node. Thus, the sortOrder property is be used to decentralize the sorting logic
between plugins.

In order to do this we simply give the track a `sortOrder` and call
`addChildInOrder()` on the parent node and the track will be placed before the
first track with a greater `sortOrder` in the list. (i.e. lower `sortOrder`s
appear higher in the stack).

```ts
// PluginA
workspace.addChildInOrder(new TrackNode({title: 'Foo', sortOrder: 10}));

// Plugin B
workspace.addChildInOrder(new TrackNode({title: 'Bar', sortOrder: -10}));
```

Now it doesn't matter which order plugin are initialized, track `Bar` will
appear above track `Foo` (unless reordered later).

If no `sortOrder` is defined, the track assumes a `sortOrder` of 0.

> It is recommended to always use `addChildInOrder()` in plugins when adding
> tracks to the `workspace`, especially if you want your plugin to be enabled by
> default, as this will ensure it respects the sortOrder of other plugins.

#### DatasetSliceTrack

`DatasetSliceTrack` is a versatile track renderer class that allows for more
fine-grained control over the behavior and appearance of slice-based tracks.
It's the underlying component used by `createQuerySliceTrack` but offers a
richer set of customization options.

To use `DatasetSliceTrack`, you instantiate it with `DatasetSliceTrackAttrs`,
which include:

- `trace`: The `Trace` object.
- `uri`: A unique URI for the track.
- `dataset`: This is the core of the track's data. It's a `SourceDataset<T>` (or
  a function returning one) that defines the SQL query or table and the schema
  for the slices.
  - **Required columns**:
    - `id` (NUM): Unique identifier for each slice.
    - `ts` (LONG): Timestamp of the event (nanoseconds). This is the start time
      if `dur` is present, or the instant time otherwise.
  - **Optional columns**:
    - `dur` (LONG): Duration of the event (nanoseconds). If absent, slices are
      instant.
    - `depth` (NUM): Vertical arrangement of slices.
    - `layer` (NUM): Influences mipmap generation; higher layers render on top.
- `sliceLayout` (optional): An object to customize the geometry and layout of
  slices (e.g., `padding`, `rowHeight`).
- `instantStyle` (optional): An object to define custom rendering for instant
  events (those without a `dur`). It requires a `width` and a `render` function.
- `colorizer` (optional): A function `(row: T) => ColorScheme` to dynamically
  set the color of each slice based on its data.
- `sliceName` (optional): A function `(row: T) => string` to set the text
  displayed on each slice. Defaults to the `name` column in the dataset.
- `tooltip` (optional): A function `(slice: SliceWithRow<T>) => m.Children` to
  provide custom Mithril content for the tooltip when hovering over a slice.
- `detailsPanel` (optional): A function `(row: T) => TrackEventDetailsPanel` to
  define a custom details panel when a slice is selected.
- `fillRatio` (optional): A function `(row: T) => number` (between 0.0 and 1.0)
  to render a horizontal bar within the slice, useful for showing utilization or
  progress.
- `shellButtons` (optional): A function `() => m.Children` to add custom
  Mithril-based buttons to the track's shell.
- `initialMaxDepth` (optional): An estimate for the maximum depth to stabilize
  track height during initial load.
- `rootTableName` (optional): A base table name for ID namespace resolution.
- `forceTsRenderOrder` (optional): If true, forces rendering in timestamp order,
  which can be useful for tracks with many overlapping instant events,
  potentially at a small performance cost.

**Example:**

```ts
const trackUri = `${trace.pluginId}#MyCustomSliceTrack`;

// Define your dataset
const myDataset: SourceDataset<MySliceRow> = {
  name: 'my_custom_slices', // A descriptive name
  schema: {
    id: NUM,
    ts: LONG,
    name: STR,
    category: STR,
    dur: LONG, // Assuming your events have duration
    depth: NUM, // Assuming you want to control depth
  },
  query: `
    SELECT
      slice_id as id,
      ts,
      dur,
      depth,
      name,
      category
    FROM my_slice_table_or_view
  `,
};

const renderer = new DatasetSliceTrack<MySliceRow>({
  trace,
  uri: trackUri,
  dataset: myDataset,
  sliceName: (row) => `${row.category}: ${row.name}`,
  colorizer: (row) => {
    if (row.category === 'important') {
      return {background: '#FF0000', foreground: '#FFFFFF'}; // Red
    }
    return {background: '#0000FF', foreground: '#FFFFFF'}; // Blue
  },
  tooltip: (slice) => {
    return m('div', [
      m('div', `Name: ${slice.row.name}`),
      m('div', `Category: ${slice.row.category}`),
      m('div', `Duration: ${formatDuration(trace, slice.dur)}`),
    ]);
  },
  // Add other customizers like detailsPanel, fillRatio etc.
});

// Register the track renderer
trace.tracks.registerTrack({
  uri: trackUri,
  title: 'My Custom Slices',
  renderer,
});

// Add the track node to the workspace as normal
const trackNode = new TrackNode({
  uri: trackUri,
  title: 'My Custom Slices',
});
trace.workspace.addChildInOrder(trackNode);
```

This approach gives you significant flexibility in how your track data is
queried, processed, and displayed. Remember to consult the source code of
[`DatasetSliceTrack`](https://github.com/google/perfetto/blob/main/ui/src/components/tracks/dataset_slice_track.ts)
and related interfaces for the most up-to-date details and advanced usage
patterns.

### Timeline Overlays

Timeline overlays allow plugins to draw on top of the timeline, spanning
multiple tracks. This is useful for drawing annotations that show relationships
between different tracks, such as flow arrows or vertical lines marking
important events.

To create a timeline overlay, you need to implement the `Overlay` interface and
register it with the track manager.

```ts
import {Overlay, TrackBounds} from '../../public';

class MyOverlay implements Overlay {
  render(
    ctx: CanvasRenderingContext2D,
    timescale: TimeScale,
    size: Size2D,
    tracks: ReadonlyArray<TrackBounds>,
  ): void {
    // Drawing logic goes here
  }
}
```

The `render` method is called on every frame and provides the following
arguments:

- `ctx`: The `CanvasRenderingContext2D` for the overlay. This is the main tool
  for drawing shapes, lines, and text onto the canvas.
- `timescale`: A `TimeScale` object that helps convert between trace time and
  horizontal pixel coordinates. Use `timescale.timeToPx(time)` to find the x-
  coordinate for a given timestamp.
- `size`: A `Size2D` object containing the `width` and `height` of the entire
  overlay canvas.
- `tracks`: A `ReadonlyArray<TrackBounds>`. Each `TrackBounds` object contains
  the `node` for a visible track and its `verticalBounds` (the `top` and
  `bottom` y-coordinates of the track on the canvas). This array allows you to
  find the exact position of any track on the timeline, which is essential for
  drawing annotations that align with specific tracks.

Once you have your overlay class, register it in your plugin's `onTraceLoad`
method:

```ts
export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyPlugin';
  async onTraceLoad(trace: Trace) {
    trace.tracks.registerOverlay(new MyOverlay());
  }
}
```

A good example of a track overlay is the `WakerOverlay`, which draws arrows
between a thread's waker and the thread itself. You can find the source for this
in `ui/src/plugins/dev.perfetto.Sched/waker_overlay.ts`.

### Tabs

Tabs are a useful way to display contextual information about the trace, the
current selection, or to show the results of an operation.

To register a tab from a plugin, use the `Trace.registerTab` method.

```ts
class MyTab implements Tab {
  render(): m.Children {
    return m('div', 'Hello from my tab');
  }

  getTitle(): string {
    return 'My Tab';
  }
}

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyPlugin';
  async onTraceLoad(trace: Trace) {
    trace.registerTab({
      uri: `${trace.pluginId}#MyTab`,
      content: new MyTab(),
    });
  }
}
```

You'll need to pass in a tab-like object, something that implements the `Tab`
interface. Tabs only need to define their title and a render function which
specifies how to render the tab.

Registered tabs don't appear immediately - we need to show it first. All
registered tabs are displayed in the tab dropdown menu, and can be shown or
hidden by clicking on the entries in the drop down menu.

Tabs can also be hidden by clicking the little x in the top right of their
handle.

Alternatively, tabs may be shown or hidden programmatically using the tabs API.

```ts
trace.tabs.showTab(`${trace.pluginId}#MyTab`);
trace.tabs.hideTab(`${trace.pluginId}#MyTab`);
```

Tabs have the following properties:

- Each tab has a unique URI.
- Only once instance of the tab may be open at a time. Calling showTab multiple
  times with the same URI will only activate the tab, not add a new instance of
  the tab to the tab bar.

#### Ephemeral Tabs

By default, tabs are registered as 'permanent' tabs. These tabs have the
following additional properties:

- They appear in the tab dropdown.
- They remain once closed. The plugin controls the lifetime of the tab object.

Ephemeral tabs, by contrast, have the following properties:

- They do not appear in the tab dropdown.
- When they are hidden, they will be automatically unregistered.

Ephemeral tabs can be registered by setting the `isEphemeral` flag when
registering the tab.

```ts
trace.registerTab({
  isEphemeral: true,
  uri: `${trace.pluginId}#MyTab`,
  content: new MyEphemeralTab(),
});
```

Ephemeral tabs are usually added as a result of some user action, such as
running a command. Thus, it's common pattern to register a tab and show the tab
simultaneously.

Motivating example:

```ts
import m from 'mithril';
import {uuidv4} from '../../base/uuid';

class MyNameTab implements Tab {
  constructor(private name: string) {}
  render(): m.Children {
    return m('h1', `Hello, ${this.name}!`);
  }
  getTitle(): string {
    return 'My Name Tab';
  }
}

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyPlugin';
  async onTraceLoad(trace: Trace): Promise<void> {
    trace.registerCommand({
      id: `${trace.pluginId}#AddNewEphemeralTab`,
      name: 'Add new ephemeral tab',
      callback: () => handleCommand(trace),
    });
  }
}

function handleCommand(trace: Trace): void {
  const name = prompt('What is your name');
  if (name) {
    const uri = `${trace.pluginId}#MyName${uuidv4()}`;
    // This makes the tab available to perfetto
    ctx.registerTab({
      isEphemeral: true,
      uri,
      content: new MyNameTab(name),
    });

    // This opens the tab in the tab bar
    ctx.tabs.showTab(uri);
  }
}
```

### Sidebar Menu Items

Plugins can add new entries to the sidebar menu which appears on the left hand
side of the UI. These entries can include:

- Commands
- Links
- Arbitrary Callbacks

#### Commands

If a command is referenced, the command name and hotkey are displayed on the
sidebar item.

```ts
trace.commands.registerCommand({
  id: 'sayHi',
  name: 'Say hi',
  callback: () => window.alert('hi'),
  defaultHotkey: 'Shift+H',
});

trace.sidebar.addMenuItem({
  commandId: 'sayHi',
  section: 'support',
  icon: 'waving_hand',
});
```

#### Links

If an href is present, the sidebar will be used as a link. This can be an
internal link to a page, or an external link.

```ts
trace.sidebar.addMenuItem({
  section: 'navigation',
  text: 'Plugins',
  href: '#!/plugins',
});
```

#### Callbacks

Sidebar items can be instructed to execute arbitrary callbacks when the button
is clicked.

```ts
trace.sidebar.addMenuItem({
  section: 'current_trace',
  text: 'Copy secrets to clipboard',
  action: () => copyToClipboard('...'),
});
```

If the action returns a promise, the sidebar item will show a little spinner
animation until the promise returns.

```ts
trace.sidebar.addMenuItem({
  section: 'current_trace',
  text: 'Prepare the data...',
  action: () => new Promise((r) => setTimeout(r, 1000)),
});
```

Optional params for all types of sidebar items:

- `icon` - A material design icon to be displayed next to the sidebar menu item.
  See full list [here](https://fonts.google.com/icons).
- `tooltip` - Displayed on hover
- `section` - Where to place the menu item.
  - `navigation`
  - `current_trace`
  - `convert_trace`
  - `example_traces`
  - `support`
- `sortOrder` - The lower the sortOrder the higher the bar.

See the
[sidebar source](https://github.com/google/perfetto/blob/main/ui/src/public/sidebar.ts)
for more detailed usage.

### Pages

Pages are entities that can be routed via the URL args, and whose content take
up the entire available space to the right of the sidebar and underneath the
topbar. Examples of pages are the timeline, record page, and query page, just to
name a few common examples.

E.g.

```
http://ui.perfetto.dev/#!/viewer <-- 'viewer' is is the current page.
```

Pages are added from a plugin by calling the `pages.registerPage` function.

Pages may be registered with the trace or the app contexts. Pages registered
with the trace are automatically removed when switching traces. Traces
registered on the app will help will appear before a trace is loaded.

Traces registered with the app should be done so in `onActivate()`, while traces
registered with the trace should be done in `onTraceLoad()`.

A page is simply a render function which is called every Mithril render cycle
while that page is active. It should return the mithril components which will be
displayed within the page area. Within the render function, just render mithril
components as normal.

```ts
trace.pages.registerPage({
  route: '/mypage',
  render: () => m('', 'Hello from my page!'),
});
```

#### Subpage

The `render()` callback takes a single argument `subpage` which is an optional
string that is defined which defines the sub-route if present. E.g. anything
after the first `/` after the page `#!/<route>/<subpage>`. This can be used to
add additional sub-sections to your page.

Examples:

- [dev.perfetto.ExplorePage](https://github.com/google/perfetto/blob/main/ui/src/plugins/dev.perfetto.ExplorePage/index.ts).

### Statusbar

Plugins can add items to the statusbar, which is displayed at the bottom of the
UI.

To add a statusbar item from a plugin, use the `trace.statusbar.registerItem`
method.

```ts
trace.statusbar.registerItem({
  renderItem: () => ({
    label: 'My Statusbar Item',
    icon: 'settings',
    onclick: () => console.log('Statusbar item clicked'),
  }),
  popupContent: () => m('div', 'Hello from my statusbar item popup'),
});
```

The `renderItem` callback should return an object with the following properties:

- `label`: The text to display in the statusbar.
- `icon`: An optional material design icon to display next to the label.
- `intent`: An optional intent to change the color of the label.
- `onclick`: An optional callback to be called when the statusbar item is
  clicked.

The `popupContent` callback is optional and should return mithril content to be
displayed in a popup when the statusbar item is clicked.

- [core_plugins/flags_page/index.ts](https://github.com/google/perfetto/blob/main/ui/src/core_plugins/flags_page/index.ts).

### Omnibox Prompts

Plugins can leverage the omnibox to prompt users for input. This is more
integrated than a standard browser `window.prompt()` and can be used for
free-form text or selecting from a predefined list of choices. The
`OmniboxManager` is available via `app.omnibox` (in `onActivate`) or
`trace.omnibox` (in `onTraceLoad`).

The primary method is `prompt()`:

- `prompt(text: string): Promise<string | undefined>`: For free-form text input.
- `prompt(text: string, choices: ReadonlyArray<string>): Promise<string | undefined>`:
  For selecting from a simple list of strings.
- `prompt<T>(text: string, choices: PromptChoices<T>): Promise<T | undefined>`:
  For selecting from a list of custom objects.
  - `PromptChoices<T>` requires:
    - `values: ReadonlyArray<T>`: The array of objects.
    - `getName: (x: T) => string`: A function to get the display name for each
      object.

The promise resolves with the user's input/selection, or `undefined` if the user
dismisses the prompt (e.g., by pressing Escape).

**Examples:**

**1. Free-form input:**

```typescript
// In onActivate or onTraceLoad
// const appOrTrace: App | Trace = ...;

async function askForName(omnibox: OmniboxManager) {
  const name = await omnibox.prompt(
    'Enter a friendly name for the new marker:',
  );
  if (name) {
    console.log(`User entered: ${name}`);
    // Proceed with the name
  } else {
    console.log('User cancelled the prompt.');
  }
}

// To call it:
// askForName(appOrTrace.omnibox);
```

**2. Simple list of choices:**

```typescript
async function chooseColor(omnibox: OmniboxManager) {
  const color = await omnibox.prompt('Choose a highlight color:', [
    'red',
    'green',
    'blue',
    'yellow',
  ]);
  if (color) {
    console.log(`User chose: ${color}`);
    // Apply the color
  }
}

// chooseColor(appOrTrace.omnibox);
```

**3. List of custom objects:**

```typescript
interface ProcessChoice {
  pid: number;
  name: string;
  threadCount: number;
}

async function selectProcess(
  omnibox: OmniboxManager,
  processes: ProcessChoice[],
) {
  const selectedProcess = await omnibox.prompt<ProcessChoice>(
    'Select a process to focus on:',
    {
      values: processes,
      getName: (p) => `${p.name} (PID: ${p.pid}, Threads: ${p.threadCount})`,
    },
  );

  if (selectedProcess) {
    console.log(
      `User selected process: ${selectedProcess.name} (PID: ${selectedProcess.pid})`,
    );
    // Focus on the selected process
  }
}

// const exampleProcesses: ProcessChoice[] = [
//   {pid: 123, name: 'system_server', threadCount: 150},
//   {pid: 456, name: 'com.example.app', threadCount: 25},
// ];
// selectProcess(appOrTrace.omnibox, exampleProcesses);
```

This feature allows for creating interactive workflows directly within the
omnibox, guided by your plugin.

### Area Selection Tabs

Plugins can register tabs to be displayed in the details panel when an area of
the timeline is selected.

To register an area selection tab, use the
`trace.selection.registerAreaSelectionTab` method.

```ts
trace.selection.registerAreaSelectionTab({
  id: 'my-area-selection-tab',
  name: 'My Area Selection Tab',
  render: (selection) => {
    return m('div', `Selected area: ${selection.start} - ${selection.end}`);
  },
});
```

The `render` callback should return mithril content to be displayed in the tab.
The `selection` argument is an `AreaSelection` object, which contains
information about the selected area.

Examples:

- [dev.perfetto.TraceProcessorTrack/index.ts](https://github.com/google/perfetto/blob/main/ui/src/plugins/dev.perfetto.TraceProcessorTrack/index.ts).

### Metric Visualisations

TBD

Examples:

- [com.android.AndroidBinderViz](https://github.com/google/perfetto/blob/main/ui/src/plugins/com.android.AndroidBinderViz/index.ts).

### State

NOTE: It is important to consider version skew when using persistent state.

Plugins can persist information into permalinks. This allows plugins to
gracefully handle permalinking and is an opt-in - not automatic - mechanism.

Persistent plugin state works using a `Store<T>` where `T` is some JSON
serializable object. `Store` is implemented
[here](https://github.com/google/perfetto/blob/main/ui/src/base/store.ts).
`Store` allows for reading and writing `T`. Reading:

```typescript
interface Foo {
  bar: string;
}

const store: Store<Foo> = getFooStoreSomehow();

// store.state is immutable and must not be edited.
const foo = store.state.foo;
const bar = foo.bar;

console.log(bar);
```

Writing:

```typescript
interface Foo {
  bar: string;
}

const store: Store<Foo> = getFooStoreSomehow();

store.edit((draft) => {
  draft.foo.bar = 'Hello, world!';
});

console.log(store.state.foo.bar);
// > Hello, world!
```

First define an interface for your specific plugin state.

```typescript
interface MyState {
  favouriteSlices: MySliceInfo[];
}
```

To access permalink state, call `mountStore()` on your `Trace` object, passing
in a migration function.

```typescript
export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyPlugin';
  async onTraceLoad(trace: Trace): Promise<void> {
    const store = trace.mountStore(migrate);
  }
}

function migrate(initialState: unknown): MyState {
  // ...
}
```

When it comes to migration, there are two cases to consider:

- Loading a new trace
- Loading from a permalink

In case of a new trace, your migration function is called with `undefined`. In
this case you should return a default version of `MyState`:

```typescript
const DEFAULT = {favouriteSlices: []};

function migrate(initialState: unknown): MyState {
  if (initialState === undefined) {
    // Return default version of MyState.
    return DEFAULT;
  } else {
    // Migrate old version here.
  }
}
```

In the permalink case, your migration function is called with the state of the
plugin store at the time the permalink was generated. This may be from an older
or newer version of the plugin.

**Plugins must not make assumptions about the contents of `initialState`!**

In this case you need to carefully validate the state object. This could be
achieved in several ways, none of which are particularly straight forward. State
migration is difficult!

One brute force way would be to use a version number.

```typescript
interface MyState {
  version: number;
  favouriteSlices: MySliceInfo[];
}

const VERSION = 3;
const DEFAULT = {favouriteSlices: []};

function migrate(initialState: unknown): MyState {
  if (initialState && (initialState as {version: any}).version === VERSION) {
    // Version number checks out, assume the structure is correct.
    return initialState as State;
  } else {
    // Null, undefined, or bad version number - return default value.
    return DEFAULT;
  }
}
```

You'll need to remember to update your version number when making changes!
Migration should be unit-tested to ensure compatibility.

Examples:

- [dev.perfetto.ExampleState](https://github.com/google/perfetto/blob/main/ui/src/plugins/dev.perfetto.ExampleState/index.ts).

### Feature Flags

Plugins can register feature flags, which allow users to toggle experimental or
developmental features on or off. This is useful for rolling out new
functionality gradually or providing options for advanced users. Feature flags
are typically registered in the `onActivate` lifecycle hook using the
`app.featureFlags` manager.

To register a feature flag, you provide `FlagSettings`:

- `id` (string): A unique identifier for the flag (e.g.,
  "com.example.MyPlugin#myCoolFeature").
- `defaultValue` (boolean): The default state of the flag (true for on, false
  for off).
- `description` (string): A detailed description shown to the user in the UI
  (e.g., in the flags page).
- `name` (string, optional): A human-readable name for the flag. If omitted, the
  `id` is used.
- `devOnly` (boolean, optional): If true, the flag will only be visible in
  developer builds of Perfetto.

The `register` method returns a `Flag` object, which provides methods to
interact with the flag's state:

- `get(): boolean`: Returns the current value of the flag.
- `set(value: boolean)`: Overrides the flag's current value and persists it.
- `isOverridden(): boolean`: Checks if the flag's value has been manually
  changed from its default.
- `reset()`: Resets the flag to its `defaultValue`.
- `overriddenState(): OverrideState`: Returns the current override state
  (`DEFAULT`, `OVERRIDE_TRUE`, `OVERRIDE_FALSE`).

**Example:**

```typescript
import {App, Flag, FlagSettings} from '../../public'; // Adjust path as needed

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyFeatureFlagPlugin';
  private static myCoolFeatureFlag: Flag;

  static onActivate(app: App): void {
    const flagSettings: FlagSettings = {
      id: `${this.id}#myCoolFeature`,
      name: 'Enable My Cool Feature',
      defaultValue: false,
      description:
        'This flag enables a super cool experimental feature that does X, Y, and Z.',
      devOnly: true, // Optional: only for dev builds
    };
    this.myCoolFeatureFlag = app.featureFlags.register(flagSettings);

    // You can immediately check its state or use it to gate other registrations
    if (this.myCoolFeatureFlag.get()) {
      console.log('My Cool Feature is enabled!');
      // Register other components that depend on this flag
    }
  }

  async onTraceLoad(trace: Trace): Promise<void> {
    // Example of using the flag later
    if (MyFeatureFlagPlugin.myCoolFeatureFlag.get()) {
      // Add tracks or tabs related to this feature
      trace.sidebar.addMenuItem({
        section: 'current_trace',
        text: 'Cool Feature Action',
        action: () => alert('Cool feature activated!'),
      });
    }
  }
}
```

Users can typically manage these flags through a dedicated "Flags" page in the
Perfetto UI, where they can see descriptions and toggle them.

### Custom Settings

Plugins can define and register their own settings, allowing users to customize
plugin behavior. These settings are managed through the `SettingsManager`,
available via `app.settings` (typically in `onActivate`) or `trace.settings`.
Registered settings appear in the main Perfetto settings page.

To register a setting, you provide a `SettingDescriptor<T>`:

- `id` (string): A unique identifier for the setting (e.g.,
  "com.example.MyPlugin#myCustomPreference"). This is also used as the storage
  key.
- `name` (string): A human-readable name displayed in the settings UI.
- `description` (string): A detailed explanation of what the setting does.
- `schema` (`z.ZodType<T>`): A [Zod](https://zod.dev/) schema that defines the
  type and validation rules for the setting's value. This is crucial for
  ensuring type safety and data integrity.
- `defaultValue` (T): The value the setting will have if not explicitly set by
  the user.
- `requiresReload` (boolean, optional): If `true`, the user will be prompted to
  reload the Perfetto UI when this setting is changed, as its effect might only
  apply on startup.
- `render` (`SettingRenderer<T>`, optional): A function
  `(setting: Setting<T>) => m.Children` that returns Mithril content to render a
  custom UI for this setting in the settings page. This is particularly useful
  for non-primitive types (objects, arrays) or when a more specialized input
  control is needed (e.g., a slider, a custom dropdown). If not provided, a
  default UI based on the schema type (e.g., checkbox for boolean, text input
  for string/number) will be attempted.

The `settings.register()` method returns a `Setting<T>` object, which extends
the descriptor and provides methods to interact with the setting:

- `get(): T`: Retrieves the current value of the setting.
- `set(value: T)`: Sets a new value for the setting. The value will be validated
  against the schema.
- `reset()`: Reverts the setting to its `defaultValue`.
- `isDefault: boolean`: A read-only property indicating if the setting is
  currently at its default value.

**Example:**

```typescript
import {App, Setting, SettingDescriptor} from '../../public'; // Adjust path
import {z} from 'zod';
import m from 'mithril';

// Define a Zod schema for a complex setting
const MyComplexObjectSchema = z.object({
  optionA: z.string().min(1),
  optionB: z.number().int().positive(),
});
type MyComplexObject = z.infer<typeof MyComplexObjectSchema>;

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MySettingsPlugin';
  private static simpleBooleanSetting: Setting<boolean>;
  private static complexObjectSetting: Setting<MyComplexObject>;

  static onActivate(app: App): void {
    // 1. A simple boolean setting
    const boolSettingDesc: SettingDescriptor<boolean> = {
      id: `${this.id}#enableSimpleFeature`,
      name: 'Enable Simple Feature',
      description: 'Toggles a basic feature on or off.',
      schema: z.boolean(),
      defaultValue: true,
      requiresReload: false,
    };
    this.simpleBooleanSetting = app.settings.register(boolSettingDesc);

    // 2. A more complex object-based setting with a custom renderer
    const complexSettingDesc: SettingDescriptor<MyComplexObject> = {
      id: `${this.id}#complexConfig`,
      name: 'Complex Configuration',
      description: 'Configure advanced options A and B.',
      schema: MyComplexObjectSchema,
      defaultValue: {optionA: 'defaultA', optionB: 10},
      render: (setting: Setting<MyComplexObject>) => {
        const currentValue = setting.get();
        return m('div.custom-setting-container', [
          m('label', 'Option A:'),
          m('input[type=text]', {
            value: currentValue.optionA,
            oninput: (e: Event) => {
              const target = e.target as HTMLInputElement;
              setting.set({...currentValue, optionA: target.value});
            },
          }),
          m('label', 'Option B (number):'),
          m('input[type=number]', {
            value: currentValue.optionB,
            oninput: (e: Event) => {
              const target = e.target as HTMLInputElement;
              setting.set({
                ...currentValue,
                optionB: parseInt(target.value, 10) || 0,
              });
            },
          }),
          m('button', {onclick: () => setting.reset()}, 'Reset to Default'),
          setting.isDefault ? m('span', ' (Default)') : null,
        ]);
      },
    };
    this.complexObjectSetting = app.settings.register(complexSettingDesc);

    // Using the setting value
    if (this.simpleBooleanSetting.get()) {
      console.log('Simple feature is ON');
    }
    const complexConf = this.complexObjectSetting.get();
    console.log(
      `Complex config: A=${complexConf.optionA}, B=${complexConf.optionB}`,
    );
  }

  // ... other plugin methods
}
```

Using Zod schemas ensures that settings are type-safe and validated, preventing
invalid data from being stored. Custom renderers provide a powerful way to
create intuitive UIs for complex settings.

Examples:

- https://github.com/google/perfetto/blob/main/ui/src/plugins/com.example.Settings/index.ts

### Logging Analytics and Errors

Plugins can contribute to Perfetto's internal analytics by logging custom events
and errors. This helps in understanding feature usage and identifying issues.
The analytics interface is available via `app.analytics` (in `onActivate`) or
`trace.analytics` (in `onTraceLoad`).

The `Analytics` interface provides the following methods:

- `logEvent(category: TraceCategories | null, event: string): void`: Logs a
  specific event.
  - `category`: Can be one of the predefined `TraceCategories` (e.g.,
    `'Trace Actions'`, `'Record Trace'`, `'User Actions'`) or `null` for general
    plugin events. It's recommended to use `null` or a very specific event
    string if your plugin's actions don't fit predefined categories, to avoid
    polluting general metrics.
  - `event`: A string describing the event (e.g., "MyPlugin:FeatureUsed",
    "MyPlugin:SpecificActionCompleted").
- `logError(err: ErrorDetails): void`: Logs an error.
  - `err`: An `ErrorDetails` object, which typically includes an error message,
    and can include a stack trace or other context.
- `isEnabled(): boolean`: Checks if analytics logging is currently enabled.
  Plugins should respect this and avoid logging if it returns `false`.

**Example:**

```typescript
import {App, Trace, Analytics, ErrorDetails} from '../../public'; // Adjust path

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyAnalyticsPlugin';

  static onActivate(app: App): void {
    if (app.analytics.isEnabled()) {
      app.analytics.logEvent(null, `${this.id}:Activated`);
    }
  }

  async onTraceLoad(trace: Trace): Promise<void> {
    if (trace.analytics.isEnabled()) {
      trace.analytics.logEvent('User Actions', `${this.id}:TraceLoaded`);
    }

    // Example of logging a custom action
    this.performSomeAction(trace.analytics);
  }

  private performSomeAction(analytics: Analytics) {
    try {
      // ... some plugin logic ...
      if (analytics.isEnabled()) {
        analytics.logEvent(null, `${MyAnalyticsPlugin.id}:SomeActionSuccess`);
      }
    } catch (e) {
      if (analytics.isEnabled()) {
        const errorDetails: ErrorDetails = {
          message: `Error in ${MyAnalyticsPlugin.id}.performSomeAction: ${
            (e as Error).message
          }`,
          stack: (e as Error).stack,
        };
        analytics.logError(errorDetails);
      }
      // Optionally re-throw or handle the error
    }
  }
}
```

By using the provided analytics interface, plugins can integrate their telemetry
with the main application in a consistent way.

### Adding Timeline Notes and Spans

Plugins can add visual markers (notes) and highlighted time ranges (span notes)
directly onto the timeline. This is useful for drawing attention to specific
points or durations based on plugin-specific logic or user actions. The
`NoteManager` is available via `trace.notes` within the `onTraceLoad` hook or
any context where the `Trace` object is accessible.

**Key Interfaces:**

- `Note`: Represents a single point-in-time marker on the timeline.
  - `timestamp` (`time`): The exact time for the note.
  - `color` (string, optional): Color of the note marker. Defaults to a random
    color.
  - `text` (string, optional): Text displayed when hovering over the note.
  - `id` (string, optional): A unique ID. If provided, can be used to update an
    existing note. Auto-assigned if omitted.
- `SpanNote`: Represents a highlighted time range.
  - `start` (`time`): The start time of the span.
  - `end` (`time`): The end time of the span.
  - `color`, `text`, `id`: Same as for `Note`.

**Using the `NoteManager`:**

- `trace.notes.addNote(args: AddNoteArgs): string`: Adds a point note to the
  timeline and returns its ID.
- `trace.notes.addSpanNote(args: AddSpanNoteArgs): string`: Adds a span note to
  the timeline and returns its ID.
- `trace.notes.getNote(id: string): Note | SpanNote | undefined`: Retrieves a
  previously added note or span note by its ID.

**Example:**

```typescript
import {Trace, time} from '../../public'; // Adjust path as needed

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyTimelineNotesPlugin';

  async onTraceLoad(trace: Trace): Promise<void> {
    // Example: Add a point note at 10 seconds into the trace
    const noteId = trace.notes.addNote({
      timestamp: time.fromSeconds(10),
      text: 'Interesting event occurred here!',
      color: '#FF00FF', // Magenta
    });
    console.log(`Added note with ID: ${noteId}`);

    // Example: Add a span note from 15s to 20s
    const spanNoteId = trace.notes.addSpanNote({
      start: time.fromSeconds(15),
      end: time.fromSeconds(20),
      text: 'Critical duration under investigation',
      color: 'rgba(255, 165, 0, 0.5)', // Orange, semi-transparent
    });
    console.log(`Added span note with ID: ${spanNoteId}`);

    // Later, you could retrieve a note if needed
    const retrievedNote = trace.notes.getNote(noteId);
    if (retrievedNote) {
      console.log('Retrieved note text:', retrievedNote.text);
    }
  }
}
```

These notes are visually represented on the timeline's marker track, providing a
way for plugins to annotate the trace dynamically.

### Controlling the Minimap

Plugins can provide custom data to be displayed on the global timeline minimap.
This allows visualization of high-level overviews of plugin-specific data across
the entire trace duration. The `MinimapManager` is available via `trace.minimap`
within the `onTraceLoad` hook.

To contribute content, a plugin must register a `MinimapContentProvider`:

- `priority` (number): If multiple plugins provide minimap providers, the one
  with the highest priority wins and takes full control over the minimap.
- `getData(timeSpan: HighPrecisionTimeSpan, resolution: duration): Promise<MinimapRow[]>`:
  A function called by the UI to fetch minimap data for a given `timeSpan` at a
  specific `resolution`.
  - It should return a Promise that resolves to an array of `MinimapRow`.
  - Each `MinimapRow` is an array of `MinimapCell` objects.
  - Each `MinimapCell` defines:
    - `ts` (`time`): The start timestamp of the cell.
    - `dur` (`duration`): The duration this cell covers.
    - `load` (number): A normalized value (0.0 to 1.0) representing the
      intensity or utilization for this cell. This value is used by the UI to
      render the cell's visual representation (e.g., color intensity).

**Using the `MinimapManager`:**

- `trace.minimap.registerContentProvider(provider: MinimapContentProvider): void`:
  Registers your custom provider.

**Example:**

```typescript
import {
  Trace,
  MinimapContentProvider,
  MinimapRow,
  MinimapCell,
  HighPrecisionTimeSpan,
  duration,
  time,
} from '../../public'; // Adjust path

class MyMinimapDataProvider implements MinimapContentProvider {
  readonly priority = 10; // Example priority

  async getData(
    timeSpan: HighPrecisionTimeSpan,
    resolution: duration,
  ): Promise<MinimapRow[]> {
    // In a real implementation, you would query Trace Processor or use other
    // plugin data sources to generate cells based on the timeSpan and resolution.
    // This example generates a single row with some dummy data.

    const cells: MinimapCell[] = [];
    let currentTs = timeSpan.start;
    const step = resolution; // Use the provided resolution as step

    while (currentTs < timeSpan.end) {
      const cellEnd = time.add(currentTs, step);
      cells.push({
        ts: currentTs,
        dur: step,
        // Generate some load, e.g., based on activity in your plugin's data
        load: Math.random(), // Replace with actual data calculation
      });
      currentTs = cellEnd;
      if (cells.length > 1000) break; // Safety break for dummy data
    }

    // Plugins can return multiple rows if they want to represent different
    // layers or types of data in the minimap.
    return [cells];
  }
}

export default class implements PerfettoPlugin {
  static readonly id = 'com.example.MyMinimapPlugin';

  async onTraceLoad(trace: Trace): Promise<void> {
    const provider = new MyMinimapDataProvider();
    trace.minimap.registerContentProvider(provider);
    console.log('MyMinimapDataProvider registered.');
  }
}
```

The UI will then call the `getData` method of registered providers as needed
when the minimap needs to be redrawn, allowing plugins to contribute dynamic,
trace-wide overviews.

### Plugin Dependencies

Plugins can declare dependencies on other plugins. This ensures that the
dependent plugins are loaded and available before the current plugin is
activated and loaded. This is useful when a plugin needs to extend or utilize
functionality provided by another plugin.

**Declaring Dependencies:**

A plugin declares its dependencies via a static `dependencies` array in its
class definition. This array should contain direct references to the static
classes of the plugins it depends on.

```typescript
// plugin-a.ts
import {PerfettoPlugin, PerfettoPluginStatic, App, Trace} from '../../public';

export default class PluginA implements PerfettoPlugin {
  static readonly id = 'com.example.PluginA';
  // ...
  doSomething(): string {
    return 'Data from Plugin A';
  }
}

// plugin-b.ts
import {PerfettoPlugin, PerfettoPluginStatic, App, Trace} from '../../public';
import PluginA from './plugin-a'; // Import the static class

export default class PluginB implements PerfettoPlugin {
  static readonly id = 'com.example.PluginB';
  static readonly dependencies = [PluginA]; // Declare PluginA as a dependency

  private pluginAInstance?: PluginA;

  async onTraceLoad(ctx: Trace): Promise<void> {
    // Get an instance of the dependency
    this.pluginAInstance = ctx.plugins.getPlugin(PluginA);

    if (this.pluginAInstance) {
      const dataFromA = this.pluginAInstance.doSomething();
      console.log(`${PluginB.id} received: ${dataFromA}`);
      // Use dataFromA or other methods from pluginAInstance
    } else {
      console.error(`${PluginB.id} could not get instance of ${PluginA.id}`);
    }
  }
}
```

**Accessing Dependencies:**

Once a plugin is loaded (e.g., within `onActivate` or `onTraceLoad`), it can get
an instance of a declared dependency using the `plugins.getPlugin()` method
available on the `App` or `Trace` context object. You pass the static class of
the dependency to this method.

- `app.plugins.getPlugin<T extends PerfettoPlugin>(plugin: PerfettoPluginStatic<T>): T`
- `trace.plugins.getPlugin<T extends PerfettoPlugin>(plugin: PerfettoPluginStatic<T>): T`

The core ensures that `onActivate` and `onTraceLoad` for dependencies are called
before they are called for the dependent plugin. If a dependency cannot be
loaded, the dependent plugin might not load or might receive `undefined` when
trying to get the plugin instance.

**Example:**

The
[`dev.perfetto.TraceProcessorTrack`](https://github.com/google/perfetto/blob/main/ui/src/plugins/dev.perfetto.TraceProcessorTrack/index.ts)
plugin depends on `ProcessThreadGroupsPlugin` and `StandardGroupsPlugin` to
organize tracks under appropriate process, thread, or standard groups.

```typescript
// From ui/src/plugins/dev.perfetto.TraceProcessorTrack/index.ts
import ProcessThreadGroupsPlugin from '../dev.perfetto.ProcessThreadGroups';
import StandardGroupsPlugin from '../dev.perfetto.StandardGroups';
// ...

export default class TraceProcessorTrackPlugin implements PerfettoPlugin {
  static readonly id = 'dev.perfetto.TraceProcessorTrack';
  static readonly dependencies = [
    ProcessThreadGroupsPlugin,
    StandardGroupsPlugin,
  ];

  // ...
  private addTrack(
    ctx: Trace,
    // ...
  ) {
    // ...
    const processGroupPlugin = ctx.plugins.getPlugin(ProcessThreadGroupsPlugin);
    const standardGroupPlugin = ctx.plugins.getPlugin(StandardGroupsPlugin);
    // Use instances of processGroupPlugin and standardGroupPlugin...
  }
}
```

By declaring dependencies, plugins can build upon each other, creating a more
modular and extensible system.

## Default plugins

Some plugins are enabled by default. These plugins are held to a higher quality
than non-default plugins since changes to those plugins effect all users of the
UI. The list of default plugins is specified at
[ui/src/core/default_plugins.ts](https://github.com/google/perfetto/blob/main/ui/src/core/default_plugins.ts).

In particular the startup time of your plugin will be scrutinized and your
plugin may be disabled by default if it has a significant impact on users who
aren't using your plugin's features. To see a list of plugins and their startup
times, visit the [plugins page](https://ui.perfetto.dev/#!/plugins) and sort
plugins by their startup time.

The majority of default plugins are Android and Chrome related due to the
lineage of the Perfetto project, ui.perfetto.dev is mostly to server the Android
and Chrome telemetry teams.

## Misc notes

- Plugins must be licensed under
  [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) the same as all other
  code in the repository.
- Plugins
