Boop.Event (BoopEx v1.1.0)

Copy Markdown View Source

An event to send to Boop. Only title is required.

FieldNotes
titlerequired, truncated to 200 characters
bodytruncated to 4000 characters
level:info (default), :success, :warning, :error, :critical
sourcewhat produced it, e.g. "cron"; defaults to the configured source
typea category within the source, e.g. "deploy"
external_idyour own id for the event
fingerprinta stable grouping key
occurred_atDateTime, NaiveDateTime (assumed UTC) or ISO 8601 string; defaults to now
dataa map of anything JSON-serialisable; sensitive keys are redacted before sending
actionsup to 3 buttons, [%{label: "Open deploy", url: "https://…"}], shown on the push and in the event

The keys exception, stacktrace, tags, context and breadcrumbs inside data get a rich rendering in Boop. See Boop.Event.exception/3 for a helper.

Fingerprints and grouping

Boop collapses events that share a fingerprint within a project into one inbox row ("KeyError ×47 · First seen 09:31 · Last seen 10:42") that opens the individual occurrences. Send a stable fingerprint for "the same thing happening again" ("#{module}-#{reason}", a job name, an alert id) and repeats stay tidy on the phone. Every occurrence is still stored and pushed.

Actions

An action is a button that opens a URL: on the notification itself (long-press it) and in the event detail on the web and the phone. Give a label of up to 40 characters and an absolute URL (https://… or an app scheme such as myapp://orders/42).

Boop.send(title: "Payment received", body: "£19.99", level: :success,
          actions: [%{label: "Open in Stripe", url: "https://dashboard.stripe.com/payments/pi_1"}])

Entries may be maps or keyword lists with :label/:url (atom or string keys), or {label, url} tuples. Labels are truncated; a missing label or URL is an error.

Summary

Functions

Builds one action for the actions field: a button that opens url.

Builds data for an error event from an exception and stacktrace, in the shape Boop renders richly.

The valid levels, in ascending severity.

Builds and validates an event from a title, keyword list, map, or %Boop.Event{}.

Converts an event to the JSON-ready map the server expects, redacting sensitive keys in data and dropping data (with a note in body) if it is still over 256 KB.

Types

action()

@type action() :: %{label: String.t(), url: String.t()}

level()

@type level() :: :info | :success | :warning | :error | :critical

t()

@type t() :: %Boop.Event{
  actions: [action()],
  body: String.t() | nil,
  data: map(),
  external_id: String.t() | nil,
  fingerprint: String.t() | nil,
  level: level(),
  occurred_at: DateTime.t() | nil,
  source: String.t() | nil,
  title: String.t() | nil,
  type: String.t() | nil
}

Functions

action(label, url)

@spec action(String.t(), String.t()) :: action()

Builds one action for the actions field: a button that opens url.

Boop.send(title: "Deploy failed", level: :error,
          actions: [Boop.Event.action("Open run", run_url), Boop.Event.action("Rollback", "myapp://rollback/42")])

exception(exception, stacktrace, extra \\ [])

@spec exception(Exception.t(), Exception.stacktrace(), keyword()) :: map()

Builds data for an error event from an exception and stacktrace, in the shape Boop renders richly.

rescue e -> Boop.send(title: inspect(e.__struct__), level: :error,
                      data: Boop.Event.exception(e, __STACKTRACE__, tags: %{env: "prod"}))

levels()

@spec levels() :: [level()]

The valid levels, in ascending severity.

new(input, config \\ [])

@spec new(String.t() | keyword() | map() | t(), Boop.Config.t() | keyword()) ::
  {:ok, t()} | {:error, Boop.Error.t()}

Builds and validates an event from a title, keyword list, map, or %Boop.Event{}.

Strings that exceed their limits are truncated rather than rejected. Returns {:error, %Boop.Error{code: :invalid}} when the title is missing or the level is unknown.

to_payload(event, config \\ [])

@spec to_payload(t(), Boop.Config.t() | keyword()) :: map()

Converts an event to the JSON-ready map the server expects, redacting sensitive keys in data and dropping data (with a note in body) if it is still over 256 KB.