Metadata-Version: 2.4
Name: reqly
Version: 0.1.0
Summary: Auto-instrumentation SDK for FastAPI and Flask: zero-code latency, error rates, and status codes shipped to a Reqly collector.
Author: reqly
License-Expression: MIT
Project-URL: Homepage, https://github.com/tanisheesh/reqly
Project-URL: Repository, https://github.com/tanisheesh/reqly
Project-URL: Issues, https://github.com/tanisheesh/reqly/issues
Project-URL: Documentation, https://github.com/tanisheesh/reqly/blob/main/CONTRIBUTING.md
Keywords: observability,apm,monitoring,fastapi,flask,telemetry,metrics,latency,tracing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Classifier: Framework :: FastAPI
Classifier: Framework :: Flask
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx<1.0,>=0.27
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.100; extra == "fastapi"
Provides-Extra: flask
Requires-Dist: flask>=2.3; extra == "flask"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: fastapi>=0.100; extra == "dev"
Requires-Dist: flask>=2.3; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"

# Reqly

Auto-instrumentation SDK for FastAPI and Flask. One line captures latency, status codes, and error rates for every request and ships them to an [Reqly collector](../collector).

## Install

```bash
pip install reqly
```

(For local development against this monorepo: `pip install -e ./sdk[dev]`.)

## Usage

```python
from fastapi import FastAPI
import reqly

app = FastAPI()
reqly.instrument(app, service_name="checkout-api")
```

```python
from flask import Flask
import reqly

app = Flask(__name__)
reqly.instrument(app, service_name="checkout-api")
```

`instrument()` auto-detects FastAPI vs Flask — no other code changes needed.

## Configuration

Every option can be passed as a kwarg to `instrument()` or set via environment variable. Resolution order: kwarg > env var > default.

| kwarg | env var | default |
|---|---|---|
| `service_name` | `REQLY_SERVICE_NAME` | `sys.argv[0]` basename |
| `collector_url` | `REQLY_COLLECTOR_URL` | `http://localhost:8000` |
| `api_key` | `REQLY_API_KEY` | `None` |
| `sample_rate` | `REQLY_SAMPLE_RATE` | `1.0` |
| `flush_interval_seconds` | `REQLY_FLUSH_INTERVAL_SECONDS` | `5.0` |
| `max_batch_size` | `REQLY_MAX_BATCH_SIZE` | `200` |
| `max_queue_size` | `REQLY_MAX_QUEUE_SIZE` | `2000` |
| `ignore_routes` | `REQLY_IGNORE_ROUTES` (comma-separated) | `/health,/metrics` |
| `capture_request_body` | `REQLY_CAPTURE_REQUEST_BODY` | `False` |

## Design guarantees

- **Fails open.** Any internal SDK error is caught and logged once; instrumentation then disables itself rather than risk repeatedly raising into your app. A slow or unreachable collector never slows down your app — all shipping happens off a background thread with strict per-phase HTTP timeouts.
- **Bounded cardinality.** Captured routes are the framework's matched route *template* (`/users/{id}`), never the raw path (`/users/123`). Unmatched paths (404s, scanners) collapse into a single `__unmatched__` bucket instead of blowing up cardinality.
- **Bounded memory.** Events are held in a fixed-size in-memory queue; under sustained backpressure, the oldest events are dropped (and counted) rather than growing unbounded or blocking request threads.

## Architecture

See [`../ARCHITECTURE.md`](../ARCHITECTURE.md#2-sdk-design) for the full design rationale (why pure ASGI middleware over `BaseHTTPMiddleware`, why a background thread over `asyncio.create_task`, why `httpx` over `requests`, etc).

## Running tests

```bash
pip install -e .[dev]
pytest
```
