Metadata-Version: 2.4
Name: surfa-ingest
Version: 0.1.0
Summary: Official Python SDK for Surfa Analytics - Ingest live traffic events
Author-email: Surfa Team <support@surfa.dev>
License: MIT
Project-URL: Homepage, https://surfa.dev
Project-URL: Documentation, https://docs.surfa.dev
Project-URL: Repository, https://github.com/yourusername/surfa
Project-URL: Issues, https://github.com/yourusername/surfa/issues
Keywords: analytics,observability,mcp,ai,llm,monitoring
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
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
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"

# Surfa Ingest SDK

Official Python SDK for ingesting live traffic events to Surfa Analytics.

## Installation

```bash
pip install surfa-ingest
```

## Quick Start

```python
from surfa_ingest import SurfaClient

# Initialize client with your ingest key
client = SurfaClient(ingest_key="sk_live_your_key_here")

# Track events
client.track({
    "kind": "tool",
    "subtype": "call_started",
    "tool_name": "search_web",
    "args": {"query": "AI news"}
})

client.track({
    "kind": "tool",
    "subtype": "call_completed",
    "tool_name": "search_web",
    "status": "success",
    "latency_ms": 234
})

# Flush events to API
client.flush()
```

## Context Manager (Recommended)

Use the context manager to automatically track session lifecycle:

```python
from surfa_ingest import SurfaClient

with SurfaClient(ingest_key="sk_live_your_key_here") as client:
    # Session automatically started
    
    client.track({
        "kind": "tool",
        "subtype": "call_started",
        "tool_name": "search_web"
    })
    
    # Session automatically ended and events flushed on exit
```

## Configuration

```python
client = SurfaClient(
    ingest_key="sk_live_your_key_here",
    api_url="https://api.surfa.dev",  # Default: http://localhost:3000
    flush_at=25,                       # Auto-flush after 25 events
    timeout_s=10,                      # HTTP timeout in seconds
)
```

## Set Runtime Metadata

Track which AI runtime is being used:

```python
client = SurfaClient(ingest_key="sk_live_...")

client.set_runtime(
    provider="anthropic",
    model="claude-sonnet-4-5",
    mode="messages"
)
```

## Event Types

### Tool Events

```python
# Tool call started
client.track({
    "kind": "tool",
    "subtype": "call_started",
    "tool_name": "search_web",
    "direction": "request",
    "args": {"query": "Python tutorials"}
})

# Tool call completed
client.track({
    "kind": "tool",
    "subtype": "call_completed",
    "tool_name": "search_web",
    "direction": "response",
    "status": "success",
    "latency_ms": 234,
    "results": [{"title": "Learn Python", "url": "..."}]
})
```

### Session Events

```python
# Session started
client.session_started()

# Session ended
client.session_ended()
```

### Runtime Events

```python
# LLM request
client.track({
    "kind": "runtime",
    "subtype": "llm_request",
    "direction": "outbound",
    "messages": [{"role": "user", "content": "Hello"}],
    "temperature": 0.7
})
```

## Event Fields

### Required Fields
- `kind` (str): Event type (e.g., "tool", "session", "runtime")

### Optional Fields
- `subtype` (str): Event subtype (e.g., "call_started", "session_ended")
- `tool_name` (str): Name of the tool
- `status` (str): Status (e.g., "success", "error")
- `direction` (str): Direction (e.g., "request", "response")
- `method` (str): HTTP method or similar
- `correlation_id` (str): Correlation ID for pairing events
- `span_parent_id` (str): Parent span ID for tracing
- `latency_ms` (int): Latency in milliseconds
- `ts` (str): Timestamp (ISO 8601 format, auto-generated if not provided)
- Any additional fields will be included in the event payload

## Auto-Flush

Events are automatically flushed when:
1. Buffer reaches `flush_at` events (default: 25)
2. Context manager exits
3. `flush()` is called explicitly

## Error Handling

```python
from surfa_ingest import SurfaClient, SurfaConfigError, SurfaValidationError

try:
    client = SurfaClient(ingest_key="invalid_key")
except SurfaConfigError as e:
    print(f"Configuration error: {e}")

try:
    client.track({"invalid": "event"})  # Missing 'kind'
except SurfaValidationError as e:
    print(f"Validation error: {e}")
```

## Logging

The SDK uses Python's standard logging module:

```python
import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("surfa_ingest")
```

## Development Status

**Current Version: 0.1.0 (Alpha)**

This SDK is in active development. The API may change in future versions.

### Implemented
- ✅ Client initialization
- ✅ Event buffering
- ✅ Session management
- ✅ Context manager support
- ✅ Event validation
- ✅ Runtime metadata

### Coming Soon
- 🔜 HTTP API integration
- 🔜 Automatic retry logic
- 🔜 Background flushing
- 🔜 Async support

## License

MIT

## Support

- Documentation: https://docs.surfa.dev
- Issues: https://github.com/yourusername/surfa/issues
- Email: support@surfa.dev
