Metadata-Version: 2.4
Name: xray-logger
Version: 0.1.1
Summary: Decision-level observability for ML/LLM pipelines
Author-email: Mohit Nagaraj <mohitnagaraj20@gmail.com>
License: MIT
Requires-Python: >=3.12
Requires-Dist: pydantic>=2.5
Requires-Dist: pyyaml>=6.0
Provides-Extra: all
Requires-Dist: aiosqlite>=0.20; extra == 'all'
Requires-Dist: asyncpg>=0.29; extra == 'all'
Requires-Dist: fastapi>=0.109; extra == 'all'
Requires-Dist: httpx>=0.27; extra == 'all'
Requires-Dist: mypy>=1.8; extra == 'all'
Requires-Dist: pytest-asyncio>=0.23; extra == 'all'
Requires-Dist: pytest>=8.0; extra == 'all'
Requires-Dist: respx>=0.21; extra == 'all'
Requires-Dist: ruff>=0.2; extra == 'all'
Requires-Dist: sqlalchemy[asyncio]>=2.0; extra == 'all'
Requires-Dist: starlette>=0.27; extra == 'all'
Requires-Dist: uvicorn>=0.27; extra == 'all'
Provides-Extra: api
Requires-Dist: aiosqlite>=0.20; extra == 'api'
Requires-Dist: asyncpg>=0.29; extra == 'api'
Requires-Dist: fastapi>=0.109; extra == 'api'
Requires-Dist: sqlalchemy[asyncio]>=2.0; extra == 'api'
Requires-Dist: uvicorn>=0.27; extra == 'api'
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.2; extra == 'dev'
Provides-Extra: sdk
Requires-Dist: httpx>=0.27; extra == 'sdk'
Requires-Dist: starlette>=0.27; extra == 'sdk'
Description-Content-Type: text/markdown

# X-Ray Logger

**Decision-level observability for ML/LLM pipelines.**

X-Ray captures *why* decisions were made—candidates considered, filters applied, scores computed, and reasoning behind each step—not just what functions ran.

## Quick Start

### 1. Start the Server

```bash
docker run -d -p 8000:8000 \
  -e XRAY_DATABASE_URL=sqlite+aiosqlite:///./xray.db \
  ghcr.io/mohit-nagaraj/xray-logger:latest
```

### 2. Install the SDK

```bash
pip install xray-logger
```

### 3. Instrument Your Code

```python
from xray_logger import init_xray, step, attach_reasoning

client = init_xray(base_url="http://localhost:8000")

@step(step_type="filter")
def filter_items(items, threshold=0.5):
    result = [i for i in items if i["score"] >= threshold]
    attach_reasoning({"threshold": threshold, "removed": len(items) - len(result)})
    return result

with client.start_run("my-pipeline"):
    filtered = filter_items(items)
```

## Features

- **Decision Transparency** - Capture candidates, scores, and reasoning at each step
- **Lightweight SDK** - Simple decorators, fail-open design
- **FastAPI Middleware** - Automatic HTTP request instrumentation
- **Query API** - Filter runs by pipeline, user, status

## Documentation

- [Quick Start Guide](https://github.com/mohit-nagaraj/xray-logger/wiki/Quick-Start)
- [Architecture](https://github.com/mohit-nagaraj/xray-logger/wiki/Architecture)
- [Examples](./examples)

## Step Types

| Type | Use Case |
|------|----------|
| `filter` | Removing candidates by criteria |
| `rank` | Ordering candidates by score |
| `llm` | LLM/AI model calls |
| `retrieval` | Fetching external data |
| `transform` | Data transformations |

## Self-Hosting with Docker Compose

```bash
git clone https://github.com/mohit-nagaraj/xray-logger.git
cd xray-logger
cp .env.example .env
docker-compose up -d
```

## License

MIT
