http_gun/telemetry

Describes the [http_gun, lifecycle] event that every client emits as a request moves through admission, submission, headers and termination.

Events are best effort: a missing event is not submission evidence or permission to retry. They carry no URL, header, query or body.

HTTP Gun emits with sinal.emit, so the application decides where handlers run. Route the prefix to a forwarder once at startup to keep handlers out of HTTP Gun’s pool and body processes:

forwarder.route(["http_gun"], my_forwarder)
let attachment = sinal.observe(telemetry.event(), fn(timing, metadata) {
  record(metadata.request_id, metadata.milestone, timing.monotonic_ms)
})

Without a route, handlers run synchronously in the pool and body processes, and a slow handler slows requests. config.with_observations sends one client’s events to a forwarder directly instead, and config.without_observations makes a client emit nothing.

Every event’s metadata carries two identities:

A third key names the client:

A library that starts its own private client labels it with the library’s name, such as "hellhound", so an application’s node-wide handler can filter it. A library may instead silence its client with config.without_observations; labelling is preferred, because it leaves the application the choice.

Types

One lifecycle event’s metadata. Read it by label: a later release may add a field.

pub type Metadata {
  Metadata(
    request_id: RequestId,
    correlation: option.Option(correlation.Correlation),
    client: option.Option(String),
    mode: Mode,
    milestone: Milestone,
  )
}

Constructors

pub type Milestone {
  AdmissionEntered
  AdmissionWaiting
  AdmissionGranted
  GunCallReturned
  ResponseHeaders(status: Int)
  HttpTerminated(Outcome)
}

Constructors

  • AdmissionEntered

    The pool received a validated invocation, before admission/capture reservation.

  • AdmissionWaiting

    The invocation entered the finite queue, waiting for capacity or connection setup.

  • AdmissionGranted

    The pool selected an eligible connection/stream or matched an offline exchange.

  • GunCallReturned

    Gun’s asynchronous request API returned. No transport processing, successful socket write, remote receipt or application effect is established by this fact.

  • ResponseHeaders(status: Int)

    Final response headers passed HTTP Gun’s admission checks.

  • HttpTerminated(Outcome)

    The HTTP owner settled its outcome. Abrupt actor/VM death can omit this event.

Scripts and disk playback both report Offline; neither claims network activity.

pub type Mode {
  Live
  Recorded
  Offline
}

Constructors

  • Live
  • Recorded
  • Offline

HTTP termination, independent of observation delivery and capture persistence. Complete means HTTP EOF, not that the application consumed or accepted the body.

pub type Outcome {
  Complete
  LocallyCancelled
  DeadlineExpired
  Failed
}

Constructors

  • Complete
  • LocallyCancelled
  • DeadlineExpired
  • Failed

A random UUID v4 identifying one observed invocation. It is not a credential, a durable receipt or a network reference. Erlang handlers see it as a binary under the request_id key.

pub opaque type RequestId
pub type Timing {
  Timing(monotonic_ms: Int)
}

Constructors

  • Timing(monotonic_ms: Int)

Values

pub fn event() -> sinal.Event(Timing, Metadata)

The typed [http_gun, lifecycle] event. Attach handlers through Sinal in the application. Handler arrival order across the pool and body processes is not a request ordering guarantee: compare monotonic_ms and the milestone’s meaning.

pub fn new_request_id() -> RequestId

A fresh random UUID v4, probabilistically unique across nodes and restarts. HTTP Gun creates one per request; a test double that emits HTTP Gun events can create its own.

pub fn request_id_to_string(id: RequestId) -> String

The identity as text, for logs.

✨ Search Document