Skip to main content

FastAPI Logging Kit

Structured, extensible logging for FastAPI and ASGI applications.

PyPI - Version PyPI - Python Version PyPI - Downloads

License Documentation CI Workflow pre-commit Last Commit Languages Open Issues codecov

fastapi-logging-kit integrates with Python's standard logging package and FastAPI. A single setup_logging(app) call enables safe request-completion logging and a console logger without altering existing root handlers. Applications can supply an explicit FASTAPI_LOGGING mapping to configure standard dictConfig components, ASGI request logging, and extensible handlers, filters, and formatters. No Django or settings-package dependency is required.

The JSON, XML, and FLAT structured formatters preserve original messages, redact named sensitive fields, and impose limits on serialization depth, items, output bytes, string lengths, and exception traces.

For migration from django_logging, see Migrating from django_logging.

Project Detail

  • Language: Python >= 3.11 (supported: 3.11–3.15)
  • Framework: FastAPI >= 0.100

Documentation

The documentation is organized into the following sections:

Quick Start

Getting started with fastapi_logging_kit is simple. Follow these steps to get up and running quickly:

  1. Install the Package

first, Install fastapi_logging_kit via pip:

$ pip install fastapi-logging-kit
  1. Call setup_logging

FastAPI has no application registry, so there is no equivalent of Django's INSTALLED_APPS. Instead, call setup_logging once, passing your application:

from fastapi import FastAPI

from fastapi_logging_kit import setup_logging

app = FastAPI()
setup_logging(app)

That single call configures the logging, installs the request logging middleware and — if you enable it — mounts the LogiBoard router.

  1. Run Your Server

Start your server to verify the installation:

uvicorn main:app --reload

The default structured integration preserves the host application's existing root handlers and installs request logging. It does not automatically create per-level log files. Configure file handlers explicitly through LOGGING or COMPONENTS if you need them.

Structured JSON logging

To emit JSON logs using standard Python logging configuration:

from fastapi import FastAPI
from fastapi_logging_kit import setup_logging

app = FastAPI()
setup_logging(app, config={
    "LOGGING": {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "json": {
                "()": "fastapi_logging_kit.formatters.JSONFormatter",
                "fmt": "%(levelname)s %(message)s %(context)s",
                "structured_logging": {
                    "INCLUDE_EXTRA": True,
                    "REDACT_FIELDS": ["customer_reference"],
                    "MAX_EVENT_BYTES": 65536,
                    "EXCEPTION_MODE": "type",
                },
            },
        },
        "handlers": {
            "stdout": {
                "class": "logging.StreamHandler",
                "formatter": "json",
            },
        },
        "root": {"level": "INFO", "handlers": ["stdout"]},
    },
    "REQUEST_LOGGING": {
        "QUERY_PARAMS_ENABLED": False,
        "REQUEST_BODY_ENABLED": False,
        "ERROR_RESPONSE_BODY_ENABLED": False,
        "LOG_STREAMING_EVENTS": False,
        "LOG_SQL_QUERIES": False,
        "MAX_SQL_BYTES": 4096,
        "MAX_SQL_QUERIES": 100,
        "MAX_REQUEST_ID_LENGTH": 80,
    },
})

By supplying LOGGING, you explicitly select Python's process-wide dictConfig replacement semantics. This is different from the no-config additive setup. To preserve existing handlers, leave LOGGING empty and use COMPONENTS for additive extensions.

Structured formatters never parse free-form key=value strings into fields. Pass structured values through extra={...} or the request-context filter instead. Redaction applies to named structured fields, not arbitrary secrets embedded in messages or exception text. The exception policy can be set to "omit", "type", or "traceback".

Usage

Once fastapi_logging_kit is installed and setup_logging has been called, you can start using it right away. The package provides several features to customize and enhance logging in your FastAPI project. Below is a guide on how to use the various features provided by fastapi_logging_kit.

Basic Logging Usage:

At its core, fastapi_logging_kit is built on top of Python's built-in logging module. This means you can use the standard logging module to log messages across your project. Here's a basic example of logging usage:

import logging

logger = logging.getLogger(__name__)

logger.debug("This is a debug message")
logger.info("This is an info message")
logger.warning("This is a warning message")
logger.error("This is an error message")
logger.critical("This is a critical message")

These logs will be handled according to the configurations set up by fastapi_logging_kit, using either the default settings or any custom settings you've provided.

Legacy configuration

Existing flat-key configuration remains supported for migration. New applications should use the structured FASTAPI_LOGGING contract above.

setup_logging accepts the legacy configuration as its second argument:

from fastapi import FastAPI

from fastapi_logging_kit import setup_logging

app = FastAPI()

setup_logging(
    app,
    {
        "LOG_DIR": "logs",
        "LOG_FILE_LEVELS": ["INFO", "ERROR", "CRITICAL"],
        "LOG_FILE_FORMAT_TYPES": {"ERROR": "JSON"},
    },
)

Legacy flat-key options can also be supplied through the environment, using the FASTAPI_LOGGING_ prefix. Pass structured LOGGING, COMPONENTS, and REQUEST_LOGGING settings explicitly. Values are parsed as JSON, falling back to a plain string:

export FASTAPI_LOGGING_LOG_DIR=/var/log/myapp
export FASTAPI_LOGGING_LOG_FILE_LEVELS='["INFO", "ERROR"]'
export FASTAPI_LOGGING_LOG_CONSOLE_COLORIZE=false

An explicit mapping passed to setup_logging takes priority over the environment, which in turn takes priority over the packaged defaults. This means the CLI commands pick up the same FASTAPI_LOGGING_LOG_DIR your application uses, with no extra wiring.

setup_logging can also be called without an application when you only want the logging configured — for example in a worker process or a maintenance script:

from fastapi_logging_kit import setup_logging

setup_logging(config={"LOG_DIR": "logs"})

Context Manager:

You can use the config_setup context manager to temporarily apply fastapi_logging_kit configurations within a specific block of code. Example usage:

import logging

from fastapi_logging_kit.utils.context_manager import config_setup

logger = logging.getLogger(__name__)


def foo():
    logger.info("This log will use the configuration set in the context manager!")


with config_setup():
    """Your logging configuration changes here"""
    foo()

# the logging configuration will restore to what it was before, in here outside of with block
  • Note: AUTO_INITIALIZATION_ENABLE must be set to False in the configuration to use the context manager. If it is True, attempting to use the context manager will raise a ValueError.

Log and Notify Utility:

To send specific logs as email, use the log_and_notify_admin function. Ensure that the ENABLE option in LOG_EMAIL_NOTIFIER is set to True in your configuration:

import logging

from fastapi_logging_kit.utils.log_email_notifier.log_and_notify import log_and_notify_admin

logger = logging.getLogger(__name__)

log_and_notify_admin(logger, logging.INFO, "This is a log message")

You can also include request details in the email by passing the request through extra:

log_and_notify_admin(
    logger,
    logging.INFO,
    "This is a log message",
    extra={"request": request},
)

Execution Tracker Decorator:

The execution_tracker decorator logs the execution time and, optionally, the number of database queries for a function:

import logging

from fastapi_logging_kit.decorators import execution_tracker

logger = logging.getLogger(__name__)


@execution_tracker(
    logging_level=logging.INFO,
    log_queries=True,
    query_threshold=10,
    query_exceed_warning=True,
)
def some_function():
    # function code
    pass

Arguments:

  • logging_level (int): the level at which the metrics are logged. Defaults to logging.INFO.
  • log_queries (bool): whether to include the number of database queries. Requires DEBUG to be True in your configuration. Defaults to False.
  • query_threshold (int | None): logs a warning when the query count exceeds this number. Defaults to None.
  • query_exceed_warning (bool): whether to emit that warning. Defaults to False.

Tracking queries

Django counted queries automatically through connection.queries. FastAPI ships no ORM, so fastapi_logging_kit keeps a bounded, context-local query log. SQLAlchemy support is optional; install it with:

pip install "fastapi-logging-kit[sqlalchemy]"

Then instrument your engine once at startup:

from sqlalchemy import create_engine

from fastapi_logging_kit import instrument_sqlalchemy

engine = create_engine("postgresql://...")
instrument_sqlalchemy(engine)

Enable request-level SQL diagnostics explicitly in the structured configuration:

FASTAPI_LOGGING = {
    "REQUEST_LOGGING": {
        "LOG_SQL_QUERIES": True,
        "MAX_SQL_BYTES": 4096,
        "MAX_SQL_QUERIES": 100,
    },
}

MAX_SQL_BYTES bounds the retained SQL text and final diagnostic message. MAX_SQL_QUERIES caps the number of statements captured per request. The public record_query() API also applies a bounded default history when it is used outside a request scope. query_capture() provides an explicit isolated scope for custom instrumentation. Captured SQL is not automatically redacted: parameterized statements are strongly preferred, and enabling SQL diagnostics should be treated as a deliberate data-exposure decision.

Using a different database library? Report queries yourself from your own instrumentation:

from fastapi_logging_kit import record_query

record_query("SELECT * FROM users", duration=0.014)

Request Logging Middleware:

RequestLogMiddleware is installed for you by setup_logging. To install it yourself — for example to control the middleware ordering — add it directly:

from fastapi import FastAPI

from fastapi_logging_kit import RequestLogMiddleware, setup_logging

app = FastAPI()
setup_logging(app, add_middleware=False)
app.add_middleware(RequestLogMiddleware, config={})

Key Features

  • Request/response logging: structured setup logs completion by default. Enable REQUEST_LOGGING.LOG_REQUEST_STARTED for starting events; completion includes user, status code, content type and elapsed time.
  • Request IDs: accepts a single valid, bounded X-Request-ID value or generates a UUID, and returns it in the response header.
  • Context propagation: binds request_id, ip_address and optional user_agent. Add ContextVarFilter to an output handler and %(context)s to its formatter to render them.
  • Streaming support: tracks streaming lifecycle and emits Streaming started and Streaming finished records only when REQUEST_LOGGING.LOG_STREAMING_EVENTS is enabled.
  • Cancellation handling: logs a warning and releases the bound context when a client disconnects mid-request.
  • SQL query logging: includes queries recorded during the request when REQUEST_LOGGING.LOG_SQL_QUERIES is enabled. SQL diagnostics are disabled by default because SQL statements may contain sensitive literal values.

The middleware is pure ASGI, so it forwards websocket and lifespan traffic untouched. Query parameters, request bodies, error-response bodies, SQL diagnostics and additional streaming lifecycle events are independently opt-in.

Example output with starting events and context rendering enabled:

INFO | 2026-01-05 12:00:00 | request_middleware | REQUEST STARTED: method=GET path=/api/items request_id=a3f1...
 | {'request_id': 'a3f1...', 'ip_address': '10.0.0.4', 'user_agent': 'curl/8.4.0'}

INFO | 2026-01-05 12:00:00 | request_middleware | REQUEST FINISHED:
	user=Anonymous
	status_code=200
	content_type=[application/json]
	response_time=[0.02 second(s)]
 | {'request_id': 'a3f1...', 'ip_address': '10.0.0.4', 'user_agent': 'curl/8.4.0'}

Identifying the user

FastAPI has no built-in authentication, so the middleware reads the user from scope["user"] — the convention used by Starlette's AuthenticationMiddleware and most FastAPI auth extensions. When no user is present, requests are logged as Anonymous.

Context Variables Usage

Your log calls can render request context when their output handler has ContextVarFilter; default setup does not inject it into arbitrary host handlers:

import logging

logger = logging.getLogger(__name__)


@app.get("/items")
async def list_items():
    logger.info("Listing items")  # A handler with ContextVarFilter can render request context.
    return []

MonitorLogSizeMiddleware

MonitorLogSizeMiddleware runs the log size audit at most once a week, warning the admin by email when the log directory exceeds LOG_DIR_SIZE_LIMIT. It is installed by setup_logging when you use the legacy flat-key configuration path. The structured FASTAPI_LOGGING contract installs RequestLogMiddleware only; it does not enable the legacy file-size audit.

The "last run" timestamp is kept in a small in-process cache. If you run several workers and want them to share it, install your own backend:

from fastapi_logging_kit import set_cache

set_cache(my_redis_backed_cache)  # any object with .get(key, default) and .set(key, value, timeout)

Context Variable Management

fastapi_logging_kit exposes the context manager used internally, so you can attach your own fields to every log record in a block of code.

Binding and Unbinding Context Variables

import logging

from fastapi_logging_kit import manager

logger = logging.getLogger(__name__)

# Binding context variables
manager.bind(user_id=42, tenant="acme")
logger.info("Processing")  # context: {'user_id': 42, 'tenant': 'acme'}

# Unbinding a single variable
manager.unbind("tenant")
logger.info("Still processing")  # context: {'user_id': 42}

# Clearing everything
manager.clear()

Batch Binding and Resetting Context Variables

batch_bind returns tokens you can use to restore the previous values:

from fastapi_logging_kit import manager

tokens = manager.batch_bind(request_id="abc", stage="validate")
try:
    ...
finally:
    manager.reset(tokens)

Retrieving and Merging Context Variables

from fastapi_logging_kit import manager

manager.get_contextvars()  # {'request_id': 'abc'}
manager.get_merged_context({"extra": "value"})  # bound logger context wins over ambient

Scoped Context Management

The cleanest option is scoped_context, which binds for the duration of a block and restores afterwards — even if the block raises:

from fastapi_logging_kit import manager

with manager.scoped_context(job_id="import-42"):
    run_import()  # every log record inside carries job_id

LogiBoard Integration

LogiBoard lets you upload and browse log files in the browser.

Setup Instructions

  1. Enable it in your configuration:
setup_logging(app, {"INCLUDE_LOG_iBOARD": True})

That registers the page at /log-iboard/ and mounts its assets at /fastapi-logging-kit/static.

  1. Restrict access.

FastAPI has no built-in permission framework. The default predicate reads is_superuser from scope["user"] and denies anonymous requests. Install authentication middleware that populates scope["user"] before relying on the default policy.

Prefer an application-scoped predicate so that separate FastAPI applications in the same process cannot affect one another:

from fastapi import FastAPI
from fastapi_logging_kit.routers import set_permission_check

app = FastAPI()


def only_admins(request) -> bool:
    user = request.scope.get("user")
    return bool(user and user.role == "admin")


set_permission_check(only_admins, app=app)

Calling set_permission_check(check) without app remains available as a process-wide default for backward compatibility. Permission callbacks must be synchronous and return a real bool; asynchronous callbacks and non-boolean results fail closed. Users failing the check are shown an "Access Denied" page with a 403 status.

Using LogiBoard

Visit /log-iboard/ and upload a .zip of your logs. LogiBoard renders the directory tree and previews JSON, XML and txt files in the browser.

Settings

For new applications, setup_logging(app) uses the structured defaults described in Quick Start. The flat-key settings below are retained for migration and are used only when you select the legacy configuration path by passing legacy keys or loading legacy settings. Those legacy values can also be supplied through FASTAPI_LOGGING_-prefixed environment variables.

Legacy default configuration:

{
    "AUTO_INITIALIZATION_ENABLE": True,
    "INITIALIZATION_MESSAGE_ENABLE": True,
    "LOG_SQL_QUERIES_ENABLE": False,
    "LOG_FILE_LEVELS": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
    "LOG_DIR": "logs",
    "LOG_DIR_SIZE_LIMIT": 1024,  # MB
    "LOG_FILE_FORMATS": {
        "DEBUG": 1,
        "INFO": 1,
        "WARNING": 1,
        "ERROR": 1,
        "CRITICAL": 1,
    },
    "LOG_FILE_FORMAT_TYPES": {
        "DEBUG": "normal",
        "INFO": "normal",
        "WARNING": "normal",
        "ERROR": "normal",
        "CRITICAL": "normal",
    },
    "EXTRA_LOG_FILES": {
        "DEBUG": False,
        "INFO": False,
        "WARNING": False,
        "ERROR": False,
        "CRITICAL": False,
    },
    "LOG_CONSOLE_LEVEL": "DEBUG",
    "LOG_CONSOLE_FORMAT": 1,
    "LOG_CONSOLE_COLORIZE": True,
    "LOG_DATE_FORMAT": "%Y-%m-%d %H:%M:%S",
    "LOG_EMAIL_NOTIFIER": {
        "ENABLE": False,
        "NOTIFY_ERROR": False,
        "NOTIFY_CRITICAL": False,
        "LOG_FORMAT": 1,
        "USE_TEMPLATE": True,
    },
    "INCLUDE_LOG_iBOARD": False,
    "DEBUG": False,
    "EMAIL": {},
    # Rotation (all optional — defaults to no rotation)
    "LOG_ROTATION": {
        "TYPE": "none",
        "MAX_BYTES": 10485760,  # 10 MB
        "BACKUP_COUNT": 5,
        "WHEN": "midnight",
        "INTERVAL": 1,
        "COMPRESS": False,
    },
    "LOG_ROTATION_OVERRIDES": {},
}

Configuration Options:

Here's a breakdown of the available configuration options:

AUTO_INITIALIZATION_ENABLE

  • Type: bool
  • Description: Enables automatic initialization of logging configurations.
  • Default: True

INITIALIZATION_MESSAGE_ENABLE

  • Type: bool
  • Description: Enables logging of the initialization message when logging starts.
  • Default: True

INCLUDE_LOG_iBOARD

  • Type: bool
  • Description: Registers the LogiBoard route and static files on your application. For setting up LogiBoard, please refer to LogiBoard Integration.
  • Default: False

LOG_SQL_QUERIES_ENABLE

  • Type: bool
  • Description: Enables logging of SQL queries within RequestLogMiddleware logs. When enabled, queries recorded during each request will be included in the log output. See Tracking queries for how queries are collected.
  • Default: False

DEBUG

  • Type: bool
  • Description: Replaces Django's settings.DEBUG. Gates query counting in the execution_tracker decorator.
  • Default: False

LOG_FILE_LEVELS

  • Type: list[str]
  • Description: Specifies which log levels should be captured in log files.
  • Default: ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]

LOG_DIR

  • Type: str
  • Description: Specifies the directory where log files will be stored.
  • Default: "logs"

LOG_DIR_SIZE_LIMIT

  • Type: int
  • Description: Specifies the maximum allowed size of the log directory in megabytes (MB). If the directory exceeds this limit and MonitorLogSizeMiddleware is enabled, a warning email will be sent to the admin weekly.
  • Default: 1024 MB (1 GB)

LOG_FILE_FORMATS

  • Type: dict[str, int | str]
  • Description: Maps each log level to its corresponding log format. The format can be an int referencing a predefined format or a custom str format.
  • Default: Format 1 for all levels.
  • Note: See the Available Format Options below for available formats.

LOG_FILE_FORMAT_TYPES

  • Type: dict[str, str]

  • Description: Defines the format type (e.g., normal, JSON, XML, FLAT) for each log level. The keys are log levels, and the values are the format types.

    • Format Types:

      • normal: Standard text log.
      • JSON: Structured logs in JSON format.
      • XML: Structured logs in XML format.
      • FLAT: logs with Flat format.
  • Default: Type normal for all levels.

EXTRA_LOG_FILES

  • Type: dict[str, bool]
  • Description: Determines whether separate log files for JSON or XML formats should be created for each log level. When set to True for a specific level, a dedicated directory (e.g., logs/json or logs/xml) will be created with files like info.json or info.xml. If False, json and xml logs will be written to .log files.
  • Default: False for all levels.

LOG_CONSOLE_LEVEL

  • Type: str
  • Description: Specifies the log level for console output.
  • Default: "DEBUG"

LOG_CONSOLE_FORMAT

  • Type: int | str
  • Description: Specifies the format for console logs, similar to LOG_FILE_FORMATS.
  • Default: format option 1

LOG_CONSOLE_COLORIZE

  • Type: bool
  • Description: Determines whether console output should be colorized.
  • Default: True

LOG_DATE_FORMAT

  • Type: str
  • Description: Specifies the date format for log messages.
  • Default: "%Y-%m-%d %H:%M:%S"

LOG_EMAIL_NOTIFIER

  • Type: dict

  • Description: Configures the email notifier for sending log-related alerts.

    • ENABLE:

      • Type: bool
      • Description: Enables or disables the email notifier.
      • Default: False
    • NOTIFY_ERROR:

      • Type: bool
      • Description: Sends an email when an ERROR record is logged.
      • Default: False
    • NOTIFY_CRITICAL:

      • Type: bool
      • Description: Sends an email when a CRITICAL record is logged.
      • Default: False
    • LOG_FORMAT:

      • Type: int | str
      • Description: The format used for the log message in the email.
      • Default: 1
    • USE_TEMPLATE:

      • Type: bool
      • Description: Whether the email body is rendered with the packaged HTML template.
      • Default: True
    • MAX_CONCURRENT:

      • Type: int (1–64)
      • Description: Maximum number of simultaneous background email deliveries per worker process. Excess notifications are dropped rather than queued.
      • Default: 4
    • SMTP_TIMEOUT:

      • Type: int (1–120 seconds)
      • Description: Network timeout for SMTP operations.
      • Default: 10

EMAIL

  • Type: dict
  • Description: The SMTP settings used to deliver notifications, grouped under the EMAIL configuration key. See Required Email Settings.
  • Default: {}

Log Rotation

Under the legacy flat-key configuration, file logging may be enabled; rotation is opt-in through LOG_ROTATION and can be overridden per level with LOG_ROTATION_OVERRIDES. The standard rotating handlers are not multi-process safe: for Gunicorn/Uvicorn workers, prefer stdout aggregation or an external rotation mechanism.

LOG_ROTATION

  • Type: dict

    • TYPE:

      • Type: str
      • Description: One of "none" (a plain FileHandler), "size" (a RotatingFileHandler) or "time" (a TimedRotatingFileHandler).
      • Default: "none"
    • MAX_BYTES:

      • Type: int
      • Description: The size at which a file is rotated. Used when TYPE is "size".
      • Default: 10485760 (10 MB)
    • BACKUP_COUNT:

      • Type: int
      • Description: How many rotated files to keep. 0 keeps all of them.
      • Default: 5
    • WHEN:

      • Type: str
      • Description: The rotation interval unit. Used when TYPE is "time". One of s, m, h, d, midnight, or w0–w6.
      • Default: "midnight"
    • INTERVAL:

      • Type: int
      • Description: How many WHEN units between rotations.
      • Default: 1
    • COMPRESS:

      • Type: bool
      • Description: Whether rotated files are gzipped.
      • Default: False

LOG_ROTATION_OVERRIDES

  • Type: dict[str, dict]
  • Description: Per-level rotation settings, shallow-merged over LOG_ROTATION, so you only specify the keys that differ.
  • Default: {}

Example — rotate everything nightly, but rotate the noisy debug log by size and compress it:

setup_logging(
    app,
    {
        "LOG_ROTATION": {
            "TYPE": "time",
            "WHEN": "midnight",
            "BACKUP_COUNT": 14,
        },
        "LOG_ROTATION_OVERRIDES": {
            "DEBUG": {
                "TYPE": "size",
                "MAX_BYTES": 5242880,  # 5 MB
                "BACKUP_COUNT": 3,
                "COMPRESS": True,
            },
        },
    },
)

CLI Commands

FastAPI projects have no manage.py, so the commands ship as a fastapi-logging-kit console script. Every command reads the same configuration your application does, so FASTAPI_LOGGING_LOG_DIR applies here too:

$ fastapi-logging-kit --help

send-logs

Zips the log directory and emails it to the given address.

$ fastapi-logging-kit send-logs ops@example.com

Key Features:

  • Compresses the entire log directory into a single zip archive.

  • Attaches the archive to an email and delivers it over SMTP.

  • Cleans up the temporary archive afterwards, whether or not the send succeeded.

  • Note: requires the EMAIL settings. see Required Email Settings.

logs-size-audit

Reports the size of the log directory, broken down by category, and emails the admin when it exceeds LOG_DIR_SIZE_LIMIT.

$ fastapi-logging-kit logs-size-audit

Example:

Log directory size breakdown:
  active            5 file(s)      12.40 MB
  rotated          14 file(s)     201.88 MB
  archived          3 file(s)      44.10 MB
  compressed        7 file(s)      18.02 MB
  TOTAL                           276.40 MB

Log directory size is under the limit: 276.4 MB

rotate-logs

Immediately rotates every active rotating handler. Useful in a deploy script, so a new process starts on fresh files.

$ fastapi-logging-kit rotate-logs

Plain FileHandler instances cannot be rotated programmatically; they are reported as skipped rather than failing.

archive-logs

Moves rotated (non-active) log files into a timestamped archive/ subdirectory, optionally compressing them.

# Basic — move rotated files into archive/
$ fastapi-logging-kit archive-logs

# Gzip each file before moving
$ fastapi-logging-kit archive-logs --compress

# Bundle the archive directory into a tar.gz and remove it
$ fastapi-logging-kit archive-logs --bundle tar.gz

# Bundle into a zip file
$ fastapi-logging-kit archive-logs --bundle zip

# Compress individual files and then bundle into tar.gz
$ fastapi-logging-kit archive-logs --compress --bundle tar.gz

# Preview everything without touching any files
$ fastapi-logging-kit archive-logs --dry-run

Arguments:

  • --compress: gzip each uncompressed rotated file before archiving.
  • --bundle FORMAT: bundle the archive directory into a single tar.gz or zip and remove the directory.
  • --dry-run: print what would happen without touching any files.

Active <level>.log files are never touched.

generate-pretty-json

Finds the .json files in logs/json/ and rewrites them as valid, pretty-printed JSON arrays under logs/json/pretty/.

$ fastapi-logging-kit generate-pretty-json

generate-pretty-xml

Finds the .xml files in logs/xml/ and wraps their contents in a single <logs> element under logs/xml/pretty/.

$ fastapi-logging-kit generate-pretty-xml

Available Format Options

The fastapi_logging_kit package provides predefined log format options that you can use in configuration. You can reference these formats by their corresponding integer keys.

1.  "%(levelname)s | %(asctime)s | %(module)s | %(message)s | %(context)s"
2.  "%(levelname)s | %(asctime)s | %(context)s | %(message)s | %(exc_text)s"
3.  "%(levelname)s | %(context)s | %(message)s | %(stack_info)s"
4.  "%(context)s | %(asctime)s - %(name)s - %(levelname)s - %(message)s"
5.  "%(levelname)s | %(message)s | %(context)s | [in %(pathname)s:%(lineno)d]"
6.  "%(asctime)s | %(context)s | %(levelname)s | %(message)s | %(exc_info)s"
7.  "%(levelname)s | %(asctime)s | %(context)s | in %(module)s: %(message)s"
8.  "%(levelname)s | %(context)s | %(message)s | [%(filename)s:%(lineno)d]"
9.  "[%(asctime)s] | %(levelname)s | %(context)s | in %(module)s: %(message)s"
10. "%(asctime)s | %(processName)s | %(context)s | %(name)s | %(levelname)s | %(message)s"
11. "%(asctime)s | %(context)s | %(threadName)s | %(name)s | %(levelname)s | %(message)s"
12. "%(levelname)s | [%(asctime)s] | %(context)s | (%(filename)s:%(lineno)d) | %(message)s"
13. "%(levelname)s | [%(asctime)s] | %(context)s | {%(name)s} | (%(filename)s:%(lineno)d): %(message)s"
14. "[%(asctime)s] | %(levelname)s | %(context)s | %(name)s | %(module)s | %(message)s"
15. "%(levelname)s | %(context)s | %(asctime)s | %(filename)s:%(lineno)d | %(message)s"
16. "%(levelname)s | %(context)s | %(message)s | [%(asctime)s] | %(module)s"
17. "%(levelname)s | %(context)s | [%(asctime)s] | %(process)d | %(message)s"
18. "%(levelname)s | %(context)s | %(asctime)s | %(name)s | %(message)s"
19. "%(levelname)s | %(asctime)s | %(context)s | %(module)s:%(lineno)d | %(message)s"
20. "[%(asctime)s] | %(levelname)s | %(context)s | %(thread)d | %(message)s"

You can also pass a custom format string instead of an integer.

Required Email Settings

To use the email notifier, the following settings must be configured under the EMAIL key:

setup_logging(
    app,
    {
        "LOG_EMAIL_NOTIFIER": {"ENABLE": True, "NOTIFY_ERROR": True},
        "EMAIL": {
            "EMAIL_HOST": "smtp.example.com",
            "EMAIL_PORT": 587,
            "EMAIL_HOST_USER": "your-email@example.com",
            "EMAIL_HOST_PASSWORD": "your-email-password",
            "EMAIL_USE_TLS": True,
            "DEFAULT_FROM_EMAIL": "your-email@example.com",
            "ADMIN_EMAIL": "admin@example.com",
        },
    },
)

These settings ensure that the email notifier is correctly configured to send log notifications to the specified ADMIN_EMAIL address.

Keep credentials out of your source tree by supplying them through the environment instead:

export FASTAPI_LOGGING_EMAIL='{"EMAIL_HOST":"smtp.example.com","EMAIL_PORT":587,"ADMIN_EMAIL":"admin@example.com"}'

Migrating from django_logging

fastapi_logging_kit retains the core logging features and legacy keys, with deliberate ASGI, serialization, and default-setup differences:

django_logging fastapi_logging_kit
Add "django_logging" to INSTALLED_APPS Call setup_logging(app)
DJANGO_LOGGING = {...} in settings A mapping passed to setup_logging, or FASTAPI_LOGGING_* env vars
Top-level EMAIL_HOST, ADMIN_EMAIL, … settings The EMAIL configuration key
settings.DEBUG The DEBUG configuration key
MIDDLEWARE list entries Installed by setup_logging, or app.add_middleware(...)
python manage.py send_logs fastapi-logging-kit send-logs
Django system checks abort startup Legacy checks warn; structured validation raises before installation
connection.queries instrument_sqlalchemy(engine) or record_query(...)
request.user scope["user"]
LogiBoard superuser check A replaceable predicate via set_permission_check
django.core.cache An in-process cache, replaceable via set_cache

Format choices, level filters, context operations, and rotation remain available. Structured serialization now preserves original messages, redacts named fields, and bounds event size; output is not byte-for-byte identical. The no-config setup preserves host handlers and does not create per-level files.

Explicit FASTAPI_LOGGING configuration

For an application-controlled logging setup, pass the FASTAPI_LOGGING configuration to setup_logging. The package does not require a particular settings module, environment loader, or Pydantic Settings implementation.

from fastapi import FastAPI
from fastapi_logging_kit import setup_logging

FASTAPI_LOGGING = {
    "ENABLED": True,
    "COMPONENTS": {},
    "REQUEST_LOGGING": {
        "ENABLED": True,
        "LOG_REQUEST_STARTED": False,
        "LOG_REQUEST_FINISHED": True,
        "EXCLUDED_PATHS": ["/health", "/metrics"],
        "EXCLUDED_PATH_PREFIXES": ["/internal"],
        "QUERY_PARAMS_ENABLED": False,
        "MAX_REQUEST_ID_LENGTH": 80,
        "REQUEST_BODY_ENABLED": False,
        "ERROR_RESPONSE_BODY_ENABLED": False,
        "MAX_BODY_BYTES": 2048,
        "MAX_ERROR_RESPONSE_BYTES": 2048,
        "TRUSTED_PROXIES": [],
    },
}

app = FastAPI()
setup_logging(app, config=FASTAPI_LOGGING)

If no LOGGING dictionary is supplied, the structured configuration uses an additive component activator: it does not replace the host's root logger, log level, or third-party handlers. Installed components are owned by the package. A custom handler can be declared and explicitly attached to root:

FASTAPI_LOGGING = {
    "COMPONENTS": {
        "handlers": {"audit": {"class": "logging.NullHandler"}},
        "root_handlers": ["audit"],
    }
}

The COMPONENTS contract supports formatters, filters, handlers, loggers, replace, disable, root_handlers, and package_handlers. Naming conflicts require explicit replacement; invalid references raise ComponentConfigurationError before handlers are activated.

Developers who explicitly provide LOGGING opt into the process-wide semantics of logging.config.dictConfig, including replacement of the root configuration when it is present in that dictionary. disable_existing_loggers defaults to False. Do not use that option expecting an additive merge.

Request logging operates through pure ASGI middleware. It does not buffer successful responses. Request IDs are checked for safe characters and size, then returned in the configured response header. Forwarded IP addresses are only trusted when the immediate peer belongs to TRUSTED_PROXIES (CIDR networks or individual IPs); otherwise the ASGI client address is used. When deploying behind a reverse proxy, coordinate these settings with your ASGI server's own forwarded-header trust configuration.

Query parameters are omitted by default. Set QUERY_PARAMS_ENABLED=True to log bounded, JSON-escaped query values; common credential keys are redacted, and additional exclusions can be configured through EXCLUDED_FIELDS and EXCLUDED_FIELDS_BY_PATH.

SQL query capture is independently opt-in through LOG_SQL_QUERIES. Its output is bounded by MAX_SQL_BYTES and MAX_SQL_QUERIES. Streaming lifecycle records are independently opt-in through LOG_STREAMING_EVENTS; the middleware still propagates request context through streams when those extra events are disabled.

JSON request-body diagnostics and JSON error-response diagnostics are also opt-in through REQUEST_BODY_ENABLED and ERROR_RESPONSE_BODY_ENABLED. Request-body capture is limited to POST, PUT, and PATCH requests, observes JSON media types only, and captures only chunks that the application itself receives. Error-response capture is restricted to HTTP status codes 400 and above and JSON media types. Both paths enforce byte limits (maximum configurable value: 64 KiB), recursively redact sensitive fields, and never log raw malformed JSON, multipart, or binary bodies. Values that exceed the configured limit are discarded and represented by a marker; request/response messages continue to the application unchanged. Keep both options disabled unless the diagnostic value justifies logging potentially sensitive application data.

The original flat-key API remains available for compatibility with existing installations. New applications should use the structured configuration shown above. Repeating the same setup on a single FastAPI application does not register duplicate request middleware; attempting to reconfigure it with a different mapping raises a descriptive error. Call setup before the ASGI application begins serving requests.

Request middleware settings are copied into each FastAPI application, but Python's logging registry and logger/handler graph are process-wide. Separate FastAPI applications in one process do not receive isolated logging registries.

Contributing and security

See CONTRIBUTING.md for setup, validation, and release steps; CODE_OF_CONDUCT.md for participation guidelines; and SECURITY.md for private vulnerability reporting. AUTHORS.md and CONTRIBUTORS.md record authorship and upstream credits.

Metadata

Release files for fastapi-logging-kit 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastapi-logging-kit 1.0.0
File Size Uploaded Provenance Actions
fastapi_logging_kit-1.0.0.tar.gz 425.0 kB With provenance Details for fastapi_logging_kit-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-logging-kit 1.0.0
File Interpreter ABI Platform Actions
fastapi_logging_kit-1.0.0-py3-none-any.whl Python 3 none any Details for fastapi_logging_kit-1.0.0-py3-none-any.whl

Total release size: 673.7 kB

Release files / fastapi_logging_kit-1.0.0.tar.gz

Download URL fastapi_logging_kit-1.0.0.tar.gz
Size 425.0 kB
Tags Source
SHA-256 checksum
How to use checksums
995b68b0b0b0b6188a4ea35805f1882719e6c614f71374d9016cebe4875df298
BLAKE2b-256 checksum
How to use checksums
5a4f29fddb6ac749eb069f64ee9226dbbad9ca02c9c4d3f4d3f5837da39d3822
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / fastapi_logging_kit-1.0.0-py3-none-any.whl

Download URL fastapi_logging_kit-1.0.0-py3-none-any.whl
Size 248.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
766bd69e51ce71de083d92afbccae83bead7be623b440be38e20240c0f0bf629
BLAKE2b-256 checksum
How to use checksums
3fdbcf1163093ccd59e3cbc874998e31458becbe4382e5487fbfa128acca890f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Security for fastapi-logging-kit 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for fastapi_logging_kit-1.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page