ObserverWeb.Tracer.Tool (Observer Web v0.2.7)

View Source

Dispatches raw :dbg trace events to the active tool's aggregation logic.

This intentionally does not port tracer's use Tracer.Tool probe/agent_opts plumbing (see https://github.com/gabiz/tracer) - session management (timeouts, max message caps, multi-node dispatch) is already handled by ObserverWeb.Tracer.Server, so only the per-tool init/handle_event/handle_stop aggregation logic is ported.

Summary

Functions

:dbg trace flags required to run the given tool (always includes :c and :timestamp).

Match spec keys forced onto every traced function for this tool, regardless of what's selected in the UI (the Profiling page has no match-spec picker of its own - see Observer.Web.Profiling.Page). :duration needs return_trace() to see :return_from events. :call_seq needs both return_trace() and argument capture, combined into the single call_seq match spec - see ObserverWeb.Tracer.get_default_functions_matchspecs/0 for why selecting both return_trace and capture_args separately wouldn't work. :flame_graph needs no match spec at all - it relies purely on the :return_to dbg flag to unwind stacks, and traces every call in the selected module(s) rather than specific functions.

Translates a raw :dbg trace message into an event struct and folds it into the tool's state.

Finalizes the tool's state into the report sent back to the requesting LiveView.

Builds the initial aggregation state for the given tool.

Whether this tool needs LOCAL call tracing (:dbg.tpl/4) instead of the default global call tracing (:dbg.tp/4). Global tracing never emits :return_to events at all (regardless of the :return_to dbg flag) and also misses calls between functions in the same traced module, so :flame_graph - which needs both - requires local tracing.

Human-readable label for a traced process, resolved with the same fallback chain etop uses: the registered name when it has one, otherwise the Process.set_label/1 process label, otherwise the proc_lib initial call (how GenServers, Supervisors and Tasks identify themselves) suffixed with the pid to keep concurrent instances of the same module apart, and finally the inspected pid alone.

Types

t()

@type t() :: :display | :count | :duration | :call_seq | :flame_graph

Functions

dbg_flags(atom)

@spec dbg_flags(t()) :: [atom()]

:dbg trace flags required to run the given tool (always includes :c and :timestamp).

:display needs full call argument values for its live log, so it's traced without :arity (the raw event's {mod, fun, _} element holds the argument list). Every other tool aggregates by {mod, fun, arity}, so :arity is requested to get the integer directly instead of a list of argument values. :flame_graph additionally needs :return_to to unwind the stack without a match spec per function (see ObserverWeb.Tracer.Tool.FlameGraph for why :running isn't used here despite upstream using it).

forced_match_spec_keys(arg1)

@spec forced_match_spec_keys(t()) :: [String.t()]

Match spec keys forced onto every traced function for this tool, regardless of what's selected in the UI (the Profiling page has no match-spec picker of its own - see Observer.Web.Profiling.Page). :duration needs return_trace() to see :return_from events. :call_seq needs both return_trace() and argument capture, combined into the single call_seq match spec - see ObserverWeb.Tracer.get_default_functions_matchspecs/0 for why selecting both return_trace and capture_args separately wouldn't work. :flame_graph needs no match spec at all - it relies purely on the :return_to dbg flag to unwind stacks, and traces every call in the selected module(s) rather than specific functions.

handle_event(atom, trace_ms, state)

@spec handle_event(t(), tuple(), term()) :: term()

Translates a raw :dbg trace message into an event struct and folds it into the tool's state.

handle_stop(atom, state)

@spec handle_stop(t(), term()) :: term()

Finalizes the tool's state into the report sent back to the requesting LiveView.

init(atom, opts)

@spec init(t(), map()) :: term()

Builds the initial aggregation state for the given tool.

local_tracing?(arg1)

@spec local_tracing?(t()) :: boolean()

Whether this tool needs LOCAL call tracing (:dbg.tpl/4) instead of the default global call tracing (:dbg.tp/4). Global tracing never emits :return_to events at all (regardless of the :return_to dbg flag) and also misses calls between functions in the same traced module, so :flame_graph - which needs both - requires local tracing.

process_label(pid)

@spec process_label(pid()) :: String.t()

Human-readable label for a traced process, resolved with the same fallback chain etop uses: the registered name when it has one, otherwise the Process.set_label/1 process label, otherwise the proc_lib initial call (how GenServers, Supervisors and Tasks identify themselves) suffixed with the pid to keep concurrent instances of the same module apart, and finally the inspected pid alone.

Works for local and remote pids (ObserverWeb.Rpc.pinfo/2 is location transparent) - most traced processes on a remote node aren't locally registered (Registry/:via registrations don't set :registered_name), so the fallbacks are what keep multi-node reports readable. Falls back to the pid when the process has already died by the time the report is built - common for short-lived traced processes.