Metadata-Version: 2.4
Name: nodus-observability
Version: 0.1.0
Summary: OTel tracing, Prometheus metrics, structured JSON logging, and trace ContextVars
Author: Shawn Knight
License: MIT
Project-URL: Homepage, https://github.com/Masterplanner25/nodus-observability
Project-URL: Repository, https://github.com/Masterplanner25/nodus-observability
Keywords: observability,opentelemetry,prometheus,logging,tracing,nodus
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: logging
Requires-Dist: python-json-logger>=2.0.0; extra == "logging"
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.0.0; extra == "otel"
Requires-Dist: opentelemetry-sdk>=1.0.0; extra == "otel"
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.0.0; extra == "otel"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.60b0; extra == "otel"
Provides-Extra: metrics
Requires-Dist: prometheus-client>=0.10.0; extra == "metrics"
Provides-Extra: all
Requires-Dist: nodus-observability[logging,metrics,otel]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: python-json-logger>=2.0.0; extra == "dev"
Dynamic: license-file

# nodus-observability

OpenTelemetry bootstrap, Prometheus registry, structured JSON logging, and async-safe trace ContextVars. Zero required dependencies beyond `python-json-logger` — OTel and Prometheus are optional extras.

## Install

```bash
pip install nodus-observability                    # core only
pip install "nodus-observability[metrics]"         # + prometheus-client
pip install "nodus-observability[otel]"            # + opentelemetry stack
pip install "nodus-observability[all]"             # everything
```

## Trace context

```python
from nodus_observability import set_trace_id, get_trace_id, reset_trace_id, ensure_trace_id

tok = set_trace_id("req-abc-123")
print(get_trace_id())    # "req-abc-123"
reset_trace_id(tok)
```

## Structured logging

```python
from nodus_observability import configure_logging, get_trace_id

configure_logging(
    env="production",
    log_level="INFO",
    get_trace_id_fn=get_trace_id,   # inject trace_id from ContextVar
)
```

## OTel tracing

```python
from nodus_observability import init_otel, get_tracer

init_otel(service_name="my-service")   # reads OTEL_EXPORTER_OTLP_ENDPOINT
tracer = get_tracer("my-module")

with tracer.start_as_current_span("my-operation") as span:
    span.set_status("ok")
```

## Prometheus metrics

```python
from nodus_observability import create_registry, Counter

REGISTRY = create_registry()   # never use the default global registry

requests_total = Counter(
    "myapp_requests_total",
    "Total requests",
    ["method", "status"],
    registry=REGISTRY,
)
requests_total.labels(method="GET", status="200").inc()
```

## Extracted from

`AINDY/platform_layer/trace_context.py`, `otel.py`, `metrics.py`, and `log_config.py` in the A.I.N.D.Y. runtime.
