TimelessMetrics (timeless_metrics v6.6.7)

Copy Markdown View Source

Embedded time series storage for Elixir.

TimelessMetrics runs as an embedded store inside your application and defaults to a Rust-backed engine for raw point ingestion and queries. Administrative data such as annotations, alerts, scrape targets, and rollup metadata stays on the Elixir side.

Quick Start

# Add to your supervision tree
children = [
  {TimelessMetrics, name: :metrics, data_dir: "/tmp/metrics"}
]

# Write metrics
TimelessMetrics.write(:metrics, "cpu_usage", %{"host" => "web-1"}, 73.2)

# Query
TimelessMetrics.query(:metrics, "cpu_usage", %{"host" => "web-1"},
  from: System.os_time(:second) - 3600,
  to: System.os_time(:second)
)

Summary

Functions

Acknowledge an alert history entry by ID.

List recent alert history entries.

Create an annotation (event marker).

Query annotations within a time range.

Create a consistent online backup.

Start a TimelessMetrics instance as part of a supervision tree.

Clear alert history entries.

Create an alert rule.

Delete an alert rule.

Delete an annotation by ID.

Detect anomalies in matching series.

Force retention enforcement now.

Evaluate all alert rules against current data.

Force flush all buffered data to disk.

Forecast future values for matching series.

Get metadata for a metric.

Get store info and statistics.

List distinct values for a specific label key across all series of a metric.

Get the latest value for a series.

Get the latest value for ALL series matching a metric name and label filter.

Get the latest text value for a series.

List all alert rules with current state.

List all distinct metric names in the store.

List all series for a given metric name.

No-op for sharded engine (no per-series blocks to merge).

Query raw time series points for a single series (exact label match).

Query with time-bucket aggregation for a single series (exact label match).

Query with cross-series aggregation, grouping results by a label key.

Query with cross-series aggregation across multiple metrics, with group-by.

Query with aggregation across multiple series matching a label filter.

Query with aggregation across multiple metric names matching a label filter.

Query pre-computed daily rollup data.

Query raw points across multiple series matching a label filter.

Query raw points for several metric names in one engine operation.

Query text time series points for a single series.

Query text points across multiple series matching a label filter.

Register metadata for a metric (type, unit, description).

Resolve a series to an integer ID for use with write_resolved/4.

Force a daily rollup run.

Sort results by a value function and take top N.

Update an alert rule (partial update). Returns :ok.

Write a batch of metric points.

Write entries directly, one per unique series. Same as write_batch/2 for the sharded engine.

Write directly using a pre-resolved series ID. Zero lookup cost.

Write a batch of text metric points.

Types

api_result(result)

@type api_result(result) :: {:ok, result} | {:error, term()}

command_result()

@type command_result() :: :ok | :noop | {:error, term()}

labels()

@type labels() :: %{optional(String.t()) => String.t()}

metric_name()

@type metric_name() :: String.t()

point()

@type point() :: {timestamp(), value()}

store()

@type store() :: atom()

timestamp()

@type timestamp() :: integer()

value()

@type value() :: number() | String.t()

write_entry()

@type write_entry() ::
  {metric_name(), labels(), value()}
  | {metric_name(), labels(), value(), timestamp()}

Functions

acknowledge_alert(store, history_id)

@spec acknowledge_alert(store(), integer()) :: command_result()

Acknowledge an alert history entry by ID.

alert_history(store, opts \\ [])

@spec alert_history(store(), keyword()) :: api_result([map()])

List recent alert history entries.

Options: :limit, :rule_id, :acknowledged (true/false/nil).

annotate(store, timestamp, title, opts \\ [])

@spec annotate(store(), timestamp(), String.t(), keyword()) :: api_result(integer())

Create an annotation (event marker).

Returns {:ok, id}.

annotations(store, from, to, opts \\ [])

@spec annotations(store(), timestamp(), timestamp(), keyword()) :: api_result([map()])

Query annotations within a time range.

Returns {:ok, [%{id: n, timestamp: ts, title: "...", description: "...", tags: [...]}]}.

backup(store, target_dir)

@spec backup(store(), Path.t()) :: api_result(map())

Create a consistent online backup.

child_spec(opts)

@spec child_spec(keyword()) :: Supervisor.child_spec()

Start a TimelessMetrics instance as part of a supervision tree.

clear_alert_history(store, opts \\ [])

@spec clear_alert_history(store(), keyword()) :: command_result()

Clear alert history entries.

Options: :acknowledged_only (default true), :before (timestamp cutoff).

create_alert(store, opts)

@spec create_alert(store(), keyword()) :: api_result(integer())

Create an alert rule.

Returns {:ok, rule_id}.

delete_alert(store, rule_id)

@spec delete_alert(store(), integer()) :: command_result()

Delete an alert rule.

delete_annotation(store, id)

@spec delete_annotation(store(), integer()) :: command_result()

Delete an annotation by ID.

detect_anomalies(store, metric_name, labels, opts)

@spec detect_anomalies(store(), metric_name(), labels(), keyword()) ::
  api_result([map()])

Detect anomalies in matching series.

Returns {:ok, [%{labels: map, analysis: [%{timestamp, value, expected, score, anomaly}]}, ...]}.

enforce_retention(store)

@spec enforce_retention(store()) :: command_result()

Force retention enforcement now.

evaluate_alerts(store)

@spec evaluate_alerts(store()) :: command_result()

Evaluate all alert rules against current data.

flush(store)

@spec flush(store()) :: command_result()

Force flush all buffered data to disk.

forecast(store, metric_name, labels, opts)

@spec forecast(store(), metric_name(), labels(), keyword()) :: api_result([map()])

Forecast future values for matching series.

Returns {:ok, [%{labels: map, data: [{ts, val}], forecast: [{ts, val}]}, ...]}.

get_metadata(store, metric_name)

@spec get_metadata(store(), metric_name()) :: api_result(map() | nil)

Get metadata for a metric.

Returns {:ok, %{type: :gauge, unit: "%", description: "..."}} or {:ok, nil}.

info(store)

@spec info(store()) :: map() | {:error, term()}

Get store info and statistics.

label_values(store, metric_name, label_key)

@spec label_values(store(), metric_name(), String.t()) :: api_result([String.t()])

List distinct values for a specific label key across all series of a metric.

Returns {:ok, ["web-1", "web-2", ...]}.

latest(store, metric_name, labels)

@spec latest(store(), metric_name(), labels()) :: api_result(point() | nil)

Get the latest value for a series.

Returns {:ok, {timestamp, value}} or {:ok, nil}.

latest_multi(store, metric_name, label_filter \\ %{})

@spec latest_multi(store(), metric_name(), labels()) :: api_result([map()])

Get the latest value for ALL series matching a metric name and label filter.

Returns {:ok, [%{labels: %{...}, timestamp: ts, value: val}, ...]}.

latest_text(store, metric_name, labels)

@spec latest_text(store(), metric_name(), labels()) :: api_result(point() | nil)

Get the latest text value for a series.

list_alerts(store)

@spec list_alerts(store()) :: api_result([map()])

List all alert rules with current state.

list_metrics(store)

@spec list_metrics(store()) :: api_result([metric_name()])

List all distinct metric names in the store.

Returns {:ok, ["cpu_usage", "mem_usage", ...]}.

list_series(store, metric_name)

@spec list_series(store(), metric_name()) :: api_result([map()])

List all series for a given metric name.

Returns {:ok, [%{labels: %{"host" => "web-1"}, ...}, ...]}.

merge_now(store)

@spec merge_now(store()) :: :noop

No-op for sharded engine (no per-series blocks to merge).

query(store, metric_name, labels, opts \\ [])

@spec query(store(), metric_name(), labels(), keyword()) :: api_result([point()])

Query raw time series points for a single series (exact label match).

Options

  • :from - Start timestamp (unix seconds, default: 0)
  • :to - End timestamp (unix seconds, default: now)

Returns {:ok, [{timestamp, value}, ...]}.

query_aggregate(store, metric_name, labels, opts)

@spec query_aggregate(store(), metric_name(), labels(), keyword()) ::
  api_result([point()])

Query with time-bucket aggregation for a single series (exact label match).

Options

  • :from - Start timestamp
  • :to - End timestamp
  • :bucket - Bucket size: :minute, :hour, :day, or {n, :seconds}
  • :aggregate - Aggregate function: :avg, :min, :max, :sum, :count, :last, :first

Returns {:ok, [{bucket_timestamp, aggregate_value}, ...]}.

query_aggregate_grouped(store, metric_name, label_filter \\ %{}, opts)

@spec query_aggregate_grouped(store(), metric_name(), labels(), keyword()) ::
  api_result([map()])

Query with cross-series aggregation, grouping results by a label key.

Returns {:ok, [%{group: %{"hostname" => "host_0"}, data: [{ts, val}]}, ...]}.

query_aggregate_grouped_metrics(store, metric_names, label_filter \\ %{}, opts)

@spec query_aggregate_grouped_metrics(store(), [metric_name()], labels(), keyword()) ::
  api_result([map()])

Query with cross-series aggregation across multiple metrics, with group-by.

Returns {:ok, [%{group: %{...}, data: [{ts, val}]}, ...]}.

query_aggregate_multi(store, metric_name, label_filter \\ %{}, opts)

@spec query_aggregate_multi(store(), metric_name(), labels(), keyword()) ::
  api_result([map()])

Query with aggregation across multiple series matching a label filter.

Returns {:ok, [%{labels: %{...}, data: [{bucket_ts, agg_value}, ...]}, ...]}.

query_aggregate_multi_filtered(store, metric_name, label_filter \\ %{}, opts)

@spec query_aggregate_multi_filtered(store(), metric_name(), labels(), keyword()) ::
  api_result([map()])

Query with aggregation and threshold filtering.

Returns {:ok, [%{labels: %{...}, data: [{ts, val}]}, ...]}.

query_aggregate_multi_metrics(store, metric_names, label_filter \\ %{}, opts)

@spec query_aggregate_multi_metrics(store(), [metric_name()], labels(), keyword()) ::
  api_result([map()])

Query with aggregation across multiple metric names matching a label filter.

Returns {:ok, [%{metric: name, labels: %{...}, data: [{ts, val}, ...]}, ...]}.

query_daily(store, metric_name, labels, from, to)

@spec query_daily(store(), metric_name(), labels(), timestamp(), timestamp()) ::
  api_result([map()])

Query pre-computed daily rollup data.

Returns {:ok, [%{bucket: ts, avg: v, min: v, max: v, count: n, sum: v, last: v}, ...]}.

query_multi(store, metric_name, label_filter \\ %{}, opts \\ [])

@spec query_multi(store(), metric_name(), labels(), keyword()) :: api_result([map()])

Query raw points across multiple series matching a label filter.

Returns {:ok, [%{labels: %{...}, points: [{ts, val}, ...]}, ...]}. Point order is stable within each series. As with the legacy/Rust parallel query paths, the outer series list is unordered; sort it in the caller when presentation order matters.

query_multi_metrics(store, metric_names, label_filter \\ %{}, opts \\ [])

@spec query_multi_metrics(store(), [metric_name()], labels(), keyword()) ::
  api_result([map()])

Query raw points for several metric names in one engine operation.

Returns {:ok, [%{metric: name, labels: labels, points: points}, ...]}.

query_text(store, metric_name, labels, opts \\ [])

@spec query_text(store(), metric_name(), labels(), keyword()) :: api_result([point()])

Query text time series points for a single series.

query_text_multi(store, metric_name, label_filter \\ %{}, opts \\ [])

@spec query_text_multi(store(), metric_name(), labels(), keyword()) ::
  api_result([map()])

Query text points across multiple series matching a label filter.

register_metric(store, metric_name, metric_type, opts \\ [])

@spec register_metric(store(), metric_name(), atom(), keyword()) ::
  TimelessMetrics.DB.query_result()

Register metadata for a metric (type, unit, description).

resolve_series(store, metric_name, labels)

@spec resolve_series(store(), metric_name(), labels()) :: api_result(integer())

Resolve a series to an integer ID for use with write_resolved/4.

Cache the result for repeated writes to the same series.

rollup(store)

@spec rollup(store()) :: command_result()

Force a daily rollup run.

top_n(results, n, order_fn \\ &last_value/1)

@spec top_n([item], non_neg_integer(), (item -> term())) :: [item] when item: term()

Sort results by a value function and take top N.

update_alert(store, rule_id, opts)

@spec update_alert(store(), integer(), keyword()) :: command_result()

Update an alert rule (partial update). Returns :ok.

write(store, metric_name, labels, value, opts \\ [])

@spec write(store(), metric_name(), labels(), value(), keyword()) :: command_result()

Write a single metric point.

Parameters

  • store - The store name (atom)
  • metric_name - String metric name (e.g., "cpu_usage")
  • labels - Map of string labels (e.g., %{"host" => "web-1"})
  • value - Numeric value (float or integer)
  • opts - Optional keyword list:
    • :timestamp - Unix timestamp in seconds (default: now)

write_batch(store, entries)

@spec write_batch(store(), [write_entry()]) :: command_result()

Write a batch of metric points.

Each entry is a tuple of {metric_name, labels, value} or {metric_name, labels, value, timestamp}.

write_each(store, entries)

@spec write_each(store(), [write_entry()]) :: command_result()

Write entries directly, one per unique series. Same as write_batch/2 for the sharded engine.

write_resolved(store, series_id, value, opts \\ [])

@spec write_resolved(store(), integer(), value(), keyword()) :: command_result()

Write directly using a pre-resolved series ID. Zero lookup cost.

{:ok, sid} = TimelessMetrics.resolve_series(:metrics, "cpu_usage", %{"host" => "web-1"})
TimelessMetrics.write_resolved(:metrics, sid, 73.2, timestamp: ts)

write_text(store, metric_name, labels, value, opts \\ [])

@spec write_text(store(), metric_name(), labels(), String.t(), keyword()) ::
  command_result()

Write a single text metric point.

write_text_batch(store, entries)

@spec write_text_batch(store(), [write_entry()]) :: command_result()

Write a batch of text metric points.