Oban.Telemetry (Oban v2.3.3) View Source

Telemetry integration for event metrics, logging and error reporting.

Job Events

Oban emits the following telemetry events for each job:

  • [:oban, :job, :start] — at the point a job is fetched from the database and will execute
  • [:oban, :job, :stop] — after a job succeeds and the success is recorded in the database
  • [:oban, :job, :exception] — after a job fails and the failure is recorded in the database

All job events share the same details about the job that was executed. In addition, failed jobs provide the error type, the error itself, and the stacktrace. The following chart shows which metadata you can expect for each event:

eventmeasuresmetadata
:start:system_time:job, :prefix
:stop:duration, :queue_time:job, :prefix
:exception:duration, :queue_time:job, :prefix, :kind, :error, :stacktrace

For :exception events the metadata includes details about what caused the failure. The :kind value is determined by how an error occurred. Here are the possible kinds:

  • :error — from an {:error, error} return value. Some Erlang functions may also throw an :error tuple, which will be reported as :error.
  • :exit — from a caught process exit
  • :throw — from a caught value, this doesn't necessarily mean that an error occurred and the error value is unpredictable

Producer Events

Oban emits the following telemetry span events for each queue's producer:

  • [:oban, :producer, :start | :stop | :exception] — when a producer deschedules or dispatches new jobs
eventmeasuresmetadata
:start:system_time:action, :queue
:stop:duration:action, :queue
:exception:duration:action, :queue

Metadata

  • :action — one of :deschedule or :dispatch
  • :queue — the name of the queue as a string, e.g. "default" or "mailers"

Circuit Events

All processes that interact with the database have circuit breakers to prevent errors from crashing the entire supervision tree. Processes emit a [:oban, :circuit, :trip] event when a circuit is tripped and [:oban, :circuit, :open] when the breaker is subsequently opened again.

eventmeasuresmetadata
[:oban, :circuit, :trip]:error, :message, :name, :stacktrace
[:oban, :circuit, :open]:name

Metadata

  • :error — the error that tripped the circuit, see the error kinds breakdown above
  • :name — the registered name of the process that tripped a circuit, i.e. Oban.Notifier
  • :message — a formatted error message describing what went wrong
  • :stacktrace — exception stacktrace, when available

Default Logger

A default log handler that emits structured JSON is provided, see attach_default_logger/0 for usage. Otherwise, if you would prefer more control over logging or would like to instrument events you can write your own handler.

Here is an example of the JSON output for the job:stop event:

{
  "args":{"action":"OK","ref":1},
  "duration":4327295,
  "event":"job:stop",
  "queue":"alpha",
  "queue_time":3127905,
  "source":"oban",
  "worker":"Oban.Integration.Worker"
}

All timing measurements are recorded as native time units but logged in microseconds.

Examples

A handler that only logs a few details about failed jobs:

defmodule MicroLogger do
  require Logger

  def handle_event([:oban, :job, :exception], %{duration: duration}, meta, nil) do
    Logger.warn("[#{meta.queue}] #{meta.worker} failed in #{duration}")
  end
end

:telemetry.attach("oban-logger", [:oban, :job, :exception], &MicroLogger.handle_event/4, nil)

Another great use of execution data is error reporting. Here is an example of integrating with Honeybadger, but only reporting jobs that have failed 3 times or more:

defmodule ErrorReporter do
  def handle_event([:oban, :job, :exception], _, %{attempt: attempt} = meta, _) do
    if attempt >= 3 do
      context = Map.take(meta, [:id, :args, :queue, :worker])

      Honeybadger.notify(meta.error, context, meta.stacktrace)
    end
  end
end

:telemetry.attach("oban-errors", [:oban, :job, :exception], &ErrorReporter.handle_event/4, [])

Link to this section Summary

Functions

Attaches a default structured JSON Telemetry handler for logging.

Measure and report :start, :stop and :exception events for a function.

Link to this section Functions

Link to this function

attach_default_logger(level \\ :info)

View Source (since 0.4.0)

Specs

attach_default_logger(Logger.level()) :: :ok | {:error, :already_exists}

Attaches a default structured JSON Telemetry handler for logging.

This function attaches a handler that outputs logs with the following fields:

  • args — a map of the job's raw arguments
  • duration — the job's runtime duration, in the native time unit
  • event — either :success or :failure depending on whether the job succeeded or errored
  • queue — the job's queue
  • source — always "oban"
  • system_time — when the job started, in microseconds
  • worker — the job's worker module

Examples

Attach a logger at the default :info level:

:ok = Oban.Telemetry.attach_default_logger()

Attach a logger at the :debug level:

:ok = Oban.Telemetry.attach_default_logger(:debug)
Link to this function

span(name, fun, meta \\ %{})

View Source

Specs

span(name :: atom(), fun :: (() -> term()), meta :: map()) :: term()

Measure and report :start, :stop and :exception events for a function.

Examples

Emit span timing events for a prune function:

:ok = Oban.Telemetry.span(:prune, &MyApp.Pruner.prune/0, %{extra: :data})

That will emit the following events:

  • [:oban, :prune, :start] — before the function is invoked
  • [:oban, :prune, :stop] — when the function completes successfully
  • [:oban, :prune, :exception] — reported if the function throws, crashes or raises an error