Timeless

LiveDashboard Plugin for Timeless Metrics

Hex.pm Docs License


"I found it ironic that the first thing you do to time series data is squash the timestamp. That's how the name Timeless was born." --Mark Cotner

Telemetry reporter and LiveDashboard page plugin for TimelessMetrics.

Phoenix LiveDashboard ships real-time metrics that reset on every page load. TimelessMetricsDashboard bridges the gap: a telemetry reporter captures events into TimelessMetrics, and the dashboard page gives you persistent historical charts, alert visibility, backup controls, and compression stats.

Drop it in and your LiveDashboard gets real trending for free.

Installation

Quick Start (Igniter)

mix igniter.install timeless_metrics_dashboard

This automatically:

  1. Adds {TimelessMetricsDashboard, data_dir: "priv/timeless_metrics"} to your supervision tree
  2. Adds import TimelessMetricsDashboard.Router to your router
  3. Adds timeless_metrics_dashboard "/dashboard" to your browser scope
  4. Updates your .formatter.exs

Manual Setup

Add to your mix.exs:

def deps do
[
{:timeless_metrics, "~> 6.2"},
{:timeless_metrics_dashboard, "~> 0.4"}
]
end

1. Supervision Tree

Add to your application's supervision tree. This starts TimelessMetrics and the telemetry reporter:

# application.ex
children = [
{TimelessMetricsDashboard, data_dir: "priv/timeless_metrics"}
]

Or for more control over which metrics are captured:

children = [
{TimelessMetricsDashboard,
data_dir: "priv/timeless_metrics",
metrics:
TimelessMetricsDashboard.DefaultMetrics.vm_metrics() ++
TimelessMetricsDashboard.DefaultMetrics.phoenix_metrics() ++
TimelessMetricsDashboard.DefaultMetrics.ecto_metrics([:my_app, :repo]) ++
TimelessMetricsDashboard.DefaultMetrics.live_view_metrics()}
]

2. Router

# router.ex
import TimelessMetricsDashboard.Router
scope "/" do
pipe_through :browser
timeless_metrics_dashboard "/dashboard"
end

The router macro sets up LiveDashboard with the metrics history callback, the Timeless page, and the backup download plug.

The history callback reads from TimelessMetrics by default. To back the history charts with a different owner-compatible store (for example the release Stack adapter for Rust/libSQL historical reads), call TimelessMetricsDashboard.metrics_history/3 yourself with :query_module set to the adapter module; it must implement query_aggregate_multi/4, and no fallback occurs if it returns an error.

3. Reporter Only (no Phoenix)

The reporter works without Phoenix. Any application that uses :telemetry can use it:

children = [
{TimelessMetrics, name: :metrics, data_dir: "/var/lib/metrics"},
{TimelessMetricsDashboard.Reporter,
store: :metrics,
metrics: TimelessMetricsDashboard.DefaultMetrics.vm_metrics()}
]

The page, component, and download modules are compiled only when their Phoenix or Plug dependencies are available. A reporter-only application does not need to add those optional dependencies.

Dashboard Tabs

Overview

Store statistics at a glance: series count, total points, compression ratio, storage size, and rollup tier breakdown.

Metrics

Browse all metrics in the store (both telemetry-captured and directly written), select a time range, and view SVG charts with automatic bucketing. Metric metadata (type, unit, description) is displayed when available.

All metrics written to the TimelessMetrics store appear here, whether they came through the reporter or were written directly via TimelessMetrics.write/4.

Alerts

Lists all configured alert rules with their current state (ok/pending/firing). Includes inline documentation with examples for creating alerts via the TimelessMetrics API:

TimelessMetrics.create_alert(:timeless_metrics,
name: "high_memory",
metric: "telemetry.vm.memory.total",
condition: :above,
threshold: 512_000_000,
duration: 60
)
# With webhook notification (ntfy.sh, Slack, etc.)
TimelessMetrics.create_alert(:timeless_metrics,
name: "high_latency",
metric: "telemetry.phoenix.endpoint.stop.duration",
condition: :above,
threshold: 500,
duration: 120,
aggregate: :avg,
webhook_url: "https://ntfy.sh/my-alerts",
webhook_format: "ntfy"
)

The alert form supports generic JSON webhooks and ntfy topic URLs and shows the configured format in the rule list.

Storage

Database path, size, and retention settings. Create and download backups, flush buffered data to disk.

Child Spec Options

Option Default Description
:name :timeless_metrics TimelessMetrics store name
:data_dir "priv/timeless_metrics" Data directory
:metrics DefaultMetrics.metrics() List of Telemetry.Metrics structs
:reporter [] Extra opts forwarded to Reporter (:flush_interval, :prefix)

Reporter Options

Option Default Description
:store required TimelessMetrics store name (atom)
:metrics [] List of Telemetry.Metrics structs
:flush_interval 10_000 Milliseconds between batch flushes
:prefix "telemetry" Metric name prefix
:name TimelessMetricsDashboard.Reporter GenServer name
:max_buffer_size 100_000 Maximum queued points before new points are dropped and counted
:batch_size 5_000 Maximum points written in each store batch

Page Options

Option Default Description
:store required TimelessMetrics store name (atom)
:chart_width 700 SVG chart width in pixels
:chart_height 250 SVG chart height in pixels
:metric_page_size 200 Maximum metric buttons rendered per page
:max_chart_series 20 Maximum series rendered on one chart
:download_path nil Path to DownloadPlug (enables download links)

The router macro also accepts :live_session_name for multiple dashboard mounts and :download_auth_token to require a bearer token for backup downloads. Archive downloads are serialized per store by default and use the web server's fixed-size HTTP chunks instead of loading the archive into BEAM memory.

Default Metrics

Pre-built metric definitions for common events:

Mix and match with your own custom Telemetry.Metrics definitions.

Architecture

The reporter handler runs in the caller's process, not the GenServer. All hot-path operations are lock-free:

Demo

Run the included demo to see everything in action:

cd timeless_metrics_dashboard
mix run examples/demo.exs
# Open http://localhost:4000/dashboard/timeless

VM metrics will start populating immediately via :telemetry_poller. Use TIMELESS_DATA_DIR to persist data across restarts:

TIMELESS_DATA_DIR=~/.timeless_demo mix run examples/demo.exs

License

MIT