Oban Met

Hex Version Hex Docs CI Status Apache 2 License

Met is a distributed, compacting, multidimensional, telemetry-powered time series datastore for Oban that requires no configuration. It gathers data for queues, job counts, execution metrics, active crontabs, historic metrics, and more.

Met powers the charts and runtime details shown in the Oban Web dashboard.

Features

Installation

Oban Met is included with Oban Web and manual installation is only necessary in hybrid environments (separate Web and Worker nodes).

To receive metrics from non-web nodes in a system with separate "web" and "worker" applications you must explicitly include oban_met as a dependency for "workers".

{:oban_met, "~> 1.3"}

Met requires Oban v2.23 or later.

Usage

No configuration is necessary and Oban Met will start automatically in a typical application. A variety of options are provided for more complex or nuanced usage.

Querying Metrics

Met records four series, each labeled by node, queue, and state, and the job series also by worker:

Use Oban.Met.latest/3 for current values and Oban.Met.timeslice/3 for history, filtered and grouped by any label:

Oban.Met.latest(:full_count, group: "state")
%{"available" => 9, "completed" => 80, "executing" => 5}

Oban.Met.timeslice(:exec_time, by: 5, group: "queue", operation: {:pct, 0.95})
[{11, 9970235387.03, "analysis"}, ..., {0, 1520977874.33, "events"}]

Producer checks from every node are available through Oban.Met.checks/1, and the merged crontab from every node through Oban.Met.crontab/1.

Configuration

Met starts without configuration, but every supervised component accepts options that may be provided two ways:

Options are namespaced by component: :cronitor, :examiner, :listener, :recorder, and :reporter. Most are internal and best left alone, but the sections below cover the options worth tuning.

Auto Start

Supervised Met instances start automatically along with Oban instances unless Oban is in testing mode. You can disable auto-starting globally with application configuration:

config :oban_met, auto_start: false

Then, start instances as a child directly within your Oban app's plugins:

plugins: [
  Oban.Met,
  ...
]

By default Met only starts when Oban's :testing mode is :disabled. To run Met under a specific testing mode, for example to inspect metrics during :manual tests, add the mode to :auto_testing_modes:

config :oban_met, auto_testing_modes: [:disabled, :manual]

Customizing Estimates

The estimate_limit determines when counts switch from an accurate count(*) query to a much more efficient, but less accurate, estimate function. The limit applies to each state's total across all queues: once a state reaches the limit, its count for every queue is estimated on the following checks. Estimates are only available on Postgres, and other databases always use exact counts.

The default limit is a conservative 50k, which may be too low for systems with insert spikes. This declares an override to set the limit to 200k:

{Oban.Met, reporter: [estimate_limit: 200_000]}

Customizing Check Interval

The reporter periodically counts jobs in each state/queue combination to provide the counts displayed in Oban Web. By default, counts are checked every 1 second. For systems where real-time counts aren't critical, or to reduce database load, you can increase the interval:

{Oban.Met, reporter: [check_interval: :timer.seconds(5)]}

The list of queues used for estimates is refreshed every 60 checks, so newly added queues may take longer to appear in estimated counts with a longer interval.

Explicit Migrations

Met will create the necessary estimate function automatically when possible. The migration isn't necessary under normal circumstances, but is provided to avoid permission issues or allow full control over database changes. If the database role Met connects with can't create or replace the function, counts fail on every check and the error is logged until the migration is used instead.

mix ecto.gen.migration add_oban_met

Open the generated migration and delegate the up/0 and down/0 functions to Oban.Met.Migration:

defmodule MyApp.Repo.Migrations.AddObanMet do
  use Ecto.Migration

  def up, do: Oban.Met.Migration.up()
  def down, do: Oban.Met.Migration.down()
end

Pass a :prefix to both functions, e.g. Oban.Met.Migration.up(prefix: "private"), when Oban runs in an alternate prefix.

Then configure the reporter not to auto-migrate:

config :oban_met, reporter: [auto_migrate: false]

Customizing the Estimate Function

By default the reporter installs and calls the built-in PostgreSQL oban_count_estimate function. On other Postgres-compatible engines that can't run that definition (e.g. CockroachDB) you can supply your own (prefix -> ddl) builder and keep auto_migrate enabled. The returned DDL must create a <prefix>.oban_count_estimate(state text, queue text) function returning an integer estimate:

{Oban.Met, reporter: [estimate_function: &MyApp.ObanEstimate.build/1]}

Compaction Periods

Recorded metrics are periodically compacted into coarser windows to bound memory use. Each period is a {step, duration} tuple in seconds, where step is the resolution and duration is how long values are retained at that resolution, after the periods before it. The defaults keep about three and a half hours of history:

{Oban.Met, recorder: [compact_periods: [{1, 120}, {5, 900}, {30, 2_000}, {60, 9_300}]]}

Web Charts {: .neutral}

Oban Web's charts are rendered from these recorded metrics. Drastically shortening the periods reduces the history available to plot and may impact chart rendering.

Sketch Time Unit

Timing metrics (execution time, queue time) are stored in space-efficient quantile sketches. By default, values are recorded in :native time units (nanoseconds on most systems), which provides maximum precision but uses more space.

For reduced storage size (~20% smaller) and better bin consolidation, you can configure sketches to store timing in milliseconds:

config :oban_met, sketch_time_unit: :millisecond

This is a compile-time option that affects how timing values are binned in sketches, so changing it requires recompiling Met, e.g. mix deps.compile oban_met --force.

Cluster Consistency {: .warning}

All nodes in a cluster must use the same sketch_time_unit setting. Mixing units between nodes will produce incorrect aggregated metrics.

After changing this setting, existing metrics will be invalid until compaction ages them out (about three and a half hours with default compaction periods).

Contributing

To run the test suite you must have PostgreSQL 12+. Once dependencies are installed, setup the databases and run necessary migrations:

mix test.setup

Use mix test.reset to drop, recreate, and migrate the test databases.

Community

There are a few places to connect and communicate with other Oban users: