ObserverWeb.Tracer.Tool.FlameGraph (Observer Web v0.2.8)

View Source

Tracks how much time each process spends in every call stack it goes through, and reports it as a plain %{name:, value:, children:} tree (one root per traced process) that the Profiling page renders as a flame graph client-side with the FlameGraphEChart hook (an ECharts custom series: one rect per call, width proportional to time spent, stacked under its caller).

Ported and adapted from https://github.com/gabiz/tracer's Tracer.Tool.FlameGraph:

  • Unlike Count/Duration/CallSeq, this traces every call in the traced module(s) (no match-spec filtering) - a flame graph needs the full call graph to be meaningful. This is why ObserverWeb.Tracer.Tool.dbg_flags/1 adds :return_to for this tool instead of a match-spec action: it unwinds the stack on return without needing return_trace() per function.
  • Drops upstream's synthetic "sleep" frame (driven by the :running trace flag's :in/:out scheduling events). ObserverWeb.Tracer.Server enables trace flags for all processes on the node (:dbg.p(:all, ...)), not just the ones executing traced code - :running isn't scoped by a match spec at all, so turning it on here would generate scheduling events for every process in the whole VM, not just the one(s) calling into the traced module. That's both noisy and a real performance/safety risk on a live system, so this only tracks active call-stack time, not idle time.
  • Upstream shells out to a bundled Perl script and writes to /tmp to render a literal flame graph SVG. Rendering client-side with the echarts dependency the project already has means no external-process/filesystem dependency and no new JS packages.
  • Caps how deep a single process's stack is tracked (not user-configurable), to keep runaway recursion from growing memory unbounded.

Summary

Functions

Finalizes into a list of chart-ready root nodes, one per traced process (%{name:, value:, children:}), sorted by total time descending. Processes with no completed samples are dropped. Roots are named by the process's registered name when it has one (see ObserverWeb.Tracer.Tool.process_label/1), the pid otherwise.

Types

t()

@type t() :: %ObserverWeb.Tracer.Tool.FlameGraph{process_state: map()}

Functions

handle_event(state, event)

@spec handle_event(
  t(),
  struct()
) :: t()

handle_stop(flame_graph)

@spec handle_stop(t()) :: [map()]

Finalizes into a list of chart-ready root nodes, one per traced process (%{name:, value:, children:}), sorted by total time descending. Processes with no completed samples are dropped. Roots are named by the process's registered name when it has one (see ObserverWeb.Tracer.Tool.process_label/1), the pid otherwise.

new()

@spec new() :: t()