Metadata-Version: 2.4
Name: indratrace
Version: 0.1.0
Summary: OpenTelemetry-native observability SDK for the IndraTrace platform — one-line traces, logs, metrics, and model-call token usage for web apps and AI agents.
Author: Indrasol
License: Apache-2.0
Project-URL: Homepage, https://indrasol.com
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-sdk>=1.20
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20
Provides-Extra: fastapi
Requires-Dist: opentelemetry-instrumentation-fastapi; extra == "fastapi"
Provides-Extra: anthropic
Requires-Dist: opentelemetry-instrumentation-anthropic>=0.40.0; extra == "anthropic"
Provides-Extra: openai
Requires-Dist: opentelemetry-instrumentation-openai>=0.40.0; extra == "openai"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: fastapi; extra == "dev"
Requires-Dist: uvicorn; extra == "dev"
Requires-Dist: httpx; extra == "dev"
Requires-Dist: anthropic>=0.40; extra == "dev"
Requires-Dist: openai>=1.40; extra == "dev"

# IndraTrace SDK

OpenTelemetry-native observability SDK for the IndraTrace platform — one-line
instrumentation for web apps and AI agents: traces, logs, metrics, and
model-call token usage.

```bash
pip install indratrace
```

`init_observability()` ships traces, logs, and metrics; `trace_agent` /
`trace_tool` wrap your agents and tools; and model spans carry exact,
provider-reported token counts when the GenAI extras are installed. Token counts
are recorded raw — the SDK never computes cost; the platform derives it at query
time.

```python
import logging

from fastapi import FastAPI

from indratrace import init_observability, trace_agent, trace_tool

# Once, at app startup.
init_observability(product="my-app", env="prod", ingest_key="...")

app = FastAPI()  # HTTP spans are captured automatically


@trace_tool  # a child span per tool call
async def risk_score(vendor: str) -> int:
    logging.getLogger(__name__).info("scoring %s", vendor)  # ships with trace context
    return len(vendor)


@trace_agent("compliance-checker")  # a parent span per agent request
async def run(query: str) -> int:
    return await risk_score(query)
```

Both decorators work on sync and async functions. They are transparent: a tool
that raises gets its span marked `ERROR` with the exception recorded, and the
exception then propagates to your code unchanged.

Install the extras you need — FastAPI for HTTP auto-instrumentation, and
`anthropic` / `openai` for model spans with token usage:

```bash
pip install "indratrace[fastapi,anthropic,openai]"
```

## Token usage from model calls

With the `anthropic` and/or `openai` extra installed, every provider call made
after `init_observability()` produces a **model span** carrying the exact,
provider-reported token counts (`gen_ai.usage.input_tokens` /
`gen_ai.usage.output_tokens`), nested under whatever agent/tool span is active.
No wrapper, no config — just call the provider as you already do:

```python
import anthropic

from indratrace import init_observability, trace_agent, trace_tool

init_observability(product="my-app", ingest_key="...")
client = anthropic.Anthropic()


@trace_tool
def summarize(doc: str) -> str:
    msg = client.messages.create(               # model span with token counts,
        model="claude-haiku-4-5",               # a child of this tool span
        max_tokens=256,
        messages=[{"role": "user", "content": doc}],
    )
    return msg.content[0].text


@trace_agent("summarizer")
def run(doc: str) -> str:
    return summarize(doc)
```

Streaming calls are captured too — usage lands on the span from the final
streamed event.

For a provider the SDK does not auto-instrument, stamp the counts yourself from
inside a span with `record_llm_usage`:

```python
from indratrace import record_llm_usage

record_llm_usage(
    model="some-model-v2",
    input_tokens=resp.usage.input,
    output_tokens=resp.usage.output,
    system="acme-ai",
)
```

Token counts are stored raw — the SDK never computes cost; the platform derives
it at query time from a price table.

Configuration is `explicit args > env vars > defaults`. The env vars are
`INDRATRACE_ENDPOINT`, `INDRATRACE_KEY`, `INDRATRACE_PRODUCT`, and
`INDRATRACE_ENV`.

Your existing `logging` calls ship automatically once your app is at INFO — the
usual case under `basicConfig(level=INFO)`, uvicorn, or gunicorn. The SDK does
**not** change your root logger's level on its own; if your app never
configured logging (so it sits at the stdlib default of WARNING), pass
`log_level="INFO"` to opt in:

```python
init_observability(product="my-app", ingest_key="...", log_level="INFO")
```

The SDK never raises into your app: if the collector is unreachable or the
config is wrong, it logs one warning and runs un-instrumented. The decorators
hold to that too — they run your function even when `init_observability()` was
never called.

Built by [Indrasol](https://indrasol.com).
