Skip to content

aiologging 0.2.0

Latest

Choose a tag to compare

@m6mok m6mok released this 09 Jul 07:54

Breaking release: the logging pipeline is now queue-based and the API strictly follows the standard logging module.

Highlights

  • Background consumer: records are created at the call site and enqueued; a background task performs handler I/O, so await logger.info(...) never waits for a file write or an HTTP request.
  • Configurable delivery: delivery="enqueue" (default, resolves on enqueue) or "await" (resolves after handlers processed the record) — via basicConfig or per logger.
  • Configurable backpressure: bounded queue with overflow="block" (default, no records lost), "drop_new" or "drop_old".
  • Stdlib bridge: captureStdlib() / basicConfig(capture_stdlib=True) routes third-party (standard logging) records through the same async handlers — thread-safe, with pre-loop buffering and feedback-loop protection.
  • Lifecycle: lazy consumer start, await aiologging.flush(), await aiologging.shutdown(), transparent event-loop change recovery (queued and in-flight records are rescued).
  • API parity with logging.Logger: getEffectiveLevel, getChild/getChildren, hasHandlers, makeRecord, findCaller with stacklevel, parent/propagate/filters attributes, module-level convenience coroutines, disable(level), getLogger() returning the root logger.

Breaking changes

  • Removed Logger.setFormatter/getFormatter (formatters live on handlers), getLevel (use getEffectiveLevel), disable()/enable() methods (use the disabled attribute or aiologging.disable), setParent/getParent, getRootLogger, getLoggerContext, log_async.
  • async with logger: now flushes the queue instead of closing the shared logger instance; call await aiologging.shutdown() once at application exit.
  • await logger.info(...) returns once the record is enqueued (configurable), not after handler I/O.

Fixes

  • Handlers can be constructed outside a running event loop on Python 3.9 (lazy asyncio.Lock creation).
  • A record being dispatched when the event loop is torn down is no longer lost.

Tested on Python 3.9–3.14 (pytest + mypy strict).