1. Behavior and Context
The class is designed for services that need:
- A single logger facade for both synchronous and asynchronous usage.
- Structured logs emitted through structlog.
- Optional secondary sink delivery (Datadog, Kafka, Redis, etc.).
- Graceful startup and shutdown in application lifecycle hooks.
During configuration:
- Loads and merges config defaults.
- Validates schema and sink requirements.
- Builds async HTTP workers (if configured).
- Builds sink logger instances from sink registry.
- Configures stdlib handlers and structlog pipeline.
2. Purpose
- Single Control Plane: One object to manage all logging channels.
- Sync/Async Symmetry: Matching debug/info/... and adebug/ainfo/... APIs.
- Operational Safety: Protects against use-before-setup and best-effort sink failures.
3. High-Level API & Examples
Example 1: Synchronous Logging Lifecycle
python
from jazzmine.logging import BaseLogger
config = {
"name": "gateway",
"level": "INFO",
"json": True,
"sinks": [{"type": "console"}],
}
logger = BaseLogger(config)
logger.resolve_config()
logger.info("service boot", version="1.2.0")Example 2: Async Worker Startup and Shutdown
python
import asyncio
from jazzmine.logging import BaseLogger
async def main():
logger = BaseLogger({
"name": "api",
"level": "INFO",
"json": True,
"sinks": [
{"type": "console"},
{"type": "http", "url": "https://collector.internal/logs", "async": True},
],
})
logger.resolve_config()
await logger.start_async_workers()
await logger.ainfo("request completed", status=200)
await logger.shutdown(timeout=3.0)
asyncio.run(main())4. Detailed Class Functionality
__init__(raw_config: Union[Dict[str, Any], str, Path])
Stores the raw configuration source (dict or path), initializes logger references, async worker map, and sink list.
resolve_config() -> Dict[str, Any]
- Loads config via ConfigLoader.load.
- Applies default values via ConfigLoader.merge_defaults.
- Validates via ConfigValidator.validate.
- Creates async workers and sink logger objects via LoggingConfigurator.
- Configures stdlib logging and structlog.
- Initializes and stores configured structlog and stdlib logger handles.
start_async_workers() -> None
Starts all AsyncHttpWorker instances and initializes each sink logger via sink.initialize().
shutdown(timeout: float = 2.0) -> None
Stops async workers and calls sink shutdown() methods. Exceptions are caught and printed to avoid shutdown crashes.
Sync Logging Methods
- debug, info, warning, error, critical
- Emit through structlog and then attempt sink fan-out.
- Sink exceptions are swallowed to preserve application flow.
Async Logging Methods
- adebug, ainfo, awarning, aerror, acritical
- Call structlog in a thread via asyncio.to_thread, then concurrently dispatch to sinks with asyncio.gather(..., return_exceptions=True).
Accessors
- get_structlog() -> structlog.BoundLogger
- get_stdlib() -> logging.Logger
Both require prior configuration (resolve_config()).
5. Error Handling
- Raises LoggerError if logging methods are called before resolve_config().
- Startup and shutdown sink/worker errors are caught and printed (best-effort behavior).
- Sink dispatch errors in sync methods are swallowed.
6. Remarks
- Call resolve_config() exactly once during service bootstrap.
- For async sinks, pair startup with explicit shutdown in application lifecycle hooks.
- If strict delivery guarantees are required, extend sink implementations with retry/backpressure semantics.