Packages
oban
0.11.0
2.23.0
2.22.1
2.22.0
2.21.1
2.21.0
2.20.3
2.20.2
2.20.1
2.20.0
2.19.4
2.19.3
2.19.2
2.19.1
2.19.0
2.18.3
2.18.2
2.18.1
2.18.0
2.17.12
2.17.11
2.17.10
2.17.9
2.17.8
2.17.7
2.17.6
2.17.5
2.17.4
2.17.3
2.17.2
2.17.1
2.17.0
2.16.3
2.16.2
2.16.1
2.16.0
2.15.4
2.15.3
2.15.2
2.15.1
2.15.0
2.14.2
2.14.1
2.14.0
2.13.6
2.13.5
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.12.1
2.12.0
2.11.3
2.11.2
2.11.1
2.11.0
2.10.1
2.10.0
retired
2.9.2
2.9.1
2.9.0
2.8.0
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.4
2.3.3
2.3.2
2.3.1
2.3.0
2.2.0
2.1.0
2.0.0
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
1.2.0
1.1.0
1.0.0
1.0.0-rc.2
1.0.0-rc.1
0.12.1
0.12.0
0.11.1
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.1
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Robust job processing, backed by modern PostgreSQL, SQLite3, and MySQL.
Current section
Files
Jump to
Current section
Files
lib/oban/telemetry.ex
defmodule Oban.Telemetry do
@moduledoc """
Telemetry integration for event metrics, logging and error reporting.
Oban currently emits an event when a job has exeucted: `[:oban, :success]` if the job succeeded
or `[:oban, :failure]` if there was an error or the process crashed.
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:
| event | metadata |
| ---------- | ---------------------------------------------------------------------------- |
| `:success` | `:id, :args, :queue, :worker, :attempt, :max_attempt` |
| `:failure` | `:id, :args, :queue, :worker, :attempt, :max_attempt, :kind, :error, :stack` |
For `:failure` events the metadata will include 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`.
* `:exception` — from a rescued exception
* `: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
## 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.
## Examples
A handler that only logs a few details about failed jobs:
```elixir
defmodule MicroLogger do
require Logger
def handle_event([:oban, :failure], %{duration: duration}, meta, nil) do
Logger.warning("[#\{meta.queue}] #\{meta.worker} failed in #\{duration}")
end
end
:telemetry.attach("oban-logger", [:oban, :failure], &ObanLogger.handle_event/4, nil)
```
Another great use of execution data is error reporting. Here is an example of integrating with
[Honeybadger][honey], but only reporting jobs that have failed 3 times or more:
```elixir
defmodule ErrorReporter do
def handle_event([:oban, :failure], _timing, %{attempt: attempt} = meta, nil) do
if attempt >= 3 do
context = Map.take(meta, [:id, :args, :queue, :worker])
Honeybadger.notify(meta.error, context, meta.stack)
end
end
end
:telemetry.attach("oban-errors", [:oban, :failure], &ErrorReporter.handle_event/4, nil)
```
[honey]: https://honeybadger.io
"""
@moduledoc since: "0.4.0"
require Logger
@doc """
Attaches a default structured JSON Telemetry handler for logging.
This function attaches a handler that outputs logs with the following fields:
* `source` — always "oban"
* `event` — either `:success` or `:failure` dependening on whether the job succeeded or errored
* `args` — a map of the job's raw arguments
* `worker` — the job's worker module
* `queue` — the job's queue
* `duration` — the job's runtime duration in microseconds
## 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)
"""
@doc since: "0.4.0"
@spec attach_default_logger() :: :ok | {:error, :already_exists}
def attach_default_logger(level \\ :info) do
events = [[:oban, :success], [:oban, :failure]]
:telemetry.attach_many("oban-default-logger", events, &handle_event/4, level)
end
@doc false
@spec handle_event([atom()], map(), map(), Logger.level()) :: :ok
def handle_event([:oban, event], measurement, meta, level)
when event in [:success, :failure] do
Logger.log(level, fn ->
Jason.encode!(%{
source: "oban",
event: event,
args: meta[:args],
worker: meta[:worker],
queue: meta[:queue],
duration: measurement[:duration]
})
end)
end
end