brazier/telemetry

Telemetry for Brazier, built on the Erlang telemetry library.

Handlers attach to event names and receive an Event for every matching emit. Brazier’s own events all start with prefix and are listed by catalogue; see docs/TELEMETRY.md for their measurements and metadata.

let assert Ok(Nil) =
  telemetry.attach("http-logger", [["brazier", "http", "request", "stop"]], fn(event) {
    let assert Ok(duration) = telemetry.int(event, "duration")
      as "every stop event measures its duration"
    io.println("request took " <> int.to_string(duration))
  })
  as "the handler id is unique"

Types

pub type ConnectionOutcome {
  Accepted
  Rejected
  Closed
}

Constructors

  • Accepted
  • Rejected
  • Closed

One emitted event, as a handler receives it. Measurement and metadata keys are strings; values keep the type they were emitted with.

pub type Event {
  Event(
    name: List(String),
    measurements: dict.Dict(String, dynamic.Dynamic),
    metadata: dict.Dict(String, dynamic.Dynamic),
  )
}

Constructors

Why the runtime forgot a connection without being told it disconnected.

pub type ForgetReason {
  ConnectionSlow
  ConnectionDown
}

Constructors

  • ConnectionSlow

    Its handler’s mailbox held more than the runtime’s limit: it was told to close (1013).

  • ConnectionDown

    Its handler had exited: a send found no process, or the runtime handled the DOWN of its monitor.

pub type NodeDirection {
  NodeUp
  NodeDown
}

Constructors

  • NodeUp
  • NodeDown
pub type PresenceEvent {
  Track
  Untrack
  LimitExceeded
}

Constructors

  • Track
  • Untrack
  • LimitExceeded
pub type ReplicaState {
  ReplicaUp
  ReplicaDown
  ReplicaPermdown
}

Constructors

  • ReplicaUp
  • ReplicaDown
  • ReplicaPermdown
pub type RuntimeSpan {
  Mount
  HandleEvent
  Navigate
}

Constructors

  • Mount
  • HandleEvent
  • Navigate
pub type SessionEvent {
  Created
  Revoked
  Expired
  Contention
}

Constructors

  • Created
  • Revoked
  • Expired
  • Contention
pub type SubscriptionAction {
  Subscribe
  Unsubscribe
}

Constructors

  • Subscribe
  • Unsubscribe
pub type TelemetryError {
  AlreadyAttached(id: String)
  NotAttached(id: String)
  InvalidEventName(String)
  InvalidHandlerId(String)
  StartFailed(reason: String)
}

Constructors

  • AlreadyAttached(id: String)

    A handler with this id is already attached.

  • NotAttached(id: String)

    No handler with this id is attached.

  • InvalidEventName(String)

    The event name is empty or has an empty or over-long segment.

  • InvalidHandlerId(String)

    Handler ids must be 1 to 255 bytes.

  • StartFailed(reason: String)

    The telemetry application could not be started.

Values

pub fn attach(
  id: String,
  events: List(List(String)),
  handler: fn(Event) -> Nil,
) -> Result(Nil, TelemetryError)

Attach handler to every event in events. Each event name is a list of segments, for example ["brazier", "pubsub", "broadcast"].

pub fn catalogue() -> List(List(String))

Every event name Brazier emits. Spans are listed as their start, stop and exception events.

pub fn detach(id: String) -> Result(Nil, TelemetryError)

Detach the handler with this id.

pub fn execute(
  name: List(String),
  measurements: dict.Dict(String, Int),
  metadata: dict.Dict(String, String),
) -> Result(Nil, TelemetryError)

Emit an event from application code. Keys stay strings, so this never creates atoms. When no handler has ever been attached to name, there is nothing to deliver and this returns Ok(Nil) without emitting.

pub fn int(event: Event, key: String) -> Result(Int, Nil)

An integer measurement, or an integer metadata value when no measurement has that key.

pub const prefix: String

The first segment of every event Brazier emits.

pub fn span(
  name: List(String),
  metadata: dict.Dict(String, String),
  run: fn() -> a,
) -> a

Run run inside a span: name ++ ["start"] is emitted before it and name ++ ["stop"] after it, with duration in native time units. If run crashes, name ++ ["exception"] is emitted with kind, reason and stacktrace, and the crash is re-raised unchanged.

Crashes if name is empty or has an empty segment: span names come from code, so an invalid one is a programming error.

pub fn start() -> Result(Nil, TelemetryError)

Start the telemetry application and attach the logger for crashed handlers. Idempotent. Brazier’s subsystems call it when they start.

pub fn string(event: Event, key: String) -> Result(String, Nil)

A string metadata value (atoms such as a span’s kind are converted), or a string measurement when no metadata value has that key.

✨ Search Document