-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
X-Ray is a decision-reasoning observability system for multi-step pipelines. It captures why decisions were made (candidates, filters, scores, reasoning), not just what functions ran.
View interactive diagram on dbdiagram.io
| Table | Purpose |
|---|---|
| Run | Pipeline execution (id, pipeline_name, status, timestamps, metadata) |
| Step | Single processing step within a run (input/output counts, reasoning, timing) |
| Payload | Externalized large data (lists >100 items, strings >2KB) |
-
removed_ratio=(input_count - output_count) / input_count— computed at query time -
duration_ms— stored in Step, computed at step end in SDK
---
Located in shared/types.py:
StepType
| Value | Description |
|---|---|
filter |
Removes candidates by criteria |
rank |
Orders candidates by score |
llm |
LLM/AI model call |
retrieval |
Fetches external data |
transform |
Data format changes |
other |
Catch-all |
RunStatus / StepStatus: running, success, error
DetailLevel: summary (counts + samples), full (complete data with truncation)
Entry point for the SDK. Manages Transport lifecycle and provides start_run() context manager.
client = init_xray(XRayConfig(base_url="http://localhost:8000"))
with client.start_run("pipeline") as run:
# Steps created hereRepresents a pipeline execution. Creates Steps, manages context via contextvars.
Single processing step. Captures input/output, timing, and reasoning.
Async buffered HTTP sender with fail-open semantics—network errors are logged but never crash the application.
-
@step(name, step_type)— Instrument a function -
@instrument_class(step_type)— Instrument all public methods of a class -
attach_reasoning(data)— Add reasoning to current step -
attach_candidates(candidates)— Add candidate list to current step
Large data is automatically summarized to keep event sizes manageable:
| Data Type | Threshold | Behavior |
|---|---|---|
| Lists | < 100 items | Stored inline |
| Lists | ≥ 100 items | Externalized with preview |
| Strings | < 2KB | Stored inline |
| Strings | ≥ 2KB | Externalized with preview |
| Candidate lists | Any size | Always inline (id + score + reason only) |
- SDK
summarize_payload()detects large data - Creates reference:
{"_ref": "p-000", "_type": "list", "_count": 500, "_preview": [...]} - Event includes
_payloads: {"p-000": [full data]} - API extracts payloads, stores in Payload table
- Step stores summary only; Payload stores full data
{
"event_type": "run_start",
"id": "uuid",
"pipeline_name": "my-pipeline",
"status": "running",
"started_at": "2024-01-01T00:00:00Z",
"input_summary": {...},
"metadata": {"user_id": "123"},
"_payloads": {...}
}{
"event_type": "step_end",
"id": "uuid",
"run_id": "parent-run-uuid",
"step_name": "filter_candidates",
"step_type": "filter",
"status": "success",
"duration_ms": 150,
"input_count": 100,
"output_count": 25,
"reasoning": {"threshold": 0.7, "removed": 75},
"_payloads": null
}sdk:
base_url: http://localhost:8000
api_key: your-api-key # Optional
buffer_size: 1000 # Max events to buffer
flush_interval: 5.0 # Seconds between flushes
default_detail: summary # summary | fullapi:
database_url: postgresql+asyncpg://localhost:5432/xray
debug: falseConfig discovery searches upward from current directory for xray.config.yaml.
-
Counts as columns —
input_count/output_countare indexed for efficient filtering -
Computed ratios —
removed_ratiocomputed at query time (allows formula changes) - Payload externalization — Large data stored separately, summaries inline
- Candidate preservation — All candidate IDs captured, never truncated
- Fail-open SDK — Network errors never crash the application
- Context managers — Automatic cleanup on exceptions
xray-logger/
├── shared/
│ ├── types.py # StepType, RunStatus, DetailLevel
│ └── config.py # Config discovery
├── sdk/
│ ├── client.py # XRayClient, init_xray()
│ ├── run.py # Run class
│ ├── step.py # Step, PayloadCollector, summarize_payload()
│ ├── transport.py # Async HTTP transport
│ ├── decorators.py # @step, @instrument_class
│ ├── middleware.py # FastAPI/Starlette middleware
│ └── config.py # XRayConfig
├── api/
│ ├── main.py # FastAPI app
│ ├── routes.py # /ingest, /xray/runs, /xray/steps
│ ├── models.py # SQLAlchemy ORM (Run, Step, Payload)
│ ├── schemas.py # Pydantic schemas
│ ├── store.py # Database operations
│ └── config.py # APIConfig
└── examples/
├── competitor_pipeline/ # RAG pipeline example
└── fastapi-middleware/ # HTTP instrumentation example