Metadata-Version: 2.4
Name: xyberos-observability
Version: 0.1.0
Summary: Observability exporters plugin (RFC-0019, M10): OTel, Prometheus, Langfuse, Sentry as thin EventBus exporters
License: Apache-2.0
Keywords: xyberos,plugin,observability,opentelemetry,prometheus,langfuse,sentry
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: xyberos>=1.0
Provides-Extra: otel
Requires-Dist: opentelemetry-sdk; extra == "otel"
Provides-Extra: prometheus
Requires-Dist: prometheus-client; extra == "prometheus"
Provides-Extra: sentry
Requires-Dist: sentry-sdk; extra == "sentry"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"

# xyberos-observability (M10)

Observability/telemetry exporters for Xyberos. Turns the runtime's event stream
into traces and metrics for **OpenTelemetry**, **Prometheus**, **Langfuse**, and
**Sentry** — satisfying RFC-0019 Track L, milestone M10.

## Install

```bash
pip install -e ./observability
```

Optional extras:

```bash
pip install -e "./observability[otel]"      # opentelemetry-sdk (in-memory spans by default)
pip install -e "./observability[prometheus]"# prometheus-client
pip install -e "./observability[sentry]"    # sentry-sdk
```

## How it works

Xyberos emits events (`runtime.request_started`, `brain.response_produced`,
`memory.stored`, ...) on its `EventBus`. This plugin attaches an
`EventRecorder` that forwards each event to the configured exporters:

| Exporter | Destination | What it does |
| --- | --- | --- |
| `OpenTelemetryExporter` | OTel span pipeline | One span per event, named `event.name`, with `event.*` attributes (plus `event.prompt`). Defaults to an `InMemorySpanExporter` so traces are inspectable without a collector. |
| `PrometheusExporter` | Prometheus registry | `xyberos_events_total{event="..."}` counter, one per event name. |
| `LangfuseExporter` | Langfuse `/api/public/ingestion` | One `observation-create` item per event with `name`, `input` (prompt) and `output` (event data). Basic auth with `public_key:secret_key`. |
| `SentryExporter` | Sentry SDK | Adds a breadcrumb per event; captures a message for failures (`runtime.request_failed`, `brain.error`). |

## Usage

```python
from xyberos import create_app
from xyberos_observability import ObservabilityPlugin, OpenTelemetryExporter

app = create_app()
app.load_plugin(ObservabilityPlugin(exporters=[OpenTelemetryExporter()]))

reply = app.chat("hello")          # emits events -> spans
```

Select exporters by environment variable (comma-separated) instead:

```bash
export OBSERVABILITY_EXPORTERS=otel,prometheus,langfuse,sentry
```

```python
from xyberos_observability import ObservabilityPlugin

app.load_plugin(ObservabilityPlugin())
```

For Langfuse, set `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY` and
`LANGFUSE_HOST` (defaults `https://cloud.langfuse.com`).

## Example

```bash
python examples/trace_a_chat.py                       # inspect in-memory spans
python examples/trace_a_chat.py --prometheus          # also track a counter
python examples/trace_a_chat.py --langfuse            # POST traces to Langfuse
```

## Tests

```bash
python -m pytest observability/tests -q
```

Tests use injectable transports / in-memory exporters, so nothing touches the
network or a real collector. The DoD test (`tests/test_plugin.py`) runs
`app.chat(...)` and asserts a trace lands in OTel and Langfuse.
