Skip to content

Audit Logging

The core.audit system provides centralized, structured logging of all important business actions.

It ensures that all critical changes in the system are:

  • traceable
  • consistent
  • queryable
  • debuggable

Audit logging is a core infrastructure feature and is used across all apps.


Purpose

Audit logs exist to answer:

  • Who did what?
  • When did it happen?
  • What changed?
  • On which object?

They are essential for:

  • debugging
  • compliance
  • accountability
  • analytics
  • incident investigation

Core Concept

All audit logging is performed through a single helper:

log_audit(...)

This function creates an AuditLog entry for any model instance.


Audit Log Model

Each audit entry contains:

  • actor → user who performed the action (nullable)
  • action → string describing the event
  • object_repr → human-readable object representation
  • object_pk → primary key (string)
  • content_type → model type
  • object_id → object identifier (string)
  • changes → structured JSON describing what changed
  • ip → request IP address
  • user_agent → client user agent
  • created_at → timestamp

Logging an Action

Example usage:

log_audit( instance=membership, actor=request.user, action="org_membership.role_changed", changes={ "role": { "old": "engineer", "new": "manager", } }, request=request, )


Action Naming Convention

Actions follow a consistent naming pattern:

.

Examples:

  • team.created
  • team.updated
  • team.deactivated
  • team.reactivated

  • team_membership.added

  • team_membership.updated
  • team_membership.role_changed
  • team_membership.deactivated
  • team_membership.reactivated

  • org_membership.created

  • org_membership.updated
  • org_membership.role_changed
  • org_membership.deactivated
  • org_membership.reactivated

Changes Format

The changes field must be:

  • JSON-serializable
  • minimal
  • structured

Standard pattern

{ "field_name": { "old": , "new": } }

Example

{ "role": { "old": "engineer", "new": "manager" }, "is_active": { "old": true, "new": false } }


Metadata

If a request is provided:

  • IP address is extracted from request.META
  • user agent is extracted from request headers

If no request is provided: - metadata fields remain empty


Where Audit Logging Happens

Audit logging is performed in the service layer, not in views.

Why?

Because:

  • services define business logic
  • services know what actually changed
  • views should remain thin
  • logging must not depend on HTTP layer

When to Log

Audit logs should be created when:

  • objects are created
  • objects are updated
  • objects are deactivated or reactivated
  • roles or permissions change
  • ownership or relationships change

When NOT to Log

Avoid logging:

  • read operations
  • trivial or derived state changes
  • idempotent operations (no actual change)
  • internal helper updates with no business meaning

Idempotency

Audit logs should only be created when something actually changes.

Example:

  • updating a team with the same data → no audit log
  • deactivating an already inactive object → no audit log

This prevents noise in the audit trail.


Querying Audit Logs

Helper functions are provided:

By object

list_audit_logs_for_object(instance=team)

By actor

list_audit_logs_for_actor(actor=user)

By action

list_audit_logs_for_action(action="team.updated")


Data Model Relationship

flowchart TD
    A[User] --> B[AuditLog]
    C[Any Model] --> B
    B --> D[Changes JSON]
- Any model can be linked via content_type + object_id - This uses Django’s GenericForeignKey


Integration Example

Example: updating a team

  1. Service validates input
  2. Service determines changed fields
  3. Service updates model
  4. Service calls log_audit
  5. Audit entry is persisted

Logging Strategy

The system follows:

  • event-based logging (not field-level hooks)
  • explicit logging (no hidden magic)
  • service-controlled logging

This ensures clarity and avoids unexpected behavior.


Benefits

Audit logging provides:

  • full traceability of changes
  • consistent debugging information
  • structured data for analytics
  • foundation for future features (history UI, activity feeds)

Future Extensions

The audit system can be extended with:

  • UI for audit history
  • filtering and pagination APIs
  • export capabilities
  • real-time activity streams
  • soft-delete tracking
  • field-level diff visualization

Summary

The audit system is a critical part of the backend infrastructure.

It ensures that all important actions are:

  • recorded
  • structured
  • accessible

This improves reliability, transparency, and long-term maintainability of the system.