Multi-provider LLM cost observability SDK
Project description
LLM Cost Observability SDK
Client-side SDK for provider response interception, usage extraction, request buffering, and optional telemetry flush to a backend cost pipeline.
What This SDK Does
- Wraps provider SDK methods without changing normal response behavior.
- Extracts usage metadata from provider responses locally.
- Buffers request details in-memory.
- Flushes buffered batches on size/time thresholds.
- Optionally sends flushed batches to backend telemetry endpoint.
- Supports lazy API-key verification for direct server API calls via
CostAnalyticsClient.
What This SDK Does Not Do On Client
- Does not perform authoritative upstream pricing sync on the client.
- Does not do final backend-grade cost computation in the main intercept-and-flush path.
- Does not require provider credentials to leave the client environment.
Architecture (Current)
- Your app calls provider SDK (Anthropic/OpenAI/custom).
- Wrapped method runs, returns original provider response.
- Interceptor extracts usage/model/stop reason.
RequestDetailsBufferstores request details locally.- Buffer flushes when:
FLUSH_BATCH_SIZEreached (default50), or- timer hits
FLUSH_INTERVAL_SECONDS(default30).
- If telemetry is configured, flushed batch is POSTed to backend (
/v1/telemetry/flushby default). - Backend resolves pricing and computes final costs.
Package Layout (Relevant)
my-sdk/src/sdk.py:CostAnalyticsSDKfacade.my-sdk/src/pricing/interceptor.py: wrapping and extraction pipeline.my-sdk/src/pricing/extractors.py: provider extractors.my-sdk/src/pricing/aggregator.py: request buffer + flush triggers.my-sdk/src/api/telemetry.py: telemetry sender with failed flush retention/retry behavior.my-sdk/src/client.py: authenticated API client (CostAnalyticsClient) with lazy key verification.my-sdk/src/auth/Config.py: env-based API key loading (CA_API_KEY).
Install
pip install -e .
Quick Start
1) Wrap a Provider Client
from anthropic import Anthropic
from sdk import CostAnalyticsSDK
sdk = CostAnalyticsSDK(server_url="https://telemetry.example.com")
client = Anthropic()
client = sdk.wrap_client(
client=client,
provider="anthropic",
method_path="messages.create",
)
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=128,
messages=[{"role": "user", "content": "Hello"}],
)
print(sdk.get_metrics())
2) Wrap Other Client Shapes
from sdk import CostAnalyticsSDK
sdk = CostAnalyticsSDK(server_url="https://telemetry.example.com")
client = sdk.wrap_client(
client=client,
provider="custom-provider",
method_path="responses.create",
)
3) Manual Flush
from pricing import get_request_buffer
buffer = get_request_buffer()
buffer.flush()
Core APIs
CostAnalyticsSDK (my-sdk/src/sdk.py)
CostAnalyticsSDK(server_url: Optional[str] = None)wrap_client(client, provider, method_path, response_to_dict=None, metadata=None)process_response(response, provider, request_id=None, metadata=None)get_metrics()get_pending_requests()flush_buffer()
get_metrics() currently returns buffer-oriented metrics:
{
"buffer_size": 12,
"pending_requests": 12
}
Buffer (my-sdk/src/pricing/aggregator.py)
FLUSH_BATCH_SIZE = 50FLUSH_INTERVAL_SECONDS = 30get_request_buffer()/get_cost_aggregator()RequestDetailsBuffer.record_request(...)RequestDetailsBuffer.flush()RequestDetailsBuffer.get_pending_requests()
Telemetry (my-sdk/src/api/telemetry.py)
TelemetryClient behavior:
- Sends flush payload to
POST {server_url}/v1/telemetry/flush(default endpoint path). - Includes headers:
Content-Type: application/jsonX-Client-ID: <uuid>- optional
Authorization: Bearer <api_key>
- On flush failure, retains up to last 5 failed batches in-memory.
- If failure looks like "request not received", retries once immediately.
- Failed batches are retried on subsequent flush attempts.
Auth for SDK-to-Server API Calls
CostAnalyticsClient (my-sdk/src/client.py) supports direct authenticated calls to server APIs.
- Reads
CA_API_KEYwhenapi_keynot passed. - Performs lazy auth verification against
GET /v1/auth/verify(default path). - Sends request metadata headers:
AuthorizationX-CA-Key-IdX-CA-User-IdX-Request-IdX-CA-ProviderX-CA-Model
Example:
from client import CostAnalyticsClient
client = CostAnalyticsClient(
api_key="ca_live_...",
base_url="https://api.example.com",
)
resp = client.request("GET", "/v1/costs")
print(resp.status_code)
Environment Variables
CA_API_KEY: client API key forCostAnalyticsClient.CA_API_BASE_URL: optional base URL override forCostAnalyticsClient.
Note: backend services may require additional variables (for example server HMAC secret) that are configured in the server repository.
Backend Contract Expectations
Telemetry flush endpoint should accept payload in this shape:
{
"client_id": "uuid",
"batch": [
{
"timestamp": "2026-01-01T00:00:00.000000",
"request_id": "req-123",
"model": "claude-3-haiku-20240307",
"provider": "anthropic",
"input_tokens": 100,
"output_tokens": 50,
"cache_read_tokens": 0,
"cache_creation_tokens": 0,
"stop_reason": "end_turn",
"metadata": {"method": "messages.create"}
}
]
}
Auth verification endpoint expected by CostAnalyticsClient:
GET /v1/auth/verify- Response:
{
"user_id": "...",
"api_key_id": "..."
}
Testing
pip install -e ".[dev]"
pytest tests/ -v
Notes on Compatibility Surface
The SDK exposes one generic extractor/interceptor path. Provider names are metadata values passed to wrap_client; authoritative pricing resolution lives on the backend.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file modelmetre-0.1.0.tar.gz.
File metadata
- Download URL: modelmetre-0.1.0.tar.gz
- Upload date:
- Size: 14.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17a78071304a9ce6e10ae5e98d1c80b2e6e0cb9ffa2188acfd466875c331b734
|
|
| MD5 |
2aa0602af250401a36faa16f9c4a245b
|
|
| BLAKE2b-256 |
d0fa11d6cc6447f83bbb15885126a45f612d20a22e0dc4c150fdc757de962cfa
|
File details
Details for the file modelmetre-0.1.0-py3-none-any.whl.
File metadata
- Download URL: modelmetre-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57d1a8c8cc677704650514194f88898b10bf1b159ce68016ffaf9e5a6f93fd73
|
|
| MD5 |
f5a9efd98140e035e897708fcbdedf54
|
|
| BLAKE2b-256 |
da71d62d4afa3142436758a8af44f726d6496c7a3d087136b1aeb2ab593dccad
|