Skip to main content

Rust-backed logging engine for Metrana (PyO3 bindings for metrana-ingestion-logger).

Project description

metrana-logging-engine

Rust-backed logging engine for Metrana — PyO3 bindings for the metrana-ingestion-logger crate (libs/ingestion_logger).

This package wraps the Rust logger's synchronous, gRPC-backed ingestion client and exposes it to Python. It is intended to be imported by client/metrana as a high-performance logging backend; it has no dependency on the rest of the metrana Python package.

Layout

client/metrana-logging-engine/
├── Cargo.toml              # standalone crate (not a root-workspace member)
├── pyproject.toml          # maturin build backend, abi3 wheel
├── src/
│   ├── lib.rs              # #[pymodule] _metrana_logging_engine
│   ├── config.rs           # Config
│   ├── enums.rs            # ResumeStrategy / Backpressure / ErrorStrategy / LogLevel
│   ├── points.rs           # column extraction (numpy/list) → SeriesFloatPoints
│   ├── logger.rs           # Logger
│   └── errors.rs           # exception hierarchy
└── python/metrana_logging_engine/   # pure-Python wrapper + type stubs

The compiled extension is logger_engine._metrana_logging_engine; __init__.py re-exports its public symbols.

Build

Requires a Rust toolchain and maturin.

make develop          # build + install into the active venv (editable-ish)
# or
maturin develop       # equivalent
maturin build --release   # produce an abi3 wheel under target/wheels/

The wheel is built abi3-py310, so a single wheel per platform covers Python 3.10, 3.11 and 3.12.

Tests

make test builds the extension and runs the pytest suite. It always runs the smoke tests; tests/test_e2e.py additionally drives the full local pipeline (logger -> ingestion -> kafka -> worker -> clickhouse -> query service) but is skipped unless the E2E stack is up:

./development/e2e_up.sh    # from the repo root; see development/README.md
make test

Benchmark

benches/rl_logging_bench.py measures the client-side burst cost of the canonical RL telemetry shape against a live stack (defaults: 1024 envs x 16 metrics, 100 minor points per series per one-minute cycle, ~1.6M points per burst from a single logger). It reports per-cycle enqueue wall time, drain lag until the server acked, CPU and RSS; --cycle-secs 0 runs bursts back-to-back as a max-throughput mode.

The target workspace must already exist (workspaces are provisioned with metrana-admin init-workspace, not through the ingestion API). The defaults match the e2e stack, which pre-creates e2e-tests and disables API-key auth; for any other endpoint pass --workspace and a real --api-key.

. .inephany-env/bin/activate && python benches/rl_logging_bench.py

Usage

from metrana_logging_engine import Config, Logger, ResumeStrategy

cfg = Config(
    api_key="...",
    workspace="my-workspace",
    project="my-project",
    run_name="run-001",
    endpoint="https://ingestion.metrana.ai",
    resume_strategy=ResumeStrategy.Allow,
)

import numpy as np

with Logger(cfg) as logger:
    # Ordered scalar series; steps/timestamps auto-assigned when omitted.
    logger.log_std_floats("loss", "ML_STEP", [1.0, 0.8, 0.6], labels={"split": "train"})

    # NumPy arrays are copied in one memcpy (no per-element unboxing) — the
    # preferred path for packing many points per call. `first_step` gives a
    # contiguous step range and `timestamp_millis` a single uniform timestamp,
    # so you don't build full step/timestamp arrays yourself.
    logger.log_std_floats(
        "loss", "ML_STEP",
        values=np.asarray(losses, dtype=np.float64),
        first_step=1000,
        timestamp_millis=now_ms,
    )

    # RL series with a major step and optional episode.
    logger.log_rl_floats(
        "cartpole", "reward", "ENVIRONMENT_STEP",
        rl_step=42,
        values=[10.0], steps=[5],
        episode=3,
    )

    # Config / arbitrary attributes (nested dicts/lists are flattened).
    logger.log_config({"lr": 1e-3, "batch_size": 32})
# close() runs on __exit__: flushes pending events and joins the sender thread.

API summary

Python Rust
Logger(config) Logger::new
log_std_floats(metric, scale, values, labels=None, *, steps=None, first_step=None, timestamps_millis=None, timestamp_millis=None) log_std_floats (ordered)
log_distributed_floats(...) log_distributed_floats (unordered)
log_rl_floats(env, metric, scale, rl_step, values, episode=None, labels=None, *, steps=…, first_step=…, timestamps_millis=…, timestamp_millis=…) log_rl_floats
log_config(value) / log_attributes(prefix, value) log_config / log_attributes
get_series_last_step(metric, scale, labels=None) get_series_last_step
get_env_last_rl_step_and_episode(env) get_env_last_rl_step_and_episode
extract_sender_errors() extract_sender_errors (as list[str])
close(timeout_secs=None) close

labels accepts a dict[str, str] or a sequence of (key, value) pairs. Durations are passed as seconds (float).

Exceptions

MetranaLoggerError
├── LoggerInitError          # Logger() init/handshake failed
├── EnqueueError             # log_* failed
│   ├── LoggerClosedError
│   ├── QueueFullError       # Backpressure.Raise with a full queue
│   └── ValidationError      # invalid metric/scale/label/points/step/episode
├── SenderError              # background sender-thread errors surfaced
└── ClosingError             # close() failed

Allocator

The extension uses jemalloc (tikv-jemallocator) as its global allocator, governing all Rust allocations in the linked crate graph (prost/tonic/rustls buffers, batching vectors, the Python→Rust point copy). This is the default jemalloc feature.

It is built with jemalloc's disable_initial_exec_tls setting, which puts jemalloc's thread-specific data in the global-dynamic TLS model (allocated lazily via __tls_get_addr) instead of initial-exec. That keeps it out of the static TLS image, so the .so dlopens cleanly with no GLIBC_TUNABLES env var — important for a library imported into arbitrary researcher processes. The trade-off is a small indirection on jemalloc's TSD access; negligible in practice.

To build without jemalloc (system allocator):

maturin develop --release --no-default-features

Maintainer caution: keep disable_initial_exec_tls on for any jemalloc build. Without it, jemalloc's ~2.6 KB TSD uses initial-exec TLS and exceeds glibc's static-TLS surplus for dlopened libraries, so import metrana_logging_engine fails with ImportError: cannot allocate memory in static TLS block. If that ever regresses, the launcher-side escape hatches are GLIBC_TUNABLES=glibc.rtld.optional_static_tls=2097152 (set before python starts) or LD_PRELOADing the .so.

Not yet exposed

  • aggregation_rules on Config — requires protobuf message bindings and is currently always empty.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

metrana_logging_engine-0.0.4-cp310-abi3-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.10+Windows x86-64

metrana_logging_engine-0.0.4-cp310-abi3-musllinux_1_2_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

metrana_logging_engine-0.0.4-cp310-abi3-musllinux_1_2_aarch64.whl (3.7 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

metrana_logging_engine-0.0.4-cp310-abi3-manylinux_2_28_x86_64.whl (3.5 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

metrana_logging_engine-0.0.4-cp310-abi3-manylinux_2_28_aarch64.whl (3.5 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

metrana_logging_engine-0.0.4-cp310-abi3-macosx_11_0_arm64.whl (3.0 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

metrana_logging_engine-0.0.4-cp310-abi3-macosx_10_12_x86_64.whl (3.1 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file metrana_logging_engine-0.0.4-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for metrana_logging_engine-0.0.4-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 c70a44d998d53c4f149192ee942ea4ee1e3872451e0f4a4469f888661edf10f6
MD5 0cfbc1b0c3d37cff32add580610159d6
BLAKE2b-256 016d18c3e3bf56ba6a1d2279f8f7a2e6ac6b88af40a39f2d0a73213c27d029c8

See more details on using hashes here.

File details

Details for the file metrana_logging_engine-0.0.4-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for metrana_logging_engine-0.0.4-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8f7fe9b8e4834c045a21b513f350ff1c4166e3ea6bc563a1487e392eb4ec4041
MD5 2711af8b5b23a0ca0a1e63544dfb60db
BLAKE2b-256 95a08d2acda38bc2b423f6ae4978b487ffca1c652f7c5125c8ba03f657c15768

See more details on using hashes here.

File details

Details for the file metrana_logging_engine-0.0.4-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for metrana_logging_engine-0.0.4-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 faf0f88a1c94ce897b2f3c847b019ccde47c7d640e026b95b148763cafc4b74b
MD5 9a61d989a66efe8dc57a22c44d1feea8
BLAKE2b-256 00014755c1c6660f8bac34d64bc826b6bca61cb29e2409877ad3f75473cb650f

See more details on using hashes here.

File details

Details for the file metrana_logging_engine-0.0.4-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for metrana_logging_engine-0.0.4-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 76e11242c25f4f21db2f39a116b87b1e62b2e4d911a2ba03b5cd132a247a177a
MD5 53b5643ee991a06bbed477f13cac1c22
BLAKE2b-256 482413944fd54f6295ca953fed1b8d7ba6743e6507017a7db273be9c5fbec06b

See more details on using hashes here.

File details

Details for the file metrana_logging_engine-0.0.4-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for metrana_logging_engine-0.0.4-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 bc5275c487604400fd9c5451dacda8ae7089716708ec6d78951c7d50357680f6
MD5 32b4ee2d539db206fe9ca09432321031
BLAKE2b-256 db04c4715cc4b88fc855a37e3b74d1f38cb50825cab0adc1a658fd18b399e8f6

See more details on using hashes here.

File details

Details for the file metrana_logging_engine-0.0.4-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for metrana_logging_engine-0.0.4-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 23fba206b2ccc17479228fe547b6d21b475403759ab1f030c2fbfae806a65dd9
MD5 9679d6df01eb7229037b0fbd86c3985c
BLAKE2b-256 ec45dedb0b306882af3c61d8eedc92ee639aa9d700623c5f66a325c027fa3d5d

See more details on using hashes here.

File details

Details for the file metrana_logging_engine-0.0.4-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for metrana_logging_engine-0.0.4-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d15f8cc0ea58c223b6169e987e5ad10b6bf4bbf394ff2a9893f0089adb54d670
MD5 7785ed215eead6360fc4597b52d591cd
BLAKE2b-256 4e32bc3dce567920cd108055020ab0413a5ed166326f3d09731c3a55428fad20

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page