DRF API Logger for Django REST Framework

A maintainer-led guide to DRF API Logger: safely log DRF requests, mask secrets, profile slow APIs, and tune production storage.

DRF API Logger for Django REST Framework illustration
On this page40 sections

Maintainer-led open-source project

DRF API Logger

Request and response observability for Django REST Framework applications. DRF API Logger is created and maintained by Vishal Anand, the author of the CodersSecret guide. Listed in Django REST Framework's official third-party packages documentation. This listing is not an endorsement.

Stable
v1.4.0
Released
2026-07-08
Verified
2026-08-26
Compatibility
Python 3.10+ · Django 4.2+ · DRF 3.16+
License
Apache-2.0
pip install drf-api-logger

If you run APIs in Django REST Framework, you eventually need answers that normal application logs do not give you quickly: which endpoint failed, what payload arrived, what status code was returned, how long the request took, whether sensitive data was masked, and whether the same endpoint is getting slower over time. DRF API Logger fills that gap. It adds request and response observability without forcing every view to write custom logging code. The OpenTelemetry observability guide shows how these API records complement service-level logs, metrics, and traces.

This guide covers DRF API Logger 1.4.0, released on July 8, 2026. The supported baseline is Python 3.10+, Django 4.2+, and Django REST Framework 3.16+; the package uses the Apache-2.0 license. DRF API Logger is listed in Django REST Framework's official third-party packages documentation. That listing is useful independent evidence of discoverability, but it does not mean the package is endorsed, certified, or maintained by the DRF project.

Maintainer disclosure: I am Vishal Anand, the creator and maintainer of DRF API Logger and the author of this guide. The walkthrough is maintainer-led, while version, compatibility, release, and listing claims link to sources you can verify directly.

DRF API Logger Request Lifecycle
📨ClientCalls DRF endpoint
🔍MiddlewareCaptures and masks
ViewRuns normally
ProfilerMeasures timing
📝QueueBatches database writes
📤ResponseReturned to client

What DRF API Logger Actually Solves

Most Django projects already have server logs, access logs, exception logs, and maybe an APM tool. Those are useful, but they often fail at one very practical workflow: reconstructing a specific API call. DRF API Logger stores the API path, HTTP method, headers, body, response body, status code, execution time, client IP address, timestamp, and optional tracing ID in a structured way.

This makes it useful for four common engineering jobs:

  • Debugging: Reproduce what happened when a client says "the API returned the wrong thing".
  • Operational monitoring: Find slow endpoints, failed status codes, noisy clients, and regression patterns.
  • Operational evidence: Keep structured request records for investigations, while using a separate immutable audit system when one is required.
  • Performance diagnosis: Use profiling fields to split total time into middleware, view/serialization, SQL, and business-logic cost.

Where It Fits in a Django REST Framework App

DRF API Logger is installed as Django middleware. That matters because middleware sees the request before the DRF view executes and sees the response after the view returns. The logger can therefore capture both sides of the call without changing every view, serializer, or viewset.

A simplified request lifecycle looks like this:

  1. The client sends a request to a DRF endpoint.
  2. The logger middleware records request metadata such as path, method, headers, body, and client IP.
  3. The DRF view runs normally. Authentication, permissions, throttling, serializer validation, database work, and response generation continue as usual.
  4. The middleware receives the response and records status code, response body, and execution time.
  5. An eligible log event is sent to the configured destination: database, signal listeners, or both.
  6. Capture, masking, serialization, custom handling, and enqueueing still happen on the request path. The background worker batches database writes so the request thread does not perform one insert per log record.
Two Logging Destinations
💾 Database Logging
📊Django admin dashboard
🔎Search request, response, headers, URL
📅Filter by date, status, method, speed
Slow API detection
📥CSV export for offline analysis
📡 Signal-Based Logging
📨Send logs to external systems
🔔Alert on slow or failing APIs
📁Write custom files or JSONL streams
🔧Build domain-specific handlers

When to Use It

Use DRF API Logger when you need structured visibility into DRF request and response behavior, especially when the API team needs to answer production questions without digging through unstructured logs. It is useful for CRUD APIs, internal admin APIs, B2B APIs, mobile app backends, partner integrations, and services where request payloads and status-code patterns matter.

Do not treat it as an immutable audit log, a compliance guarantee, a WAF, SIEM, IDS, APM, or distributed tracing backend. It complements those systems. Metrics tell you that error rate increased. Tracing tells you which service path was slow. DRF API Logger gives you the concrete DRF request/response record inside your Django app.

Install and Wire It Correctly

Step 1: Install the package:

pip install drf-api-logger

Step 2: Add it to INSTALLED_APPS:

INSTALLED_APPS = [
    # Django apps
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Third-party apps
    'rest_framework',
    'drf_api_logger',
]

Step 3: Add the middleware:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    'drf_api_logger.middleware.api_logger_middleware.APILoggerMiddleware',
]

Middleware order depends on what you want captured. In most projects, putting it after Django's common authentication/session middleware is a sensible default because the logger sees normalized Django requests and can still capture the response after DRF finishes.

Step 4: Enable database logging and migrate:

DRF_API_LOGGER_DATABASE = True
python manage.py migrate

The database table is only useful after migrations are run. If you enable database logging but skip migrations, you should expect missing-table errors or no usable admin records.

MySQL and MariaDB upgrade warning: migration 0003 adds profiling columns. Adding columns to a large existing log table can lock or rebuild it depending on the exact database version, engine, row format, and table definition. Inspect the generated SQL first with python manage.py sqlmigrate drf_api_logger 0003, test the operation against production-like data, and use database-native online DDL or a reviewed online migration process where appropriate. Do not copy a generic ALTER TABLE command without validating it.

Database Logging Deep Dive

Database logging stores API calls in a Django model and exposes them through the Django admin. This is the easiest mode to start with because it gives your team an immediate UI for searching, filtering, and inspecting API traffic.

The built-in admin dashboard gives you charts and high-level API activity:

DRF API Logger admin dashboard with API analytics charts

The log listing view gives you a table of API calls with status codes, methods, timings, and request metadata:

DRF API Logger list view showing API call logs with status codes, methods, and execution times

Clicking into a log entry gives you detailed request and response information, including timing and diagnostics:

DRF API Logger detail view showing slow SQL query detection with execution time breakdown

Sensitive values can be masked before storage, so fields like passwords and tokens do not appear as raw values:

DRF API Logger detail view showing automatic masking of password and token fields

Profiling views make slow endpoints easier to reason about because the problem is split into query count, SQL time, middleware time, and application time:

DRF API Logger detail view showing API timing and diagnostic information

Model Fields You Should Understand

The core log model stores the operational fields you usually need during debugging:

class APILogsModel(models.Model):
    id = models.BigAutoField(primary_key=True)
    api = models.CharField(max_length=1024)
    headers = models.TextField()
    body = models.TextField()
    method = models.CharField(max_length=10, db_index=True)
    client_ip_address = models.CharField(max_length=50)
    response = models.TextField()
    status_code = models.PositiveSmallIntegerField(db_index=True)
    execution_time = models.DecimalField(decimal_places=5, max_digits=8)
    added_on = models.DateTimeField()

    # Present when API profiling is enabled
    profiling_data = models.TextField(null=True)
    sql_query_count = models.PositiveIntegerField(null=True)

The important operational detail is that execution_time is server-side execution time, not the user's complete network round trip. That makes it useful for backend diagnosis because it removes client network conditions from the number.

Signal-Based Logging Deep Dive

Signal-based logging is for teams that do not want eligible API records stored only in the application database. When enabled, DRF API Logger emits a signal for calls that pass its filters and endpoint policy. Your listeners can write JSON lines, ship events to a log pipeline, publish to Kafka, trigger an alert, or attach application-specific context.

DRF_API_LOGGER_SIGNAL = True
from drf_api_logger import API_LOGGER_SIGNAL

def write_jsonl(**kwargs):
    import json
    with open('/var/log/myapp/api-logs.jsonl', 'a') as file_obj:
        file_obj.write(json.dumps(kwargs, default=str) + '\n')

def alert_on_server_errors(**kwargs):
    if kwargs.get('status_code', 200) >= 500:
        notify_ops_team(
            api=kwargs.get('api'),
            method=kwargs.get('method'),
            status=kwargs.get('status_code'),
            took=kwargs.get('execution_time'),
            trace=kwargs.get('tracing_id'),
        )

API_LOGGER_SIGNAL.listen += write_jsonl
API_LOGGER_SIGNAL.listen += alert_on_server_errors

You can also unsubscribe listeners when needed:

API_LOGGER_SIGNAL.listen -= write_jsonl

What the Signal Payload Looks Like

The signal payload contains the same kind of data you need for external observability pipelines:

{
    'api': '/api/users/',
    'method': 'POST',
    'status_code': 201,
    'headers': '{"Content-Type": "application/json"}',
    'body': '{"username": "john", "password": "***FILTERED***"}',
    'response': '{"id": 1, "username": "john"}',
    'client_ip_address': '192.168.1.100',
    'execution_time': 0.142,
    'added_on': datetime.now(),
    'tracing_id': 'uuid4-string'
}

This makes signal mode useful when your main log storage is not Django admin. For example, you can keep a short retention window in the database for support and debugging and send a deliberately minimized event stream to a centralized log system for longer retention. The signal is an integration point, not a SIEM or exporter backend by itself.

Sampled API Profiling in v1.4

The most important modern capability to explain is API profiling. When profiling is enabled, each logged request can include a timing breakdown instead of only a single total duration. That lets you answer better questions:

  • Was the request slow because of SQL?
  • Was it slow because the serializer did too much work?
  • Was middleware adding unexpected overhead?
  • Did the endpoint run many queries and look like an N+1 problem?
  • Was total time high even though SQL time was low, pointing to external calls or business logic?
DRF_API_LOGGER_ENABLE_PROFILING = True
DRF_API_LOGGER_PROFILING_SQL_TRACKING = True
DRF_API_LOGGER_PROFILING_SAMPLE_RATE = 0.10

When enabled, the profiling data can include middleware time, view and serialization time, SQL time, SQL query count, and diagnosis hints. DRF_API_LOGGER_PROFILING_SAMPLE_RATE accepts a fraction from 0.0 to 1.0, so a busy service can profile a sample while still applying its normal logging rules. The package documentation describes patterns such as SQL taking more than 70 percent of total time with high query count as likely N+1 behavior, while low SQL time with high total time suggests business logic or external service latency. Treat diagnosis labels as investigation hints, not proof.

Profiling Diagnosis Map
SQL > 70% + many queriesLikely N+1 query pattern
SQL > 70% + few queriesSlow query or missing index
SQL < 20% + high total timeBusiness logic or external calls
Middleware > 10% of totalMiddleware overhead deserves review

Configuration Reference by Use Case

A large config block is hard to reason about, so treat settings by the problem they solve.

Core Destination Settings

DRF_API_LOGGER_DATABASE = True
DRF_API_LOGGER_SIGNAL = False

Use database mode for admin search and debugging. Use signal mode when your organization already has centralized logging. Use both when you want a short local debugging window plus a minimized external stream governed by its own access and retention controls.

Queue and Background Processing

DRF_LOGGER_QUEUE_MAX_SIZE = 50
DRF_LOGGER_INTERVAL = 10

The queue controls how often logs are flushed. Larger queues reduce write frequency but can increase memory usage and delay visibility. Shorter intervals make logs visible faster but write more frequently. For high-traffic systems, tune both with real production traffic instead of guessing.

Selective Logging

DRF_API_LOGGER_SKIP_NAMESPACE = ['admin', 'internal']
DRF_API_LOGGER_SKIP_URL_NAME = ['health-check', 'metrics']
DRF_API_LOGGER_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
DRF_API_LOGGER_STATUS_CODES = [200, 201, 400, 401, 403, 404, 500]

Selective logging is how you keep the signal-to-noise ratio healthy. Do not store health checks, metrics endpoints, noisy internal probes, or endpoints that generate data you are not allowed to retain.

Sensitive Data and Payload Limits

DRF_API_LOGGER_EXCLUDE_KEYS = [
    'password',
    'token',
    'access',
    'refresh',
    'secret',
    'api_key',
    'authorization',
]

DRF_API_LOGGER_MAX_REQUEST_BODY_SIZE = 32768
DRF_API_LOGGER_MAX_RESPONSE_BODY_SIZE = 65536

Masking protects common secret fields. The default request cap is 32,768 bytes (32 KiB) and the default response cap is 65,536 bytes (64 KiB). Oversized payloads are replaced with a marker rather than stored in full. A value of -1 removes the corresponding limit; that is intentionally unlimited, so use it only after a storage and privacy review.

Supported Content Types

DRF_API_LOGGER_CONTENT_TYPES = [
    'application/json',
    'application/vnd.api+json',
    'application/xml',
    'text/csv',
]

By default, JSON APIs are the primary use case. The package also supports custom content types, including vendor JSON media types such as JSON:API style content types.

Tracing IDs

DRF_API_LOGGER_ENABLE_TRACING = True
DRF_API_LOGGER_TRACING_ID_HEADER_NAME = 'X-Trace-ID'
DRF_API_LOGGER_TRACING_FUNC = 'myapp.tracing.generate_trace_id'

Tracing IDs matter when an API request crosses systems. If your gateway already sends a trace header, configure the header name so DRF API Logger stores the upstream correlation ID instead of inventing an unrelated one. In your views, you can access request.tracing_id when tracing is enabled.

Request Correlation, W3C traceparent, and Logging Context

DRF_API_LOGGER_ENABLE_CORRELATION = True
DRF_API_LOGGER_CORRELATION_REQUEST_ID_HEADERS = [
    'X-Request-ID',
    'X-Correlation-ID',
]
DRF_API_LOGGER_CORRELATION_TRACE_ID_HEADERS = [
    'traceparent',
    'X-Trace-ID',
]
DRF_API_LOGGER_ENABLE_LOGGING_CONTEXT = True

Correlation mode parses inbound request IDs and W3C traceparent values, exposes request-scoped context during the view call, and adds correlation plus low-cardinality route metadata to signal payloads. It intentionally does not add correlation columns or synthetic fields to APILogsModel. Keep trace IDs and request IDs in logs and traces, not as Prometheus labels.

Endpoint Policies and a Custom Handler

DRF_API_LOGGER_POLICY = {
    'rules': [
        {'url_name': 'health_check', 'log': False},
        {
            'route': 'api/payments/',
            'request_body': False,
            'response_body': False,
            'mask_keys': ['card_number', 'payment_token'],
            'signal': False,
        },
    ],
}

DRF_API_LOGGER_CUSTOM_HANDLER = 'myapp.logging.clean_api_log'

Endpoint policies let a sensitive route disable logging, strip request or response bodies, add route-specific mask keys, or prevent signal export. A custom handler can transform a record before it enters the queue, or return None to drop it. Keep handlers fast and deterministic because they run on the request path.

ASGI, Observability Helpers, and First-Party Metrics

The 1.4 middleware supports Django's async middleware chain while remaining compatible with synchronous deployments. Request-scoped context is isolated across concurrent ASGI requests, but the same production rule still applies: benchmark capture, masking, profiling, and custom handlers under your workload.

Safe Prometheus, OpenTelemetry, and Sentry Helpers

from drf_api_logger import API_LOGGER_SIGNAL
from drf_api_logger.observability import (
    annotate_opentelemetry_span,
    configure_sentry_scope,
    record_prometheus_metrics,
)

def export_observability(**event):
    record_prometheus_metrics(event, API_REQUESTS, API_DURATION)
    annotate_opentelemetry_span(current_span, event)
    configure_sentry_scope(sentry_scope, event)

API_LOGGER_SIGNAL.listen += export_observability

These helpers attach safe route and status context without turning DRF API Logger into Prometheus, OpenTelemetry, or Sentry. Your application still owns those dependencies, exporters, sampling, retention, and access controls. Metrics labels are allowlisted and low-cardinality; never use raw URLs, query strings, request IDs, trace IDs, user IDs, IP addresses, tokens, bodies, SQL text, or exception messages as labels.

Logger Health, API Metrics, and Detect-Only Security Signals

pip install "drf-api-logger[prometheus]"

DRF_API_LOGGER_METRICS_ENABLED = True
DRF_API_LOGGER_METRICS_GROUPS = ['logger', 'pipeline']
DRF_API_LOGGER_API_METRICS_ENABLED = True

# Optional and disabled by default
DRF_API_LOGGER_SECURITY_METRICS_ENABLED = True
DRF_API_LOGGER_SECURITY_MODE = 'detect'

First-party metrics can report request-path overhead, queue depth, worker health, flushes, storage failures, API counts, duration, body sizes, slow requests, exceptions, and throttles. API metrics are enabled separately so an application that already instruments requests can avoid duplicates.

Security signals are detect-only and disabled by default. They can flag patterns such as authentication failures, admin probes, route scans, suspicious payloads, enumeration hints, rate-limit pressure, or bulk export behavior. They do not block traffic and they are not a WAF, IDS, or SIEM. Expect false positives, validate alert thresholds, protect any Prometheus endpoint behind an internal authenticated route, and run python manage.py check after enabling metrics.

Path Storage Format

DRF_API_LOGGER_PATH_TYPE = 'ABSOLUTE'
# Other options: FULL_PATH, RAW_URI

ABSOLUTE stores the full absolute URI using Django's normal host validation. FULL_PATH stores only path and query string. RAW_URI can bypass normal host validation behavior, so use it only when you understand the security implications.

Querying Logs with the Django ORM

Once database logging is enabled, API logs become queryable with normal Django ORM patterns.

from datetime import timedelta
from django.db.models import Avg, Count, Max
from django.utils import timezone
from drf_api_logger.models import APILogsModel

since = timezone.now() - timedelta(hours=24)

# Recent failed API calls
errors = APILogsModel.objects.filter(
    added_on__gte=since,
    status_code__gte=400,
).order_by('-added_on')

# Slowest endpoints
slowest = APILogsModel.objects.filter(
    added_on__gte=since,
).order_by('-execution_time')[:20]

# Endpoint error rates
endpoint_summary = (
    APILogsModel.objects
    .filter(added_on__gte=since)
    .values('api', 'method')
    .annotate(
        calls=Count('id'),
        avg_seconds=Avg('execution_time'),
        max_seconds=Max('execution_time'),
    )
    .order_by('-calls')
)

execution_time is stored in seconds, so the aggregate names above deliberately say avg_seconds and max_seconds. Multiply explicitly if your dashboard presents milliseconds; do not label the raw decimal as milliseconds.

Retention and Cleanup

API logs grow until you intentionally delete or archive them. Decide retention before enabling database logging in production. A short local window is often enough for support and debugging; any longer period should be justified by operational and privacy requirements rather than copied from an example.

# Preview rows older than 30 days
python manage.py prune_api_logs --days 30 --dry-run

# Delete in bounded batches
python manage.py prune_api_logs --days 30 --batch-size 1000

Schedule the built-in prune_api_logs command through your normal job runner, monitor its results, and always use --dry-run before the first destructive execution. The command also supports a fixed --before date when policy requires a calendar cutoff.

Production Database Design

For small applications, storing logs in the default database may be acceptable. For high-traffic systems, use a dedicated logging database so API log writes and log searches do not compete with customer-facing transactional data. Apply the same workload-first reasoning from the database indexing guide before adding indexes to the log table.

DRF_API_LOGGER_DEFAULT_DATABASE = 'logs_db'

Then configure a Django database router or run migrations against the chosen database, depending on how your project handles multiple databases.

Add indexes based on your real query patterns. Common examples:

CREATE INDEX idx_api_logs_added_on
ON drf_api_logs(added_on);

CREATE INDEX idx_api_logs_api_method
ON drf_api_logs(api, method);

CREATE INDEX idx_api_logs_status_added_on
ON drf_api_logs(status_code, added_on);

Security and Privacy Checklist

API logging is powerful, but it can become a liability if you log the wrong data. Treat API logs as sensitive production data, and use the API security checklist to review authentication, authorization, validation, rate limits, and audit controls around the endpoints.

  • Mask secrets: Add every credential-like key to DRF_API_LOGGER_EXCLUDE_KEYS.
  • Limit payload size: Use max request and response body settings before enabling production logging.
  • Skip sensitive endpoints: Do not log endpoints that process card data, tokens, secret exports, or regulated data unless you have a clear retention policy.
  • Restrict admin access: Only trusted operators should see request and response logs.
  • Set retention: Delete or archive old rows automatically.
  • Use a separate database: Keep logs away from the primary write path for busy systems.
  • Review compliance requirements: GDPR, HIPAA, PCI, SOC 2, and internal policies may restrict what you can store.

Troubleshooting: No Logs Showing Up

Start with the read-only production diagnostics command:

python manage.py drf_api_logger_doctor

drf_api_logger_doctor checks the active logging mode, database and migration readiness, table availability, queue and worker state, payload limits, masking settings, and profiling risk. CI or deployment automation can also request JSON output or set a failure threshold; see the operations documentation for those options.

If you installed the package but do not see logs, check these in order:

  1. Middleware is missing: Confirm APILoggerMiddleware is in MIDDLEWARE.
  2. Database logging is disabled: Set DRF_API_LOGGER_DATABASE = True.
  3. Migrations were not run: Run python manage.py migrate.
  4. Endpoint is skipped: Review skip namespace, skip URL name, method filters, and status-code filters.
  5. Content type is not logged: Add your API media type to DRF_API_LOGGER_CONTENT_TYPES.
  6. Admin endpoint confusion: Django admin panel requests are excluded from logging.
  7. Wrong database: If using DRF_API_LOGGER_DEFAULT_DATABASE, migrate and query the correct database.

Large log growth usually comes from response bodies, high-volume endpoints, or long retention. Fix the data volume at the source:

  • Set DRF_API_LOGGER_MAX_REQUEST_BODY_SIZE and DRF_API_LOGGER_MAX_RESPONSE_BODY_SIZE.
  • Skip health checks, polling endpoints, metrics endpoints, and noisy internal routes.
  • Use status-code filtering if you only need failures.
  • Archive or delete rows older than your operational retention window.
  • Move long-term logs to cheaper storage through signal listeners.

Troubleshooting: Slow Admin Search

If the admin log table becomes slow, the logger is doing its job but the storage strategy needs tuning. Add indexes, filter by date first, avoid retaining unlimited logs, and consider a separate logging database. Search over giant request and response bodies is inherently expensive, so do not keep unnecessary payloads forever.

DRF API Logger vs Plain Django Logging

Plain Django logging is still useful for application events, exceptions, and custom log statements. DRF API Logger is different because it captures structured API request/response records automatically. The difference is not "which one is better"; the difference is what question you are answering.

  • Use Django logging for application events, error traces, startup issues, and custom domain events.
  • Use DRF API Logger for API-level request/response records, status-code analysis, slow endpoint diagnosis, and support debugging.
  • Use APM/tracing for cross-service timing and distributed request paths.

Practical Production Setup

For a serious production API, start with a conservative configuration:

DRF_API_LOGGER_DATABASE = True
DRF_API_LOGGER_SIGNAL = True

DRF_LOGGER_QUEUE_MAX_SIZE = 100
DRF_LOGGER_INTERVAL = 5

DRF_API_LOGGER_SKIP_URL_NAME = ['health-check', 'metrics']
DRF_API_LOGGER_STATUS_CODES = [400, 401, 403, 404, 409, 422, 429, 500, 502, 503]

DRF_API_LOGGER_EXCLUDE_KEYS = [
    'password',
    'token',
    'access',
    'refresh',
    'secret',
    'api_key',
    'authorization',
]

DRF_API_LOGGER_MAX_REQUEST_BODY_SIZE = 32768
DRF_API_LOGGER_MAX_RESPONSE_BODY_SIZE = 65536

DRF_API_LOGGER_SLOW_API_ABOVE = 200
DRF_API_LOGGER_ENABLE_CORRELATION = True
DRF_API_LOGGER_CORRELATION_REQUEST_ID_HEADERS = ['X-Request-ID']
DRF_API_LOGGER_CORRELATION_TRACE_ID_HEADERS = ['traceparent']
DRF_API_LOGGER_ENABLE_LOGGING_CONTEXT = True

# Validate profiling in staging, then sample it in production.
DRF_API_LOGGER_ENABLE_PROFILING = True
DRF_API_LOGGER_PROFILING_SQL_TRACKING = True
DRF_API_LOGGER_PROFILING_SAMPLE_RATE = 0.10

This example records selected failures, masks sensitive fields, keeps the documented default body caps, correlates with upstream request and W3C trace context, and profiles a sample. Review each status filter, payload cap, and retention period against your actual debugging and privacy requirements; this is a starting point, not a compliance preset.

What to Monitor After Enabling It

  • Log table growth: Rows per day, storage size, and index size.
  • Queue behavior: Whether logs flush regularly under normal and peak traffic.
  • Slow endpoint count: Endpoints crossing your configured threshold.
  • Error bursts: Sudden increases in 4xx or 5xx responses.
  • Payload size: Whether large request or response bodies are being stored.
  • Admin query speed: Whether support engineers can search logs quickly.
  • Logger health: Queue depth, worker state, request-path overhead, flush duration, dropped records, and storage failures when first-party metrics are enabled.

FAQ

Does DRF API Logger affect API response time?

It is designed for low request-path overhead, not zero overhead. Capture, masking, serialization, optional profiling or custom handling, and enqueueing remain on the request path. Batched database writes happen in the background. Benchmark representative payloads and monitor queue health, memory, and logger overhead under real traffic.

Can I use database logging and signal logging together?

Yes. Database logging gives you a convenient admin interface, while signal logging lets an application-owned listener process the same eligible record. Minimize and secure any external destination separately.

Should I log every endpoint?

Not always. Skip health checks, metrics endpoints, high-frequency polling routes, and endpoints that carry data you should not retain.

Is profiling safe in production?

Profiling is useful, but treat it as an operational feature to validate under your workload. SQL tracking can add overhead in some environments, so enable it deliberately and monitor impact.

No. It solves a different layer of the observability problem. Use it for structured DRF API records and optional detect-only signals. Use dedicated systems for enforcement, immutable auditing, distributed traces, metrics storage, alert investigation, and error tracking.

Reference Links

Final Recommendation

DRF API Logger 1.4 is a practical way to add API-level evidence and performance diagnostics to a supported Django REST Framework service without rewriting views. Start in staging, run drf_api_logger_doctor, confirm masking and body policy, inspect migrations, validate ASGI or sync behavior, and measure request-path overhead. Then enable only the destinations, endpoint policies, profiling sample, metrics, and retention schedule your production system needs.

Share this article

Stuck on implementation?

Get private, 1-on-1 help with system design, performance, scaling, or any technical challenge.

Book a Session

Related Production Resources

Course

Free learning tracks

Turn this guide into a structured production engineering path.

Lab

Interactive engineering labs

Practice the same ideas through scenario-based simulators.

Reference

Production cheatsheets

Keep the operational commands and checks nearby.

Glossary

Key terms

Review the vocabulary behind the architecture.

Discussion

Questions, corrections, or production notes? Add them here so other learners can benefit.

Comments load on demand

To keep this article fast and private by default, the GitHub-powered discussion loads only when you reach this section.

Prefer GitHub? Open the project discussions directly .

Continue Reading

Related practical guides from the same production engineering path.

Open Source 12 min read

How to Build a Python CLI Tool That People Actually Use

Build a production-quality Python CLI with Typer, publish it to PyPI, add shell completions, colored output, progress bars, and CI/CD - everything between "it works on my machine" and "10,000 installs."

Python CLI
Backend 12 min read

Celery Task Queues: From Simple Tasks to Complex Workflows

Django + Celery is the most popular async task processing stack in Python. Learn task retries, chains, chords, rate limiting, monitoring with Flower, and the production patterns that keep your workers healthy.

Celery Django
Backend 11 min read

M2M Authentication: Securing Service-to-Service Communication

A comprehensive guide to Machine-to-Machine authentication - from OAuth 2.0 Client Credentials to mTLS, JWTs, and API keys. Learn how to secure your microservices.

Authentication Security
Backend 18 min read

Improving Python Code Performance: Practical Tips That Actually Work

From profiling bottlenecks to leveraging built-in optimizations, learn proven techniques to make your Python code run significantly faster.

Python Performance