Metadata-Version: 2.5
Name: nopanic-otel
Version: 0.1.0
Summary: OpenTelemetry metrics, span events and live gauges for nopanic resilience policies.
Project-URL: Homepage, https://github.com/dagdelenemre/nopanic
Project-URL: Repository, https://github.com/dagdelenemre/nopanic
Project-URL: Issues, https://github.com/dagdelenemre/nopanic/issues
Project-URL: Changelog, https://github.com/dagdelenemre/nopanic/blob/main/packages/nopanic-otel/CHANGELOG.md
Author-email: Emre Kadir Dağdelen <dagdelen.cyber@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: circuit-breaker,metrics,nopanic,opentelemetry,otel,resilience,retry,tracing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: System :: Monitoring
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: nopanic>=0.3.0
Requires-Dist: opentelemetry-api>=1.20
Provides-Extra: dev
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# nopanic-otel

OpenTelemetry metrics, span events and live gauges for [nopanic](https://github.com/dagdelenemre/nopanic) resilience policies.

```
pip install nopanic-otel
```

```python
import nopanic_otel
from nopanic import circuit_breaker, bulkhead

payments = circuit_breaker(name="payments")
reports = bulkhead(20, name="reports")

nopanic_otel.instrument()                 # every event: counter + span event
nopanic_otel.observe(payments, reports)   # live gauges, read on each collection
```

Configure the OpenTelemetry SDK (providers and exporters) as usual; this package only needs `opentelemetry-api`.

## What you get

**`instrument()`** turns every nopanic event into:

- `nopanic.events` (counter), with attributes `nopanic.kind` (e.g. `retry.attempt_failed`, `breaker.state_change`), `nopanic.policy`, `nopanic.name` and `code.function`;
- `nopanic.retry.delay` and `nopanic.ratelimit.wait` (histograms, seconds);
- an event on the **current span** (`nopanic.retry.attempt_failed`, `nopanic.breaker.rejected`, ...) carrying the event data, so each trace shows the retries, rejections and transitions that happened inside that request.

Pass `metrics_enabled=False` or `span_events=False` to keep only one side, and `meter_provider=` to use a specific provider.

**`observe(*policies)`** registers observable gauges:

| Gauge | Source |
| --- | --- |
| `nopanic.breaker.state` | 0 closed, 1 half_open, 2 open, 3 forced_open, 4 disabled |
| `nopanic.breaker.failure_rate`, `.slow_call_rate`, `.calls` | `breaker.metrics` |
| `nopanic.bulkhead.in_flight` | `bulkhead.in_flight` |
| `nopanic.ratelimit.available_tokens`, `nopanic.ratelimit.rate` | rate limiters (rate: adaptive only) |
| `nopanic.timeout.abandoned` | sync `timeout` workers still running |
| `nopanic.cache.size` | `cache.size` |
| `nopanic.retry_budget.available` | `RetryBudget.available` |

`keyed` policies are expanded: each instance is reported with a `nopanic.key` attribute. Both functions return a callable that undoes them.

## License

MIT.
