Fort. Audit. Emitter
(fort_audit v0.1.0)
Copy Markdown
Synchronous Logger emission for committed audit log rows.
At-least-once: a crash between the Logger call and the emitted_at
DB stamp may cause re-emission on restart. Downstream consumers should
dedupe on audit_logs.id for exactly-once processing.
Label/body metadata split
To prevent accidental label-cardinality explosions in metrics-oriented backends (Loki, Datadog, Elasticsearch), Logger metadata is split into two tiers:
- Labels — configured via
:logger_label_fields; emitted as top-level metadata keys (indexed fields in most collectors). Default:[:outcome, :actor_type, :subject_type]. - Body — everything else nests under a single
:detailskey (a single JSON object, not N individual indexed fields).
This split is conservative by default: :outcome (2 values) and
:actor_type/:subject_type (bounded by schema design) are safe
as labels. :action, :actor_id, :subject_id, :category, and
:audit_log_id are excluded from the default — applications with
genuinely bounded action vocabularies can opt them in explicitly:
config :fort_audit, :logger_label_fields, [:outcome, :action]
Summary
Functions
Emits a Logger line for the given AuditLog and stamps emitted_at.
Functions
@spec emit_and_stamp(Ecto.Repo.t(), Fort.Schemas.AuditLog.t()) :: {:ok, Fort.Schemas.AuditLog.t()}
Emits a Logger line for the given AuditLog and stamps emitted_at.
The log level is :info for "success" outcome and :error for
"failure", matching the field shape used by earlier versions of
Fort.Audit.
Logger metadata is split into two tiers based on :logger_label_fields
config (default [:outcome, :actor_type, :subject_type]):
- Labels — top-level metadata keys (indexed by Loki Promtail, Datadog, Elasticsearch, etc.)
- Body — nested under a single
:detailskey (a single JSON object, not individual indexed fields)
This prevents accidentally unbounded fields (actor_id, audit_log_id,
etc.) from creating label-cardinality explosions in metrics-oriented
backends.
Returns {:ok, updated_audit_log} where the returned struct has
emitted_at populated.