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 :details key (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

emit_and_stamp(repo, audit_log)

@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 :details key (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.