Metadata-Version: 2.4
Name: fiddler-otel
Version: 1.2.0
Summary: Core OpenTelemetry instrumentation library for Fiddler GenAI observability
Author-email: Fiddler AI <support@fiddler.ai>
License-Expression: Apache-2.0
Project-URL: Homepage, https://fiddler.ai
Project-URL: Documentation, https://docs.fiddler.ai
Project-URL: Repository, https://github.com/fiddler-labs/fiddler-sdk
Project-URL: Issues, https://github.com/fiddler-labs/fiddler-sdk/issues
Keywords: fiddler,ai,genai,llm,monitoring,observability,instrumentation,opentelemetry
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: Software Development :: Quality Assurance
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: Programming Language :: Python :: 3.14
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-api>=1.28.0
Requires-Dist: opentelemetry-sdk>=1.28.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.28.0
Requires-Dist: pydantic>=2.0
Requires-Dist: httpx<1.0,>=0.24.0

# fiddler-otel

Core OpenTelemetry instrumentation library for **Fiddler GenAI observability**. This is the foundation package used by all Fiddler framework integrations (`fiddler-langgraph`, `fiddler-langchain`).

## Installation

```bash
pip install fiddler-otel
```

## Quick Start

### Using the `@trace` decorator

The simplest way to instrument any Python function — synchronous or async:

```python
from fiddler_otel import FiddlerClient, trace

client = FiddlerClient(
    application_id="YOUR_APPLICATION_ID",
    api_key="YOUR_API_KEY",
    url="https://your-instance.fiddler.ai",
)

@trace(span_type="generation", name="my_llm_call")
def call_llm(prompt: str) -> str:
    # your LLM call here
    return response

@trace(span_type="chain")
async def run_pipeline(user_input: str) -> str:
    result = call_llm(user_input)
    return result
```

### Using span wrappers manually

For fine-grained control over span attributes:

```python
from fiddler_otel import FiddlerClient, FiddlerGeneration, FiddlerChain, FiddlerTool

client = FiddlerClient(
    application_id="YOUR_APPLICATION_ID",
    api_key="YOUR_API_KEY",
    url="https://your-instance.fiddler.ai",
)

with client.start_span("my_agent", span_type="chain") as chain_span:
    gen = FiddlerGeneration(client.start_span("llm_call"))
    with gen as span:
        span.set_input("What is the capital of France?")
        response = call_llm("What is the capital of France?")
        span.set_output(response)
        span.set_usage(input_tokens=10, output_tokens=5, total_tokens=15)
```

### Multi-turn Conversations

Link multiple agent invocations into a single conversation:

```python
from fiddler_otel import set_conversation_id
import uuid

set_conversation_id(str(uuid.uuid4()))

# All spans created after this call carry the same conversation_id
result = my_agent(user_message)
```

### Local JSONL Capture

Write spans to a local file **in addition to** sending them directly to Fiddler. Useful for local debugging or auditing.

> **Note:** `jsonl_capture_enabled=True` is additive — spans are still exported to Fiddler. To stop direct export, set `otlp_enabled=False` (see [Offline / S3 Routing Mode](#offline--s3-routing-mode) below).

```python
client = FiddlerClient(
    application_id="...",
    api_key="...",
    url="...",
    jsonl_capture_enabled=True,
    jsonl_file_path="trace_data.jsonl",
)
```

Or via environment variables:

```bash
FIDDLER_JSONL_ENABLED=true \
FIDDLER_JSONL_FILE=trace_data.jsonl \
python my_agent.py
```

### Console Tracing (Development)

Print all spans to stdout during development.

> **Note:** `console_tracer=True` is additive — spans are still exported to Fiddler. It does not suppress direct OTLP export.

```python
client = FiddlerClient(
    application_id="...",
    api_key="...",
    url="...",
    console_tracer=True,
)
```

### Offline / S3 Routing Mode

Use `otlp_enabled=False` to **stop all direct OTLP export** to Fiddler. Combined with `otlp_json_capture_enabled=True`, spans are written to local `.json` files in standard OTLP JSON format (`ExportTraceServiceRequest` envelope) that can be ingested by the Fiddler S3 connector.

When `otlp_enabled=False`, `api_key` and `url` are not required.

> **Why is `application_id` still required?**
> Even when not connecting to Fiddler directly, `application_id` is embedded in every trace file as a resource attribute. The Fiddler S3 connector reads this attribute to route ingested traces to the correct application in your Fiddler account. Obtain the UUID4 from your Fiddler application dashboard.

```python
client = FiddlerClient(
    application_id="YOUR_APPLICATION_ID",  # from your Fiddler dashboard — embedded in trace files
    otlp_enabled=False,                    # no spans sent directly to Fiddler
    otlp_json_capture_enabled=True,        # write OTLP JSON files locally
    otlp_json_output_dir="./trace_output",  # directory for output files (created if absent)
)
```

Each export batch produces one file named `fiddler_trace_<timestamp>_<hex>.json` inside `otlp_json_output_dir`. The directory is created automatically if it does not exist. These files can be uploaded to object storage and ingested by the Fiddler S3 connector without any reformatting.

## Public API

| Symbol | Description |
|---|---|
| `FiddlerClient` | Main client — configures the tracer and exports spans to Fiddler |
| `FiddlerSpan` | Base span wrapper with `set_input`, `set_output`, `set_attribute` |
| `FiddlerGeneration` | LLM span wrapper — adds `set_usage`, `set_messages`, `set_context` |
| `FiddlerChain` | Chain/pipeline span wrapper |
| `FiddlerTool` | Tool call span wrapper |
| `trace` | Decorator for automatic span creation around any function |
| `get_current_span` | Get the active Fiddler span inside a traced function |
| `set_conversation_id` | Link multiple invocations into one conversation |
| `get_client` | Return the global singleton `FiddlerClient` |

## Context Isolation

`fiddler-otel` uses its own **isolated OpenTelemetry context** that does not interfere with any existing global tracer in your application. If you already use OpenTelemetry for infrastructure tracing, Fiddler spans will not appear in your infrastructure traces and vice versa.

## Framework Integrations

| Package | Framework | Install |
|---|---|---|
| `fiddler-langgraph` | LangGraph + LangChain v0.x | `pip install fiddler-langgraph` |
| `fiddler-langchain` | LangChain V1 (`create_agent`) | `pip install fiddler-langchain` |

Both integration packages depend on `fiddler-otel` and re-export its core symbols, so you typically only need to install the integration package for your framework.

## Requirements

- Python 3.10+
- `opentelemetry-api >= 1.27.0`
- `opentelemetry-sdk >= 1.27.0`
- `opentelemetry-exporter-otlp-proto-http >= 1.27.0`
- `pydantic >= 2.0`
