Skip to main content

Foxtrot November shared audit-logging library for Django/DRF micro-services

Project description

ftn-audit

Shared Django/DRF audit logging library with asynchronous OTLP delivery via Celery.

What this package includes

  • Request and user context capture via middleware (AuditContextMiddleware)
  • Signal receivers (pre_save, post_save, post_delete, m2m_changed)
  • Formatter registry with route-aware and event-aware selection
  • Generic formatter fallback when no custom formatter is registered
  • Delivery strategies (NoopAuditStrategy, OtlpAuditStrategy)
  • Celery task for OTLP emission
  • Unit and integration tests with pytest + pytest-django

Requirements

  • Python 3.11+
  • pip

Minimal Django integration

1) Install app and middleware

# settings.py
INSTALLED_APPS = [
    # ...
    "ftn_audit.apps.FtnAuditConfig",
]

MIDDLEWARE = [
    # ...
    "ftn_audit.middleware.AuditContextMiddleware",
]

2) Configure Celery task discovery

# celery.py
from celery import Celery

app = Celery("service_name")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks()

3) Register formatters in each app

# my_app/audit_formatters.py
from ftn_audit import register_audit_formatter, AbstractAuditLogFormatter
from .models import MyModel


@register_audit_formatter(MyModel)
class MyFormatter(AbstractAuditLogFormatter):
    def get_description(self) -> str:
        return f"Updated MyModel #{self.subject.pk}"

    def get_attributes(self):
        attrs = self.get_default_attributes()
        attrs["my.attr"] = "value"
        return attrs

Formatter resolution order:

  1. (raw_route + event_type)
  2. (raw_route)
  3. (event_type)
  4. (default)

priority is only applied inside the same specificity tier.

4) Recommended settings

AUDIT_ENABLED = True
AUDIT_DELIVERY_MODE = "celery"  # celery | sync | noop
AUDIT_OTLP_FALLBACK = "structured_log"  # structured_log | drop
AUDIT_STRICT_FORMATTER_VALIDATION = True
AUDIT_AUTO_CONNECT_SIGNALS = True  # optional, default True
AUDIT_AUTO_DISCOVER_FORMATTERS = True  # optional, default True
AUDIT_CHANGESET_CHECK_RELATIONSHIP = True  # optional, include FK changes in changeset

Migration notes

  • Foreign-key auditing: AUDIT_CHANGESET_CHECK_RELATIONSHIP defaults to True. Set it to False only if your service explicitly wants to skip FK changes in update changesets.
  • Formatter raw_route compatibility: middleware now emits canonical placeholders (:name). Update formatter raw_route= registrations from legacy forms (<type:name>, (?P<name>...)) to :name.
  • Import path rename: ftn_audit.jobs was renamed to ftn_audit.tasks. Update imports, e.g. from ftn_audit.tasks import emit_audit_log_task.

Error handling and safeguards

  • Audit code should never break request execution: all middleware/receiver/strategy exceptions are caught and logged.
  • Enqueue failures are logged and dropped.
  • OTLP emission failures in Celery use bounded retries.
  • OTLP enqueue is registered via transaction.on_commit, so events are emitted only after commit.
  • Signal handlers ignore raw=True fixture loads to avoid spurious audit events.
  • Changesets are filtered by update_fields when present, so only persisted fields are audited.
  • M2M payload safety: PK sets are capped (M2M_PK_SET_MAX) to avoid oversized OTLP payloads.
  • Celery audit task uses ignore_result=True to avoid unnecessary result-backend writes.

Known limitations

  • Django bulk operations bypass per-instance signals (bulk_create, bulk_update, queryset update, queryset delete). If needed, add explicit auditing at service-layer boundaries.
  • Reverse-side M2M modifications (reverse=True) are not audited by default. This can be extended with explicit configuration if your domain needs it.
  • One-to-many collection semantics should be expressed through child create/update/delete formatters (FK changes). There is no dedicated O2M signal registry yet.

Install

python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e .[test]

Makefile workflow

Bootstrap environment:

make bootstrap

Run tests:

make test

Shortcuts:

  • make test-unit
  • make test-integration
  • make docker-build
  • make docker-test

Test commands

Run all tests:

pytest -q

Run focused unit tests:

pytest -q tests/test_middleware.py tests/test_strategy.py tests/test_receiver_unit.py tests/test_tasks.py

Run integration tests:

pytest -q tests/test_receiver_integration.py

Minimum test coverage checklist

Shared library tests cover:

  • autodiscovery imports both audit_formatters.py modules and audit_formatters packages
  • middleware canonical raw_route
  • registry selection (raw_route match -> default -> generic)
  • M2M receiver firing only for allowlisted collections
  • commit safety (rollback prevents enqueue)
  • enqueue failure (log + drop)
  • OTLP task retries are bounded

Microservice-level expectations:

  • formatter unit tests for key routes
  • startup integration test verifies registrations are loaded into registry

Acceptance criteria status

  • No explicit audit calls in business logic: yes (signal + middleware driven).
  • Audit events include raw_route and user metadata when available: yes.
  • Formatter selection is based on HTTP verb + route template: yes (raw_route = METHOD|/template).
  • M2M relations are audited only when allowlisted (@register_audit_collection): yes.
  • OTLP emission happens only after commit: yes (transaction.on_commit).
  • Audit failures never break the request path: yes (exceptions are swallowed and logged).

Notes

  • Tests use minimal Django settings from tests/settings.py.
  • Test app is under tests/test_app.
  • OTLP network emission is mocked in tests (emit_audit_log_task.delay).

Docker

Build image:

docker compose build

Run tests in container:

docker compose run --rm test

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ftn_audit-1.0.0b3.tar.gz (28.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ftn_audit-1.0.0b3-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

Details for the file ftn_audit-1.0.0b3.tar.gz.

File metadata

  • Download URL: ftn_audit-1.0.0b3.tar.gz
  • Upload date:
  • Size: 28.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for ftn_audit-1.0.0b3.tar.gz
Algorithm Hash digest
SHA256 922dc5f4055b491ebe964a02ca0206f1fb59ec6dba931cf2dccab545ace89348
MD5 854d6ff08d7661ababb909bcfaf74987
BLAKE2b-256 339ad2326253cd6f0cbc478e71a2a332614af2e2ed7b439cb12cab260d28f0fa

See more details on using hashes here.

File details

Details for the file ftn_audit-1.0.0b3-py3-none-any.whl.

File metadata

  • Download URL: ftn_audit-1.0.0b3-py3-none-any.whl
  • Upload date:
  • Size: 25.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for ftn_audit-1.0.0b3-py3-none-any.whl
Algorithm Hash digest
SHA256 4090734efcb3542f0940ea8d54f37b2998faa9313bfc2069fe57dcae4e405b81
MD5 fa377845c62a0d17b3202d2ad9647cc7
BLAKE2b-256 46d109d226dd3bbf41b7a7f64cae3bd990a69509c2276354b776d9518225c9a0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page