Skip to content
femtologging
Menu

Read

A first record, end to end.

Build the extension, configure output, emit a structured record, and drain the runtime before exit.

0.2.0 surface · 0.2.0-beta1 forthcoming

A laptop showing blurred code on a dark laboratory bench beneath the objective lens of an electron microscope.

FL-M-005SE · false colour · simulated10 cm illustrative scale

Plate 05The application, before magnification. Nothing unusual is visible at this scale.

Build the documented source

The next release is assumed to be 0.2.0-beta1. It is forthcoming. The package-index command below is the prospective release command; use the source build today.

Forthcoming release · not the current installation path
python -m pip install femtologging==0.2.0b1

Source requirements: Python 3.12 or later and a Rust toolchain. The examples on this site were run with CPython 3.13 on Linux against revision f5bcaa8257f4c59a361dc4f41585b9ecccb9f345. The checkout still declares package version 0.1.0; these are source-verified 0.2.0 examples.

Current source installation
git clone https://github.com/leynos/femtologging.git
cd femtologging
git checkout f5bcaa8257f4c59a361dc4f41585b9ecccb9f345
python -m venv .venv
. .venv/bin/activate
python -m pip install .

On Windows, activate the environment with .venv\Scripts\Activate.ps1. Confirm the Rust toolchain is on PATH before invoking pip.

Configure and emit

basicConfig configures a native stream handler on the root logger. A named logger propagates to it. Per-call extra fields travel with the record, but the default text formatter prints only the logger, level, and message.

"""Run the first record example against the documented femtologging source."""

import sys

from femtologging import (
    basicConfig,
    get_logger,
)

basicConfig(level="INFO", stream=sys.stdout)
logger = get_logger("survey.transport")
root = get_logger("root")

try:
    logger.info("record received", extra={"specimen": 42})
    if not logger.flush_handlers() or not root.flush_handlers():
        message = "Logging did not flush"
        raise RuntimeError(message)
finally:
    root.clear_handlers()
Outputsurvey.transport [INFO] record received

Drain both queue boundaries

Stop producers first. Flush the named logger, then the root logger that owns its output. Clearing the root handlers releases the configured native output workers after draining.

A successful logging call is not a delivery receipt. Check flush results and drop counters. Explicitly owned handler objects should be removed and closed; the worked examples demonstrate this lifecycle.

Choose the next boundary