stdlib Logging Bridge
Capture Python’s standard library logging output in fapilog’s structured pipeline.
Overview
Many Python libraries use the standard logging module. The stdlib bridge lets you:
Capture third-party library logs in fapilog’s structured format
Migrate gradually from stdlib to fapilog
Unify all application logs in a single pipeline
Quick Start
import logging
import fapilog
from fapilog.core.stdlib_bridge import enable_stdlib_bridge
# Get a fapilog logger
logger = fapilog.get_logger(preset="production")
# Enable the bridge - stdlib logs now flow to fapilog
enable_stdlib_bridge(logger)
# Third-party library logs are now captured
logging.getLogger("requests").info("This goes to fapilog")
logging.getLogger("sqlalchemy").warning("This too")
API Reference
enable_stdlib_bridge()
def enable_stdlib_bridge(
logger: Any,
*,
level: int = logging.INFO,
remove_existing_handlers: bool = False,
capture_warnings: bool = False,
logger_namespace_prefix: str = "fapilog",
target_loggers: Iterable[logging.Logger] | None = None,
force_sync: bool = False,
loop_thread_name: str = "fapilog-stdlib-bridge",
startup_timeout: float = 2.0,
) -> None:
Parameter |
Default |
Description |
|---|---|---|
|
required |
fapilog logger instance to forward logs to |
|
|
Minimum level to capture |
|
|
Remove existing handlers from target loggers |
|
|
Also capture |
|
|
Prefix for loggers to ignore (loop prevention) |
|
|
Specific loggers to bridge; |
|
|
Force synchronous processing (avoid in async apps) |
|
|
Background thread name |
|
|
Timeout for background loop startup |
Common Use Cases
Capture All stdlib Logs
# Bridge root logger - captures everything
enable_stdlib_bridge(logger, level=logging.DEBUG)
Capture Specific Libraries
import logging
# Only capture requests and sqlalchemy
enable_stdlib_bridge(
logger,
target_loggers=[
logging.getLogger("requests"),
logging.getLogger("sqlalchemy.engine"),
],
)
Capture Python Warnings
import warnings
# Include warnings.warn() output
enable_stdlib_bridge(logger, capture_warnings=True)
warnings.warn("This will appear in fapilog output")
Replace Existing Handlers
# Remove default handlers, use only fapilog
enable_stdlib_bridge(logger, remove_existing_handlers=True)
Framework Integration
Django
Django uses stdlib logging extensively. To unify with fapilog:
# settings.py or apps.py
import logging
import fapilog
from fapilog.core.stdlib_bridge import enable_stdlib_bridge
# In AppConfig.ready() or similar startup hook
logger = fapilog.get_logger(preset="production")
enable_stdlib_bridge(
logger,
target_loggers=[
logging.getLogger("django"),
logging.getLogger("django.request"),
logging.getLogger("django.db.backends"),
],
)
Note: For complete Django integration, see the Django cookbook (coming soon).
Celery
Celery workers use stdlib logging for task execution:
# celery.py or tasks.py
import logging
from celery.signals import worker_process_init
import fapilog
from fapilog.core.stdlib_bridge import enable_stdlib_bridge
@worker_process_init.connect
def setup_logging(**kwargs):
logger = fapilog.get_logger(preset="production")
enable_stdlib_bridge(
logger,
target_loggers=[
logging.getLogger("celery"),
logging.getLogger("celery.task"),
],
)
Level Mapping
stdlib Level |
fapilog Method |
|---|---|
|
|
|
|
|
|
|
|
|
|
Preserved Context
The bridge preserves stdlib LogRecord attributes:
# These fields are added to fapilog events:
{
"stdlib_logger": "requests.packages.urllib3",
"module": "connectionpool",
"filename": "connectionpool.py",
"lineno": 824,
"funcName": "urlopen",
}
Loop Prevention
The bridge automatically ignores logs from fapilog’s internal loggers to prevent infinite loops. By default, any logger starting with "fapilog" is ignored.
# Customize the prefix if needed
enable_stdlib_bridge(logger, logger_namespace_prefix="myapp.fapilog")
Performance Considerations
The bridge runs in a background thread for non-blocking operation
Async apps should NOT use
force_sync=TrueHigh-volume stdlib logging may impact performance; consider raising
level
Troubleshooting
Logs Not Appearing
Check the
levelparameter - default isINFO, notDEBUGVerify the logger name matches
target_loggersCheck if logs are being filtered by fapilog’s log level
Duplicate Logs
If you see duplicate logs:
# Remove existing handlers when enabling bridge
enable_stdlib_bridge(logger, remove_existing_handlers=True)
Import Errors
If enable_stdlib_bridge is not found:
# Full import path
from fapilog.core.stdlib_bridge import enable_stdlib_bridge