Metadata-Version: 2.4
Name: klyna
Version: 1.0.0
Summary: Official Klyna SDK for Python — Flask, FastAPI, Django, Starlette middleware
License: MIT
Keywords: klyna,api-monitoring,flask,fastapi,django,middleware
Classifier: Programming Language :: Python :: 3
Classifier: Framework :: Flask
Classifier: Framework :: Django
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# klyna

Official Klyna SDK for Python. Automatically captures HTTP request metrics and sends them to the Klyna platform. Zero external dependencies — pure Python stdlib.

## Installation

```bash
pip install klyna
```

## Quick Start

### FastAPI / Starlette (ASGI)

```python
from fastapi import FastAPI
from klyna import KlynaASGIMiddleware, KlynaConfig

app = FastAPI()
config = KlynaConfig(api_key='sk_live_...')

# Wraps FastAPI, Starlette, or Django ASGI
app = KlynaASGIMiddleware(app, config)
```

### Flask

```python
from flask import Flask
from klyna import KlynaFlask, KlynaConfig

app = Flask(__name__)
config = KlynaConfig(api_key='sk_live_...')
klyna = KlynaFlask(app, config)
```

Application factory pattern:

```python
from klyna import KlynaFlask, KlynaConfig

klyna = KlynaFlask()

def create_app():
    app = Flask(__name__)
    klyna.init_app(app, KlynaConfig(api_key='sk_live_...'))
    return app
```

### Django

Add to `settings.py`:

```python
MIDDLEWARE = [
    'klyna.middleware.django.KlynaDjangoMiddleware',
    # ... your other middleware
]

KLYNA_API_KEY = 'sk_live_...'
```

Or configure programmatically in `wsgi.py`:

```python
from klyna import KlynaConfig
from klyna.middleware.django import KlynaDjangoMiddleware

application = get_wsgi_application()
application = KlynaDjangoMiddleware(application, KlynaConfig(api_key='sk_live_...'))
```

### Starlette

```python
from starlette.applications import Starlette
from klyna import KlynaASGIMiddleware, KlynaConfig

app = Starlette(routes=[...])
app = KlynaASGIMiddleware(app, KlynaConfig(api_key='sk_live_...'))
```

## Configuration Reference

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `api_key` | `str` | **required** | Your Klyna API key (`sk_live_...`) |
| `base_url` | `str` | `https://app.klyna.io` | Override for self-hosted deployments |
| `batch_size` | `int` | `50` | Flush when queue reaches this size |
| `flush_interval` | `float` | `5.0` | Flush interval in seconds |
| `sample_rate` | `float` | `1.0` | Fraction of requests to capture (0.0–1.0) |
| `ignored_paths` | `List[str]` | `['/health', '/healthz', '/readyz', '/metrics', '/favicon.ico']` | Paths to skip |
| `timeout` | `float` | `10.0` | HTTP request timeout in seconds |
| `debug` | `bool` | `False` | Log SDK activity to stderr |

## Graceful Shutdown

The SDK registers an `atexit` handler automatically. For explicit control:

```python
import signal
from klyna import KlynaClient, KlynaConfig

client = KlynaClient(KlynaConfig(api_key='sk_live_...'))

def handler(sig, frame):
    client.shutdown()
    raise SystemExit(0)

signal.signal(signal.SIGTERM, handler)
```

## License

MIT
