PhoenixExRatatui.Telemetry (PhoenixExRatatui v0.1.0)

Copy Markdown View Source

:telemetry integration for phoenix_ex_ratatui.

Mirrors the shape of ExRatatui.Telemetry one layer up — events fire at the boundaries this package controls (LiveView mount, frame push, client input forward, Transport shutdown) rather than at the runtime / session layer ex_ratatui already instruments. Both fire concurrently when a Phoenix-driven TUI is running, and consumers attach handlers to whichever they need.

Why a separate event tree

ex_ratatui measures the App / runtime layer: [:ex_ratatui, :runtime, :event], [:ex_ratatui, :render, :frame], [:ex_ratatui, :session, :lifecycle, *], and so on. Those events fire from inside ExRatatui.Server regardless of transport.

phoenix_ex_ratatui adds events for the Phoenix-side cost:

  • mount + Transport boot (network handshake, App mount, first take_cells_diff/1 returning the full grid)
  • the per-frame work the LiveView itself does on top of the runtime: encoding the diff to JSON, calling push_event/3, pushing over the WebSocket
  • client input being decoded and forwarded into the runtime
  • Transport teardown

Attaching handlers to BOTH event trees gives a complete profile of a Phoenix-driven TUI without double-counting any single operation.

Events

All events are prefixed with :phoenix_ex_ratatui.

Span events (:start / :stop / :exception)

Each span emits three events with the suffix appended. Handlers typically attach to :stop for timing and :exception for failure tracking.

EventDescriptionMetadata
[:phoenix_ex_ratatui, :transport, :connect]PhoenixExRatatui.Transport.start_link/1 — constructs CellSession, boots ExRatatui.Server, runs mount/1, ships first frame.:mod, :width, :height, :target
[:phoenix_ex_ratatui, :render, :frame]Per-frame Phoenix-side work: Renderer.Html.encode_diff/1 + Phoenix.LiveView.push_event/3.:mod, :width, :height, :ops_count

:start events carry %{monotonic_time: integer, system_time: integer} as measurements. :stop events add :duration (native units). On exception the metadata gains :kind, :reason, and :stacktrace.

Single events

EventDescriptionMeasurementsMetadata
[:phoenix_ex_ratatui, :transport, :disconnect]Transport.stop/2 was called and the runtime server is being torn down. Does not fire on linked-process EXIT — ex_ratatui's own [:ex_ratatui, :transport, :disconnect] covers that path.%{system_time: integer}:mod, :reason
[:phoenix_ex_ratatui, :input, :forward]A decoded client input is forwarded to the runtime via Transport.push_event/2.%{system_time: integer}:mod, :event
[:phoenix_ex_ratatui, :intent, :dispatch]A runtime intent was dispatched to the LV/LC socket (e.g. {:navigate, "/path"}push_navigate). Fires once per intent, regardless of recognised vs unrecognised.%{system_time: integer}:intent

Attaching a default logger

# In Application.start/2 (or iex during dev):
PhoenixExRatatui.Telemetry.attach_default_logger()

That attaches a handler logging every :stop and single event at :debug level. Pass attach_default_logger(level: :info) to bump the level. Detach with detach_default_logger/0.

Real apps wire Telemetry.Metrics instead — define metrics in a MyApp.Telemetry module and they show up in the LiveDashboard's Metrics tab automatically. Example:

defmodule MyApp.Telemetry do
  import Telemetry.Metrics

  def metrics do
    [
      summary("phoenix_ex_ratatui.transport.connect.stop.duration",
        unit: {:native, :millisecond}),
      counter("phoenix_ex_ratatui.transport.disconnect"),
      summary("phoenix_ex_ratatui.render.frame.stop.duration",
        unit: {:native, :microsecond}),
      counter("phoenix_ex_ratatui.input.forward")
    ]
  end
end

Summary

Functions

Attaches a logger that prints every phoenix_ex_ratatui telemetry event. Useful during development; detach with detach_default_logger/0.

Detaches the default logger previously attached with attach_default_logger/1.

Emits a single :telemetry event rooted at [:phoenix_ex_ratatui | event].

Wraps fun in a :telemetry span rooted at [:phoenix_ex_ratatui | event].

Functions

attach_default_logger(opts \\ [])

@spec attach_default_logger(keyword()) :: :ok | {:error, :already_exists}

Attaches a logger that prints every phoenix_ex_ratatui telemetry event. Useful during development; detach with detach_default_logger/0.

Options

  • :level — log level (default: :debug).
  • :events — list of event suffixes to attach (default: all :stop and single events).

detach_default_logger()

@spec detach_default_logger() :: :ok | {:error, :not_found}

Detaches the default logger previously attached with attach_default_logger/1.

execute(event, measurements, meta)

@spec execute([atom(), ...], map(), map()) :: :ok

Emits a single :telemetry event rooted at [:phoenix_ex_ratatui | event].

:system_time is added to the measurements automatically if not already present.

span(event, meta, fun)

@spec span([atom(), ...], map(), (-> term())) :: term()

Wraps fun in a :telemetry span rooted at [:phoenix_ex_ratatui | event].

The fun's return value is returned unchanged. The given meta is forwarded to both the :start and :stop events.