How to configure Database and Logging
Configure asynchronous database engines with DatabaseSettings and customize structured logging with LoggingSettings and file rotation.
ZCore provides structured configuration schemas for the database engine (DatabaseSettings) and observability pipeline (LoggingSettings), supporting environment variable synchronization, declarative classes, and programmatic runtime initialization.
1. Configuring the Database Engine
Option A: Environment Variables (Zero-Code)
Set database variables in your .env file. ZCore automatically synchronizes flat environment variables with settings.DATABASE:
# .env
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/production_db
POOL_SIZE=20
MAX_OVERFLOW=10Bootstrap db_manager in main.py:
# main.py
from zcore import db_manager, settings
db_manager.init_app(config=settings.DATABASE)Option B: Declarative Settings Subclass
To configure engine options like connection arguments (connect_args) or execution options (execution_options), declare DATABASE in your custom Settings class:
# config.py
from zcore.config import Settings, DatabaseSettings
class AppSettings(Settings):
DATABASE: DatabaseSettings = DatabaseSettings(
url="postgresql+asyncpg://postgres:postgres@localhost:5432/production_db",
pool_size=20,
max_overflow=30,
pool_recycle=3600,
pool_pre_ping=True,
connect_args={"server_settings": {"jit": "off"}},
execution_options={"isolation_level": "REPEATABLE READ"},
extra_engine_kwargs={}
)Option C: Direct db_manager.init_app Invocation
Pass a DatabaseSettings model instance or dictionary directly during startup:
# main.py
from zcore import db_manager
from zcore.config import DatabaseSettings
db_manager.init_app(
config=DatabaseSettings(
url="postgresql+asyncpg://postgres:postgres@localhost:5432/production_db",
pool_size=15,
connect_args={"timeout": 30}
)
)2. Configuring Structured Logging
Option A: Standard Setup with .env
# .env
LOG_LEVEL=INFO
LOG_SQL_QUERIES=False # Flat setting for query logging
SLOW_QUERY_THRESHOLD_MS=200.0 # Independently track slow queriesInitialize logging at the beginning of main.py:
# main.py
from zcore.logging import setup_logging
setup_logging()Option B: Declarative LoggingSettings
Configure file rotation boundaries (max_bytes, backup_count), slow SQL query thresholds, and distinct logger behaviors (muted, passthrough, intercept) in your Settings subclass:
# config.py
from zcore.config import Settings, LoggingSettings
class AppSettings(Settings):
LOGGING: LoggingSettings = LoggingSettings(
level="INFO",
json_format=None, # None: Console in Debug, JSON in Production
log_sql_queries=False, # Disabled by default in rc.2 to avoid noise
slow_query_threshold_ms=200.0, # Log only queries exceeding 200ms (works independently!)
file_path="./logs/app.log", # Enables RotatingFileHandler
max_bytes=20 * 1024 * 1024, # Rotate when file reaches 20MB (default: 10MB)
backup_count=10, # Retain 10 rotated log backups (default: 5)
muted_loggers=["sqlalchemy.engine"],
passthrough_loggers=["uvicorn", "uvicorn.access", "uvicorn.error"]
)Option C: Advanced Programmatic Overrides
setup_logging supports custom structlog processors, extra standard library handlers, and complete logging.config.dictConfig overrides:
# main.py
import logging
from zcore.logging import setup_logging, LoggingSettings
# 1. Custom handlers and processors
setup_logging(
config=LoggingSettings(
level="DEBUG",
file_path="./logs/app.log",
max_bytes=10 * 1024 * 1024,
backup_count=5
),
extra_handlers=[logging.StreamHandler()],
log_level="DEBUG"
)
# 2. Complete dictConfig override
setup_logging(
dict_config={
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {"class": "logging.StreamHandler", "level": "INFO"}
},
"root": {"handlers": ["console"], "level": "INFO"}
}
)SQL Query Logging:
When log_sql_queries is enabled, executed statements are formatted with duration metrics (duration_ms). If slow_query_threshold_ms is set, queries exceeding this limit are tracked and logged independently, even if general query logging is turned off.