Ascii.Telemetry (Ascii v0.3.0)

Copy Markdown View Source

Your app's :telemetry events as live data for the pieces: a process that keeps a reading of each metric a sample at a time, for a sparkline's series, a gauge's needle or a progress bar.

children = [
  {Ascii.Telemetry,
   name: MyApp.Readings,
   metrics: [
     Telemetry.Metrics.last_value("vm.memory.total", unit: {:byte, :megabyte}),
     Telemetry.Metrics.counter("phoenix.endpoint.stop.duration", reporter_options: [label: "requests"]),
     Telemetry.Metrics.summary("my_app.repo.query.total_time", unit: {:native, :millisecond})
   ]}
]

# in a LiveView
if connected?(socket), do: Ascii.Telemetry.subscribe(MyApp.Readings)

def handle_info({:ascii_telemetry, _feed, readings}, socket),
  do: {:noreply, assign(socket, history: Ascii.Telemetry.sparkline(readings))}

<Ascii.Phoenix.live_player id="history" piece="sparkline" options={@history} />

Or have it feed players itself, each sample:

{Ascii.Telemetry, metrics: metrics, players: [{MyApp.History, &Ascii.Telemetry.sparkline/1}]}

Metrics

Telemetry.Metrics definitions, as for any reporter (the telemetry_metrics package; it need not be a dependency of this library), or maps of the same: %{name: "db", event: [:my_app, :repo, :query], measurement: :total_time, kind: :summary, unit: "ms"}. Each sample, every :every milliseconds, gives each metric one reading:

  • last_value - its latest measurement (kept until another comes);
  • counter - how many events came;
  • sum - their measurements added up;
  • summary, distribution - their mean, or nothing if none came.

A metric's label is its reporter_options[:label], else its name's last part but one, as memory for vm.memory.total; its unit is the one it converts to.

Options

  • :metrics - the metrics (required).
  • :every - milliseconds a sample (default 1000).
  • :window - samples kept of each metric (default 120).
  • :players - {player, fun} pairs: each sample, fun turns the readings into options for the player (Ascii.Player.set_options/2).
  • :name - to register the process.

Handlers run in the processes that emit the events, so each is a message to this process and no more. They are detached when it stops. Only available when telemetry is a dependency (Phoenix brings it).

Summary

Types

A metric's readings, oldest first, by its label, with its unit.

Functions

Options for gauge: the latest reading of the metric label (the first, if not given), its label and unit; :min and :max for the dial.

The readings so far.

Options for sparkline: a series a metric (the first five; :only picks by label), and its rate, samples a second.

Starts a feed; see the module docs for the options.

Sends the calling process {:ascii_telemetry, feed, readings} after every sample, until it exits.

Types

readings()

@type readings() :: [%{label: String.t(), unit: String.t(), values: [number()]}]

A metric's readings, oldest first, by its label, with its unit.

Functions

gauge(readings, opts \\ [])

@spec gauge(
  readings :: readings(),
  opts :: [label: String.t(), min: number(), max: number()]
) :: map()

Options for gauge: the latest reading of the metric label (the first, if not given), its label and unit; :min and :max for the dial.

readings(feed)

@spec readings(feed :: GenServer.server()) :: readings()

The readings so far.

sparkline(readings, opts \\ [])

@spec sparkline(
  readings :: readings(),
  opts :: [only: [String.t()], every: pos_integer()]
) :: map()

Options for sparkline: a series a metric (the first five; :only picks by label), and its rate, samples a second.

start_link(opts)

@spec start_link(opts :: keyword()) :: GenServer.on_start()

Starts a feed; see the module docs for the options.

subscribe(feed)

@spec subscribe(feed :: GenServer.server()) :: :ok

Sends the calling process {:ascii_telemetry, feed, readings} after every sample, until it exits.