Elixir error reporting client for a ForgeOps instance:
ForgeOpsTracker.init(dsn: "https://<api_key>@your-forgeops-host/api/v1/events")
ForgeOpsTracker.install_handlers()See the module docs on ForgeOpsTracker.LoggerHandler for what install_handlers/0 actually
covers (every process crash anywhere in the whole BEAM VM, via :logger: a meaningfully
stronger automatic-capture story than any single-thread uncaught-exception hook) and
capture_exception/3 for reporting one you've already rescued yourself.
Summary
Functions
Report an exception (or any raised/thrown term: see ForgeOpsTracker.EventBuilder's own doc
for why this doesn't require a real Exception struct) you've already rescued yourself
Configures the client. Call once at startup: application.ex's own start/2, before the rest
of your supervision tree starts, is the natural place. Accepts the same keys as
ForgeOpsTracker.Configuration's struct fields
Installs the :logger handler described in ForgeOpsTracker.LoggerHandler's own module doc.
Call once, after init/1. Safe to call more than once: a later call is a no-op.
Records one occurrence of transaction_name (a request, a database query, a queue job) taking
duration_ms, bucketed by kind ("controller"/"job"/"query"). Not something app code
normally calls directly: ForgeOpsTracker.Integrations.Phoenix/Ecto/Oban all call this once
wired up via their own attach/0/attach/1.
Manually attaches an affected user to whatever gets reported for the rest of this process
(a Phoenix request's own connection process, a GenServer, an IEx session): stored in the
process dictionary, the same "one process per request" isolation boundary Phoenix itself
already gives every request, and the direct Elixir analog to Thread.current in
gems/forge_ops_tracker's own equivalent. id/email/username are all independently
optional; call with an empty map (or nothing set at all) to clear whatever was set.
Functions
@spec capture_exception(term(), Exception.stacktrace(), map(), map() | nil) :: :ok
Report an exception (or any raised/thrown term: see ForgeOpsTracker.EventBuilder's own doc
for why this doesn't require a real Exception struct) you've already rescued yourself:
try do
charge_card(order)
rescue
e ->
ForgeOpsTracker.capture_exception(e, __STACKTRACE__, %{order_id: order.id})
reraise e, __STACKTRACE__
endstacktrace has to come from the actual rescue/catch site (__STACKTRACE__): unlike
languages where an exception object carries its own trace, Elixir's stacktrace is only
available via that special form, and only for as long as nothing else has run since the
rescue/catch (the same reason the example above captures it before doing anything else).
user, if not given, defaults to whatever set_user/1 last set for this process (nil if
nothing did); pass one explicitly to override that for this one report.
@spec init(keyword()) :: ForgeOpsTracker.Configuration.t()
Configures the client. Call once at startup: application.ex's own start/2, before the rest
of your supervision tree starts, is the natural place. Accepts the same keys as
ForgeOpsTracker.Configuration's struct fields:
ForgeOpsTracker.init(dsn: "...", environment: "production")Fields not passed here fall back to Application.get_env(:forge_ops_tracker, key) /
FORGE_OPS_DSN-style environment variables read when this app started: see
ForgeOpsTracker.Configuration's own module doc.
@spec install_handlers() :: :ok
Installs the :logger handler described in ForgeOpsTracker.LoggerHandler's own module doc.
Call once, after init/1. Safe to call more than once: a later call is a no-op.
Records one occurrence of transaction_name (a request, a database query, a queue job) taking
duration_ms, bucketed by kind ("controller"/"job"/"query"). Not something app code
normally calls directly: ForgeOpsTracker.Integrations.Phoenix/Ecto/Oban all call this once
wired up via their own attach/0/attach/1.
Re-checks Configuration.enabled?/1 and track_performance on every call, the same "guarded
every time, not just once at attach time" posture capture_exception/3 already has over
Reporter.report/3: config can change at runtime, so a :telemetry.attached handler that
checked this only once at startup could keep recording long after either flag turned off.
@spec set_user(map()) :: :ok
Manually attaches an affected user to whatever gets reported for the rest of this process
(a Phoenix request's own connection process, a GenServer, an IEx session): stored in the
process dictionary, the same "one process per request" isolation boundary Phoenix itself
already gives every request, and the direct Elixir analog to Thread.current in
gems/forge_ops_tracker's own equivalent. id/email/username are all independently
optional; call with an empty map (or nothing set at all) to clear whatever was set.