omnixys-observability
Omnixys shared observability package — OpenTelemetry tracing, structlog structured logging, Prometheus metrics, request-context propagation and error classification.
Installation
pip install omnixys-observability
Features
- Tracing: OTLP HTTP trace export with ratio/always-on sampling, FastAPI/httpx/logging auto-instrumentation, and a
@spandecorator for functions and methods - Logging: structlog JSON (or colored pretty) console output, OTLP log export, context enrichment (request/correlation id, user, tenant, trace ids), and recursive secret redaction
- Metrics: Prometheus counters/histograms/gauges for HTTP, GraphQL, DB, Kafka, cache, rate limiting, auth and outbox — plus
RateLimitMetricsandSloMetricshelpers - Request context: contextvars-based
RequestContextpropagation across async boundaries - Errors:
classify_error()/ErrorClassifierbuckets intoserver_error/client_error/internal_error - Runtime:
configure_observability()one-call setup of traces + logs with a shared service resource
Usage
One-call setup
from observability import configure_observability, shutdown_observability
configure_observability(
service_name="ticketing",
otlp_endpoint="http://collector:4318",
environment="production",
)
Structured logging
from observability import configure_logging, get_logger, RequestContext, set_request_context
configure_logging("INFO", service_name="ticketing")
set_request_context(RequestContext(request_id="r1", user_id="u1", tenant_id="t1"))
log = get_logger("ticketing")
log.info("event_created", event_id="e1")
log.error("payment_failed", status=503, token="sk_live_...") # token -> [REDACTED]
LOG_PRETTY=true forces colored console output; production defaults to JSON.
Console vs. Loki levels
The console threshold and the OTLP (Loki) threshold are independent:
configure_logging("INFO", ...)keeps the console atINFO.- The OTLP export defaults to
DEBUG, so debug logs still appear in Grafana/Loki in production while the console stays quiet.
Override the Loki threshold via the OTEL_LOG_LEVEL environment variable or
the otel_log_level parameter (values: NOISE, TRACE, DEBUG, INFO,
WARNING, ERROR; invalid values fall back to DEBUG):
OTEL_LOG_LEVEL=WARNING # Loki receives WARNING and above only
configure_logging("INFO", service_name="ticketing", otel_log_level="DEBUG")
Noise and trace levels
NOISE is the quietest level. It exists for transport/protocol chatter that
carries no value in normal operation (Kafka client requests/responses, OTLP
HTTP exporter POST /v1/logs lines, HTTP connection logs). Records at NOISE
are only emitted to a sink when its level is explicitly set to NOISE
(log_level="NOISE", otel_log_level="NOISE", or LOG_LEVEL/OTEL_LOG_LEVEL).
TRACEsits betweenNOISEandDEBUGand is available for application tracing that you still want to opt into.- Both levels are available on the package logger
(
get_logger("ticketing").noise("kafka_request"),.trace("dns_lookup")) as well as on stdlib loggers (logging.getLogger(...).noise(...),.trace(...)).
The following third-party loggers are re-routed automatically: aiokafka,
kafka, urllib3, requests, httpx, httpcore, and the OTLP exporter.
Their DEBUG/INFO chatter is re-leveled to NOISE so it stays invisible at
default levels but is still recoverable. WARNING and ERROR records from
these loggers pass through unchanged.
Spans
from observability import span
@span
async def process_event(event_id: str) -> None: ...
@span(name="billing.charge", attributes={"provider": "stripe"})
def charge(customer_id: str) -> None: ...
Metrics
from observability import SloMetrics, RateLimitMetrics, http_requests_total
http_requests_total.labels(method="POST", path="/events", status_code="201").inc()
slo = SloMetrics()
slo.record_success()
slo.record_error()
slo.error_rate() # 0.5
rl = RateLimitMetrics()
rl.hit("sms:user:42")
rl.get("sms:user:42") # 1
Error classification
from observability import classify_error
classify_error(HTTPException(status_code=503)) # "server_error"
classify_error(HTTPException(status_code=404)) # "client_error"
classify_error(RuntimeError("boom")) # "internal_error"
Testing
uv run pytest -q # 44 tests
uv run ruff check . # lint
uv run mypy src/ # strict typing
License
GPL-3.0-or-later
Metadata
Release files for omnixys-observability 5.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| omnixys_observability-5.0.0.tar.gz | 62.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| omnixys_observability-5.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.3 kB
Release files / omnixys_observability-5.0.0.tar.gz
| Download URL | omnixys_observability-5.0.0.tar.gz |
|---|---|
| Size | 62.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eb14e76d495aa370be19bc4000558736f99380d8098c3e2bc1e83fab0279ecb7
|
|
BLAKE2b-256 checksum How to use checksums |
63a9b0caa1378d7a1ed119b71e0f2eaae783fe9e3819ee54e1eb6f6155e05935
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.8 {"installer":{"name":"uv","version":"0.12.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / omnixys_observability-5.0.0-py3-none-any.whl
| Download URL | omnixys_observability-5.0.0-py3-none-any.whl |
|---|---|
| Size | 12.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7359735684542d0ba119a47f333e64c1f618d929be1dfd3d58f46b65cffae264
|
|
BLAKE2b-256 checksum How to use checksums |
589f008ff29e0b391716215d27bfbcf58c5250e0009e059a1431b445510265fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.8 {"installer":{"name":"uv","version":"0.12.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|