AuditTrail. ControllerAudit
(audit_trail v0.1.0)
Copy Markdown
Plug for declarative controller-level audit logging.
Declare at the top of a controller which actions to audit and under what
event name. The plug hooks into register_before_send so it captures the
final response status without you touching each function body.
Usage
plug AuditTrail.ControllerAudit,
write: [
api_login: "auth:login",
api_logout: "auth:logout",
api_register: "user:registered",
api_reset_password: "auth:password_reset"
],
read: [
api_verify: "auth:session"
]Behaviour
writeactions are logged regardless of response status (success or error both matter for the audit trail).readactions are only logged on 2xx responses — failed reads are noise.- Sensitive params (
password,code,token, etc.) are stripped automatically before the payload is stored. - Oversized values (file uploads, base64 blobs, huge lists) are truncated
automatically before the payload is stored — see
@max_value_bytes/@max_list_items. - The actor is read from the process dictionary at
before_sendtime, so login flows that callAuditTrail.set_actor/1mid-action are captured correctly.
Resource and operation tagging (optional)
By default the logged payload only carries action and event_type. To
also tag what resource was touched and which CRUD operation happened,
pass an optional resource: and split actions across create:, read:,
update:, delete: instead of (or alongside) write:/read::
plug AuditTrail.ControllerAudit,
resource: "payment",
create: [api_charge: "payment:charged"],
update: [api_refund: "payment:refunded"],
delete: [api_void: "payment:voided"],
read: [api_show: "payment:viewed"]create, update, and delete behave exactly like write (logged on
success and failure) but additionally set operation to "create",
"update", or "delete" in the payload, so you can filter logs by CRUD
operation. write still works unchanged and tags operation: "write".
None of this is required — omit resource: and keep using write/read
exactly as before.
Capturing the specific record (optional)
To filter the audit trail down to one record (e.g. "every log entry for
this one payment"), the payload also carries resource_id. It's picked
up automatically from conn.params["id"] or conn.params["uuid"] — no
setup needed if your route already uses either key. If your param is
named something else, point at it explicitly:
plug AuditTrail.ControllerAudit,
resource: "idf",
id_param: "uuid", # or :uuid — matches conn.params["uuid"]
update: [api_update_idf: "idf:updated"]resource_id is nil if neither the default keys nor id_param: match
anything in conn.params — existing controllers need no changes.