Metadata-Version: 2.4
Name: heimdall-sdk
Version: 0.1.0
Summary: Python SDK for Heimdall observability platform
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.95; extra == "fastapi"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: respx>=0.20; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: fastapi>=0.95; extra == "dev"
Requires-Dist: httpx>=0.24; extra == "dev"

# Heimdall Python SDK

Synchronous, fail-safe Python client for the [Heimdall](https://heimdall-ob.com) ingest API. Send telemetry events, errors, and performance metrics from any Python application.

## Installation

```bash
pip install heimdall-sdk
```

With FastAPI middleware support:

```bash
pip install heimdall-sdk[fastapi]
```

## Quick Start

```python
from heimdall import HeimdallClient

client = HeimdallClient(
    api_key="your-api-key",
    service_name="payments-api",
    environment="production",
)

# Send telemetry events
client.success("payment_processed", metadata={"amount": 150, "currency": "USD"})
client.error("payment_failed", metadata={"reason": "insufficient_funds"})
client.warning("retry_attempt", metadata={"attempt": 2})
client.info("user_login", tags={"region": "us-east"})
client.timeout("external_api_call")
client.canceled("bulk_import")
```

## Error Capture

```python
try:
    process_payment(order)
except Exception as exc:
    client.capture_exception(exc, endpoint="/checkout")
    # exc is NOT re-raised by the SDK
```

Manual error reporting:

```python
client.send_error(
    "PaymentGatewayError",
    "Gateway returned 503",
    endpoint="/api/payments",
    stacktrace=traceback.format_exc(),
)
```

## Performance Tracking

Direct call:

```python
client.send_performance(
    "db_query",
    target_type="database",
    target_name="users",
    duration_ms=45,
)
```

Decorator (automatically measures duration):

```python
@client.track("transfer", target_type="function", include_exceptions=True)
def process_transfer(amount: float) -> dict:
    ...
```

Context manager:

```python
with client.timing("bank_sync", target_type="job", target_name="nightly_sync"):
    sync_with_bank()
```

## FastAPI Integration

```python
from fastapi import FastAPI
from heimdall import HeimdallClient
from heimdall.integrations.fastapi import setup_heimdall

app = FastAPI()
client = HeimdallClient(api_key="your-api-key", service_name="my-api")

setup_heimdall(app, client)
```

Every HTTP request automatically gets a `request_duration` performance metric using the route path template (e.g. `GET /users/{user_id}`).

## Configuration

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `api_key` | `str` | required | Heimdall API key |
| `base_url` | `str` | `https://heimdall-ob.com/api/v1` | Override for local development |
| `enabled` | `bool` | `True` | Set `False` to disable all network calls |
| `raise_on_error` | `bool` | `False` | Raise `HeimdallTransportError` on failures |
| `timeout` | `float` | `5.0` | HTTP request timeout in seconds |
| `service_name` | `str` | `None` | Injected into every event's tags |
| `environment` | `str` | `None` | Injected into every event's tags |
| `default_metadata` | `dict` | `None` | Merged into every event's metadata |
| `default_tags` | `dict` | `None` | Merged into every event's tags |

## Fail-Safe by Default

All send methods return `True` on success and `False` on any failure — the SDK never raises into your application unless `raise_on_error=True`.

```python
result = client.success("order_placed")
if not result:
    logger.warning("Heimdall telemetry unavailable")
```

## Development

```bash
git clone <repo>
cd heimdall-sdk
pip install -e ".[dev]"
pytest
```

For more examples see [`specs/001-heimdall-python-sdk/quickstart.md`](specs/001-heimdall-python-sdk/quickstart.md).
