Instrumentation façade for Chimeway telemetry spans.
All lifecycle telemetry in Chimeway routes through this module so that event naming is consistent and metadata is redacted before emission.
Event Catalog
Chimeway emits the following :telemetry span events. Each span produces
three events: [:..., :start], [:..., :stop], and [:..., :exception].
| Span | Event name | Metadata keys |
|---|---|---|
| Event creation | [:chimeway, :events, :create] | notification_key, event_id, correlation_id |
| Delivery planning | [:chimeway, :deliveries, :plan] | notification_key, event_id, recipient_id |
| Policy evaluation | [:chimeway, :policy, :evaluate] | delivery_id, notification_key, channel |
| Sync dispatch | [:chimeway, :dispatch, :sync] | delivery_id, notification_key, channel |
| Oban enqueue (optional) | [:chimeway, :dispatch, :enqueue] | delivery_id, notification_key |
| Oban perform (optional) | [:chimeway, :dispatch, :perform] | delivery_id, notification_key |
| Attempt record | [:chimeway, :attempts, :record] | attempt_id, delivery_id, outcome |
The two Oban spans are only emitted when Oban is present in the dependency tree.
PII Redaction
safe_meta/1 strips any key not in the allowed set before metadata is passed
to :telemetry.span/3. This prevents sensitive payload fields (email addresses,
template content, provider API responses) from appearing in telemetry handlers.
Allowed keys: notification_key, event_id, recipient_id, channel,
delivery_id, attempt_id, outcome, suppression_reason, correlation_id,
attempt_number, error_class, adapter_module
All metadata that call sites pass to span/3 must be pre-filtered:
Chimeway.Telemetry.span([:events, :create], safe_meta(%{
notification_key: key,
event_id: id,
correlation_id: cid
}), fn ->
result = do_create_event()
{result, %{event_id: id}}
end)Attaching Handlers
Chimeway does NOT auto-attach handlers at library startup. Call
attach_default_handlers/0 explicitly in your application's start/2:
def start(_type, _args) do
Chimeway.Telemetry.attach_default_handlers()
# ...
endTo attach a custom handler:
:telemetry.attach_many(
:my_handler,
[
[:chimeway, :events, :create, :stop],
[:chimeway, :dispatch, :sync, :stop]
],
&MyApp.TelemetryHandler.handle/4,
nil
)Example: Forwarding to StatsD / Datadog
defmodule MyApp.ChimewayStatsD do
def handle([:chimeway, :dispatch, :sync, :stop], measurements, meta, _config) do
tags = ["channel:#{meta.channel}", "key:#{meta.notification_key}"]
Statix.timing("chimeway.dispatch.sync", measurements.duration, tags: tags)
end
end
Summary
Functions
Attaches a Logger-based default telemetry handler for all Chimeway spans.
Filters a metadata map to the allowed telemetry keys only.
Wraps a function with a :telemetry span using Chimeway's 4-level event prefix.
Functions
@spec attach_default_handlers() :: :ok
Attaches a Logger-based default telemetry handler for all Chimeway spans.
Logs :stop events at :debug level and :exception events at :warning level.
Idempotent — calling this function multiple times does not crash or double-attach.
Must be called explicitly by the host application. Chimeway does not
auto-attach handlers at startup. A typical place is Application.start/2:
def start(_type, _args) do
Chimeway.Telemetry.attach_default_handlers()
children = [...]
Supervisor.start_link(children, strategy: :one_for_one)
end
Filters a metadata map to the allowed telemetry keys only.
Drops any key not in the allowed set. Normalizes both atom and string keys to atoms before filtering. This is the single enforcement point for PII redaction in Chimeway telemetry.
Allowed keys
notification_key, event_id, recipient_id, channel, delivery_id, attempt_id, outcome, suppression_reason, correlation_id, attempt_number, error_class, adapter_module
Example
iex> Chimeway.Telemetry.safe_meta(%{notification_key: "order_shipped", email: "user@example.com"})
%{notification_key: "order_shipped"}
Wraps a function with a :telemetry span using Chimeway's 4-level event prefix.
event_suffix is appended to [:chimeway], e.g. [:events, :create]
produces [:chimeway, :events, :create, :start/stop/exception].
The function func must return {result, extra_stop_meta} where
extra_stop_meta is merged into the stop event metadata by :telemetry.span/3.
Pass through safe_meta/1 on any extra stop metadata to prevent PII leakage
from the stop event.
Returns result.