Skip to main content

guides/telemetry.md

# Telemetry

mailglass emits standard `:telemetry` spans on every entry point — delivery, rendering, webhook ingest, and reconciliation.

## Prerequisites

- `telemetry` dependency available (installed by default)
- An event handler attached to `:mailglass` events

## Available Spans

The following spans include `[ID, :start | :stop | :exception]` events:

- `[:mailglass, :deliver]` — synchronous delivery pipeline
- `[:mailglass, :render]` — render pipeline (HEEx to HTML/Text)
- `[:mailglass, :webhook, :ingest]` — webhook verification and ingest
- `[:mailglass, :reconcile]` — delivery status reconciliation

## PII Whitelist

Telemetry metadata includes:
- `tenant_id`
- `message_id`
- `stream` (e.g. transactional)
- `adapter`
- `status`
- `latency`

It **never** includes recipient addresses, subject lines, or message bodies.

## Example: Logging delivery latency

```elixir
:telemetry.attach(
  "log-delivery",
  [:mailglass, :deliver, :stop],
  fn _name, measurements, metadata, _config ->
    Logger.info("Delivered message #{metadata.message_id} in #{measurements.duration}ms")
  end,
  nil
)
```

## End-to-End Example

```elixir
:telemetry.attach(
  "test-telemetry",
  [:mailglass, :render, :stop],
  fn _name, _measurements, metadata, _config ->
    send(self(), {:telemetry_rendered, metadata.function})
  end,
  nil
)

MyApp.UserMailer.welcome(%{email: "alice@example.com"})
|> Mailglass.Renderer.render()

assert_receive {:telemetry_rendered, :welcome}
```