Experimental
This API may change in any 0.0.x release. Changes are listed in the CHANGELOG.
The behaviour every toolbar panel implements, the built-ins included (ADR 05).
A plugin collects events from :telemetry inside the host's processes and,
in the panel, folds them into summary badges (summary_init/1,
summary_add/2, badges/1) and shows them in its own tab
(panel/0, see PhoenixDevToolbar.Panel). Register plugins in config/dev.exs:
config :phoenix_dev_toolbar,
plugins: [:defaults, {MyApp.Toolbar.Jobs, queues: [:default]}]:defaults expands to the built-ins (Ecto, Request, LiveView, Process, System). Listing a
built-in with options overrides it; {:exclude, Module} removes one. An
invalid entry is logged and skipped: the host application always boots.
Example
defmodule MyApp.Toolbar.Jobs do
use PhoenixDevToolbar.Plugin, id: :jobs, name: "Jobs"
alias PhoenixDevToolbar.{Context, Event}
@impl PhoenixDevToolbar.Plugin
def init(opts), do: {:ok, %{queues: Keyword.get(opts, :queues, :all)}}
@impl PhoenixDevToolbar.Plugin
def telemetry_events(_config), do: [[:oban, :engine, :insert_job, :stop]]
@impl PhoenixDevToolbar.Plugin
def collect(_event, {measurements, metadata}, %Context{}) do
data = %{worker: metadata.job.worker}
{:record, Event.new(:jobs, :inserted, data, duration: measurements.duration)}
end
endWhere the code runs
init/1 runs once, when the toolbar attaches its handlers. collect/3 runs
inside the host process that emitted the event (a request, a LiveView,
a Repo caller), and only for processes the toolbar tracks. So it must be
cheap and pure:
- never call another process synchronously, never do I/O
- bound everything it keeps:
inspect/2limits, never whole structs - never create atoms from runtime data
A collect/3 that raises, throws or exits is disabled (quarantined) and the
error is logged once; the other plugins keep working.
The behaviour is unstable before 1.0 (see the note at the top).
Summary
Types
A badge of the summary bar, shown even when the panel is collapsed. id
becomes the DOM id pdt-badge-<id>, unique in the whole panel: start it
with your plugin's id. title is the tooltip.
What init/1 returns: handed to every other callback.
Callbacks
The summary bar badges for the summary, in display order.
Turns one telemetry event into a recorded event, or skips it. Runs inside the
emitting host process: cheap, pure, never raises. context.config is the
plugin's config.
A unique id, stored in every event the plugin records (Event.plugin).
Validates the options given in the config and returns the plugin's config.
Runs once, in the toolbar's own process. Defaults to {:ok, opts}.
The tab label in the panel.
The plugin's tab: a module that does use PhoenixDevToolbar.Panel. A plugin
without it collects events and shows badges only.
Folds one of the plugin's events into its summary. Pure and cheap.
The initial state of the plugin's summary for a page, folded by
summary_add/2 in the panel process, event by event: it survives the
oldest events being trimmed from the buffer.
The :telemetry events to attach to.
Functions
Sets the behaviour and defines id/0, name/0 and a default init/1.
Types
@type badge() :: %{ :id => String.t(), :text => String.t(), :level => :ok | :info | :warn | :error, optional(:title) => String.t() }
A badge of the summary bar, shown even when the panel is collapsed. id
becomes the DOM id pdt-badge-<id>, unique in the whole panel: start it
with your plugin's id. title is the tooltip.
@type config() :: term()
What init/1 returns: handed to every other callback.
Callbacks
The summary bar badges for the summary, in display order.
@callback collect( :telemetry.event_name(), {measurements :: map(), metadata :: map()}, PhoenixDevToolbar.Context.t() ) :: {:record, PhoenixDevToolbar.Event.t()} | :skip
Turns one telemetry event into a recorded event, or skips it. Runs inside the
emitting host process: cheap, pure, never raises. context.config is the
plugin's config.
@callback id() :: atom()
A unique id, stored in every event the plugin records (Event.plugin).
Validates the options given in the config and returns the plugin's config.
Runs once, in the toolbar's own process. Defaults to {:ok, opts}.
@callback name() :: String.t()
The tab label in the panel.
@callback panel() :: module()
The plugin's tab: a module that does use PhoenixDevToolbar.Panel. A plugin
without it collects events and shows badges only.
@callback summary_add(summary :: term(), PhoenixDevToolbar.Event.t()) :: term()
Folds one of the plugin's events into its summary. Pure and cheap.
The initial state of the plugin's summary for a page, folded by
summary_add/2 in the panel process, event by event: it survives the
oldest events being trimmed from the buffer.
@callback telemetry_events(config()) :: [:telemetry.event_name()]
The :telemetry events to attach to.