FastAPI logging bootstrap: dev-friendly console, production structlog JSON
Project description
fastapi-logkit
FastAPI logging bootstrap: readable console logs in development, structured structlog JSON to stdout in production-minded environments.
- Prefer turning off Uvicorn/Gunicorn access logs and emitting HTTP access as structured middleware logs instead.
- The global exception handler logs unhandled request errors; process-level logs are normalized via Uvicorn/Gunicorn logger wiring.
Installation
pip install fastapi-logkit
PyPI: fastapi-logkit
Usage
fastapi_logkit does not read OS environment variables. Read deploy env, log level, etc. in your app and pass values into helpers.
import os
from fastapi import FastAPI
from fastapi_logkit import setup_logging
from fastapi_logkit.fastapi import install_logkit
def app_env() -> str:
return (os.getenv("APP_ENV") or os.getenv("ENVIRONMENT") or "development").strip()
cfg = setup_logging(
env=app_env(),
level=os.getenv("LOG_LEVEL", "INFO").strip().upper(),
)
app = FastAPI()
install_logkit(app, config=cfg)
- With
install_logkit(..., config=cfg), the exception handler mirrorscfg.json_logs(structured JSON vsapp.errortext). - If
access_logis omitted, it defaults fromis_production_environment(cfg.env).
When running Uvicorn, pass log_config from get_uvicorn_log_config_for_run. After setup_logging / configure_logging, the returned LogKitConfig is kept as the active config; get_uvicorn_log_config_for_run() reads it (via get_active_logkit_config) so silence_uvicorn matches bootstrap without repeating config=:
from fastapi_logkit.integrations.uvicorn import get_uvicorn_log_config_for_run
cfg = setup_logging(env=app_env(), level=os.getenv("LOG_LEVEL", "INFO").strip().upper())
uvicorn.run(
"main:app",
log_config=get_uvicorn_log_config_for_run(),
)
Pass config= or silence_uvicorn= / env= when you need a one-off that differs from the last setup_logging result. If nothing has called setup_logging yet, omitting config falls back to resolving env (default "development") and is_json_logging_environment for silence, same as before.
For isolated tests, clear_active_logkit_config() (in fastapi_logkit.bootstrap) clears the stored config.
Production-style run: uvicorn main:app --host 0.0.0.0 --port 8000 --no-access-log
Behaviour summary (arguments / helpers)
| API / helper | Description |
|---|---|
setup_logging(env=..., level="INFO", json_logs=None, ...) |
Omit json_logs to derive it from is_json_logging_environment(env) (production / prod / staging → JSON pipeline). Stores the resulting LogKitConfig as the active config for helpers below. |
get_active_logkit_config() |
The LogKitConfig from the last successful setup_logging / configure_logging, or None. Also exported from fastapi_logkit. |
clear_active_logkit_config() |
Clears the active config (fastapi_logkit.bootstrap; useful between test cases). |
get_uvicorn_log_config_for_run(...) |
Uvicorn log_config dict. With no args after setup_logging, uses active silence_uvicorn; otherwise config= / silence_uvicorn= / env= as documented in the integration module. |
is_json_logging_environment(env) |
Whether env is treated as a JSON-logging env; string only (does not touch os). |
is_production_environment(env) |
True only for production / prod — default access middleware install in install_logkit. |
resolve_env_name(env) |
If env is None, returns "development" (no env var lookup). |
configure_logging(...) |
Alias of setup_logging. |
Body redaction, proxy IP trust, and which access lines are emitted are configured via AccessLogOptions + install_logkit(..., access_log_options=...).
Proxy headers and originIP
Access logs include clientIP (the immediate TCP peer from ASGI scope["client"]) and originIP (intended “client behind proxies” when enabled).
AccessLogOptions.trust_proxy_headersdefaults toFalse. In that caseoriginIPmatchesclientIP(forwarded headers are ignored), which avoids spoofedX-Forwarded-Forwhen the app is not behind a trusted edge proxy.- With
trust_proxy_headers=True,originIPis resolved in order: first hop ofX-Forwarded-For(comma-separated list), elseX-Real-IP, else the same value asclientIP. Header names are compared case-insensitively as received in the ASGI scope.
Only set trust_proxy_headers=True when a trusted reverse proxy (nginx, a load balancer, etc.) terminates TLS and sets or overwrites these headers for you; otherwise clients can forge them.
Pass the flag via install_logkit(..., access_log_options=AccessLogOptions(trust_proxy_headers=True)) and/or setup_logging(..., access_log_options=AccessLogOptions(trust_proxy_headers=True)) so it lives on LogKitConfig.access_log when you reuse config=.
HTTP access line threshold
Each access line is classified with a stdlib severity: 2xx/3xx → INFO, 4xx → WARNING, 5xx → ERROR. A line is emitted only if that severity is ≥ the configured minimum.
- By default,
install_logkit(..., config=cfg)sets the access minimum fromcfg.level(same string assetup_logging(..., level=...)). For example,level="WARNING"suppresses successful 2xx/3xx access lines but still records 4xx and 5xx. - Set
AccessLogOptions(access_min_level=logging.WARNING)(or another numeric level) to override the threshold without changing the global structlog floor.
JSON line fields (JSON mode)
Each stdout line is produced by structlog.processors.JSONRenderer(), with fields merged as follows:
| Category | Fields |
|---|---|
| Common (processors) | env — name passed into setup_logging. logLevel — numeric Pino-like level (e.g. info=30). The event key is stripped right before rendering. |
Request context (RequestContextMiddleware) |
request_id, method, path merged from structlog contextvars. |
Access log (AccessLogMiddleware) |
statusCode, userAgent, clientIP, originIP, dateTime (ms timestamp), endPoint, pathParams, method, traceBack when present. For 4xx/5xx with body logging enabled, requestBody. |
JSON unhandled_exception_handler without access middleware on the stack |
traceBack, endPoint, method, statusCode (500). May skip when access middleware already logged the same failure. |
| App kwargs | Any keys passed to logger.info("name", **fields) are included verbatim. |
See the fastapi_logkit/ source for processors and middleware details.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_logkit-0.1.2.tar.gz.
File metadata
- Download URL: fastapi_logkit-0.1.2.tar.gz
- Upload date:
- Size: 14.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cdbbf8022cc0cccf5b4019c4500e03621312b3548b4f203e4e1c3ac846fbfb4
|
|
| MD5 |
cabaeebf6b03dcaab326328e3703915f
|
|
| BLAKE2b-256 |
529886a797de41ec2074f750f5ab17d42b35d5a2b2f187d4a45dd0b8d37e8b44
|
File details
Details for the file fastapi_logkit-0.1.2-py3-none-any.whl.
File metadata
- Download URL: fastapi_logkit-0.1.2-py3-none-any.whl
- Upload date:
- Size: 15.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de13b3d1b246cead835af3e180c4bbaaf485ab7de946fb041ca62fe37f9c3862
|
|
| MD5 |
6a3ed634580088a599e244cc391b7cb0
|
|
| BLAKE2b-256 |
565a5c8ebf9dff2a76e58bae6e4c16208e93394c058daf9e1fe4fb439451b063
|