Telemetry integration for mailglass.
Event Naming Convention
All mailglass events follow the 4-level path plus a phase suffix:
[:mailglass, :domain, :resource, :action, :start | :stop | :exception]Named span helpers wrap :telemetry.span/3 for each domain. Domain helpers
land in their owning phase (render in Phase 1, send/batch in Phase 3,
persist/events in Phase 2, webhook_verify/webhook_ingest in Phase 4,
preview_render in Phase 5).
Phase 1 Events
Render pipeline
[:mailglass, :render, :message, :start | :stop | :exception]— Measurements on:start:%{system_time: integer}— Measurements on:stop:%{duration: native_time}— Metadata:%{tenant_id: string, mailable: atom}
Metadata Policy (D-31)
Whitelisted keys: :tenant_id, :mailable, :provider, :status, :message_id, :delivery_id, :event_id, :latency_ms, :recipient_count, :bytes, :retry_count.
Forbidden (PII): :to, :from, :body, :html_body, :subject, :headers, :recipient, :email.
Enforcement is lint-time (Phase 6 custom Credo check NoPiiInTelemetryMeta)
plus a runtime StreamData property test that asserts every emitted stop
event's metadata keys are a subset of the whitelist across 1000 varied
inputs.
Handler Isolation
:telemetry.span/3 wraps each attached handler in a try/catch. A handler
that raises is detached automatically and [:telemetry, :handler, :failure]
is emitted — the caller's pipeline is unaffected. Mailglass does not
add a parallel try/rescue wrapper (would duplicate or — worse — swallow
the meta-event operators rely on).
Default Logger
Call attach_default_logger/1 at boot (or configure
[telemetry: [default_logger: true]] in the Application env) to log every
Mailglass event:
Mailglass.Telemetry.attach_default_logger()
Mailglass.Telemetry.attach_default_logger(level: :warning)
Summary
Functions
Attaches the default logger handler for the Phase 1 event set.
Named span helper wrapping the adapter.deliver/2 call (Phase 3, D-26).
Named span helper for the events-append write path. Phase 2 surface.
One-shot wrapper around :telemetry.execute/3 for non-span counter events.
Named span helper wrapping each Multi commit in the send pipeline (Phase 3, D-26).
Named span helper for persist-layer write paths (projector, reconciler). Phase 2 surface.
Named span helper for the render pipeline. Phase 1 surface.
Named span helper for the Outbound hot path (Phase 3, D-26).
Wraps a zero-arity function in :telemetry.span/3, emitting :start,
:stop, and (on exception) :exception events under event_prefix.
Functions
@spec attach_default_logger(keyword()) :: :ok | {:error, :already_exists}
Attaches the default logger handler for the Phase 1 event set.
Returns :ok on first attach and {:error, :already_exists} if a handler
with the same ID is already attached (useful for idempotent boot paths).
Options
:level— log level passed toLogger.log/2. Default::info.
Named span helper wrapping the adapter.deliver/2 call (Phase 3, D-26).
Emits [:mailglass, :outbound, :dispatch, :start | :stop | :exception].
Provider latency is the fat tail — this span captures it.
Named span helper for the events-append write path. Phase 2 surface.
Equivalent to span([:mailglass, :events, :append], metadata, fun).
:stop metadata SHOULD include inserted?: boolean and
idempotency_key_present?: boolean per D-04.
One-shot wrapper around :telemetry.execute/3 for non-span counter events.
Callers are expected to prepend :mailglass to the event path.
Named span helper wrapping each Multi commit in the send pipeline (Phase 3, D-26).
| Emits `[:mailglass, :persist, :outbound, :multi, :start | :stop | :exception]`. |
Metadata carries :step_name (`:persist_queued | :persist_dispatched | :persist_failed`). |
Named span helper for persist-layer write paths (projector, reconciler). Phase 2 surface.
Event path: [:mailglass, :persist | suffix]. Examples:
Mailglass.Telemetry.persist_span([:delivery, :update_projections], meta, fn -> ... end)
Mailglass.Telemetry.persist_span([:reconcile, :link], meta, fn -> ... end)
Named span helper for the render pipeline. Phase 1 surface.
Equivalent to span([:mailglass, :render, :message], metadata, fun).
Named span helper for the Outbound hot path (Phase 3, D-26).
Emits [:mailglass, :outbound, :send, :start | :stop | :exception].
Metadata whitelist per D-31: :tenant_id, :mailable, :stream, :delivery_id, :status, :latency_ms.
Wraps a zero-arity function in :telemetry.span/3, emitting :start,
:stop, and (on exception) :exception events under event_prefix.
The same metadata map is emitted on every phase. The function's return value is returned unchanged.
Examples
Mailglass.Telemetry.span([:mailglass, :render, :message],
%{tenant_id: "acme", mailable: MyMailer},
fn -> render(message) end)