Core Runtime
Logger reference

Base Logger Orchestration

BaseLogger is the main runtime entry point for structured logging in the package. It handles configuration resolution, standard logging setup, structlog integration, async worker lifecycle, and fan-out to configured sink adapters.

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:

  1. Loads and merges config defaults.
  2. Validates schema and sink requirements.
  3. Builds async HTTP workers (if configured).
  4. Builds sink logger instances from sink registry.
  5. 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.