LatticeStripe.Telemetry (LatticeStripe v1.1.0)

Copy Markdown View Source

Telemetry integration for LatticeStripe.

LatticeStripe emits :telemetry events for all HTTP requests and webhook signature verification. Attach handlers to these events to integrate with your observability stack (Prometheus, DataDog, OpenTelemetry, etc.).

HTTP Request Events

[:lattice_stripe, :request, :start]

Emitted before each HTTP request is dispatched.

Measurements:

KeyTypeDescription
:system_timeintegerSystem time at span start (in native time units). See System.system_time/0.
:monotonic_timeintegerMonotonic time at span start. See System.monotonic_time/0.

Metadata:

KeyTypeDescription
:methodatomHTTP method atom: :get, :post, :delete
:pathString.t()Request path, e.g. "/v1/customers"
:resourceString.t()Parsed resource name, e.g. "customer", "payment_intent", "checkout.session"
:operationString.t()Parsed operation name, e.g. "create", "retrieve", "list", "confirm"
:api_versionString.t()Stripe API version, e.g. "2026-03-25.dahlia"
:stripe_accountString.t() | nilConnected account ID from Stripe-Account header, or nil
:telemetry_span_contextreferenceAuto-injected by :telemetry.span/3 for correlating start/stop/exception events

[:lattice_stripe, :request, :stop]

Emitted after each HTTP request completes (success or API error).

Measurements:

KeyTypeDescription
:durationintegerElapsed time in native time units. Convert via System.convert_time_unit/3.
:monotonic_timeintegerMonotonic time at span stop.

Metadata (all start fields plus):

KeyTypeDescription
:methodatomHTTP method atom
:pathString.t()Request path
:resourceString.t()Parsed resource name
:operationString.t()Parsed operation name
:api_versionString.t()Stripe API version
:stripe_accountString.t() | nilConnected account ID or nil
:status:ok | :errorOutcome of the request
:http_statusinteger | nilHTTP status code (nil for connection errors)
:request_idString.t() | nilStripe request-id header value
:attemptsintegerTotal attempts made (1 = no retries, 2 = one retry, etc.)
:retriesintegerNumber of retries (attempts - 1)
:error_typeatom | nilError type atom on failure: :connection_error, :card_error, etc.
:idempotency_keyString.t() | nilIdempotency key used (on error only)
:telemetry_span_contextreferenceCorrelates with start event

[:lattice_stripe, :request, :exception]

Emitted when an uncaught exception or throw escapes the request function. This covers transport-level bugs, not API errors (which produce [:lattice_stripe, :request, :stop] with status: :error). Handled automatically by :telemetry.span/3.

Measurements:

KeyTypeDescription
:durationintegerElapsed time in native time units
:monotonic_timeintegerMonotonic time at exception

Metadata:

KeyTypeDescription
:methodatomHTTP method atom
:pathString.t()Request path
:resourceString.t()Parsed resource name
:operationString.t()Parsed operation name
:api_versionString.t()Stripe API version
:stripe_accountString.t() | nilConnected account ID or nil
:kind:error | :exit | :throwException kind
:reasonanyException reason
:stacktracelistException stacktrace
:telemetry_span_contextreferenceCorrelates with start event

[:lattice_stripe, :request, :retry]

Emitted for each retry attempt before the retry delay sleep.

Measurements:

KeyTypeDescription
:attemptintegerRetry attempt number (1 = first retry after initial failure)
:delay_msintegerDelay in milliseconds before the retry

Metadata:

KeyTypeDescription
:methodatomHTTP method atom
:pathString.t()Request path
:error_typeatomError type that triggered the retry
:statusinteger | nilHTTP status code (nil for connection errors)

Webhook Verification Events

[:lattice_stripe, :webhook, :verify, :start]

Emitted before webhook signature verification begins.

Measurements:

KeyTypeDescription
:system_timeintegerSystem time at span start
:monotonic_timeintegerMonotonic time at span start

Metadata:

KeyTypeDescription
:pathString.t() | nilRequest path where webhook was received, if available
:telemetry_span_contextreferenceAuto-injected for span correlation

[:lattice_stripe, :webhook, :verify, :stop]

Emitted after webhook signature verification completes.

Measurements:

KeyTypeDescription
:durationintegerElapsed time in native time units
:monotonic_timeintegerMonotonic time at span stop

Metadata:

KeyTypeDescription
:pathString.t() | nilRequest path where webhook was received
:result:ok | :errorVerification outcome
:error_reasonatom | nilFailure reason: :invalid_signature, :stale_timestamp, :missing_header, :no_valid_signature, or nil on success
:telemetry_span_contextreferenceCorrelates with start event

[:lattice_stripe, :webhook, :verify, :exception]

Emitted when an uncaught exception escapes webhook verification. Handled automatically by :telemetry.span/3.

Measurements:

KeyTypeDescription
:durationintegerElapsed time in native time units
:monotonic_timeintegerMonotonic time at exception

Metadata:

KeyTypeDescription
:pathString.t() | nilRequest path
:kind:error | :exit | :throwException kind
:reasonanyException reason
:stacktracelistException stacktrace
:telemetry_span_contextreferenceCorrelates with start event

Usage with Telemetry.Metrics

If you're using telemetry_metrics with Prometheus or StatsD, here are ready-to-use metric definitions:

[
  # Request latency by resource and operation
  Telemetry.Metrics.summary("lattice_stripe.request.stop.duration",
    tags: [:resource, :operation, :status],
    unit: {:native, :millisecond}
  ),

  # Request throughput by outcome
  Telemetry.Metrics.counter("lattice_stripe.request.stop",
    tags: [:resource, :operation, :status]
  ),

  # Latency distribution (p50/p95/p99)
  Telemetry.Metrics.distribution("lattice_stripe.request.stop.duration",
    tags: [:resource, :operation],
    unit: {:native, :millisecond}
  ),

  # Retry rate by error type
  Telemetry.Metrics.counter("lattice_stripe.request.retry",
    tags: [:error_type]
  ),

  # Webhook verification outcomes
  Telemetry.Metrics.counter("lattice_stripe.webhook.verify.stop",
    tags: [:result, :error_reason]
  )
]

Invoice Auto-Advance Events

[:lattice_stripe, :invoice, :auto_advance_scheduled]

Emitted after a successful Invoice.create/3 when the returned invoice has auto_advance: true. This signals that Stripe will automatically finalize the draft invoice after approximately 1 hour. Attach a handler to log a warning or trigger a monitoring alert when auto-advance invoices are created.

Measurements:

KeyTypeDescription
:system_timeintegerSystem time at emission (in native time units). See System.system_time/0.

Metadata:

KeyTypeDescription
:invoice_idString.t()The created invoice ID (e.g. "in_123")
:customerString.t() | nilCustomer ID associated with the invoice, or nil

Attaching a Default Logger

For instant visibility during development or to log all Stripe requests in production, use attach_default_logger/1:

# In your application start/2:
LatticeStripe.Telemetry.attach_default_logger()

# Or with options:
LatticeStripe.Telemetry.attach_default_logger(level: :debug)

This logs one line per request in the format:

[info] POST /v1/customers => 200 in 145ms (1 attempt, req_abc123)
[warn] GET /v1/payment_intents/pi_123 => :error in 301ms (3 attempts, connection_error)
[warning] Invoice in_123 (customer: cus_456) has auto_advance: true  Stripe will auto-finalize in ~1 hour

Converting Duration

The :duration measurement is in native time units. Convert to milliseconds:

duration_ms = System.convert_time_unit(duration, :native, :millisecond)

Summary

Functions

Attaches a default structured logger for all LatticeStripe request events.

Functions

attach_default_logger(opts \\ [])

@spec attach_default_logger(keyword()) :: :ok

Attaches a default structured logger for all LatticeStripe request events.

Safe to call multiple times -- detaches any existing handler with the same ID first.

Options

  • :level -- log level (default: :info)

Example

LatticeStripe.Telemetry.attach_default_logger(level: :info)

Logs one line per completed request:

[info] POST /v1/customers => 200 in 145ms (1 attempt, req_abc123)
[warning] GET /v1/customers/cus_xxx => 404 in 12ms (1 attempt, req_yyy)

Also logs a warning when an invoice is created with auto_advance: true:

[warning] Invoice in_123 (customer: cus_456) has auto_advance: true  Stripe will auto-finalize in ~1 hour