Metadata-Version: 2.4
Name: genai-instana
Version: 0.1.0a2
Summary: Zero-touch GenAI tracing wrapper for Instana (OpenTelemetry + OpenLLMetry, coexistence-first)
Author-email: Kartik Hiremath <kartik.hiremath001@ibm.com>, Madhu Tadiparthi <madhu.tadiparthi@ibm.com>
License-Expression: MIT
Project-URL: Homepage, https://www.ibm.com/products/instana
Project-URL: Documentation, https://www.ibm.com/docs/en/instana-observability?topic=capabilities-generative-ai-observability
Keywords: opentelemetry,genai,llm,tracing,observability,instana,traceloop,monitoring
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
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 :: Implementation :: CPython
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: opentelemetry-sdk>=1.43.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.43.0
Requires-Dist: opentelemetry-instrumentation-requests>=0.64b0
Requires-Dist: opentelemetry-instrumentation-httpx>=0.64b0
Requires-Dist: httpx>=0.27
Requires-Dist: opentelemetry-instrumentation-urllib3>=0.64b0
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.64b0
Requires-Dist: opentelemetry-instrumentation-asgi>=0.64b0
Requires-Dist: opentelemetry-instrumentation-flask>=0.64b0
Requires-Dist: opentelemetry-instrumentation-wsgi>=0.64b0
Requires-Dist: opentelemetry-semantic-conventions-ai>=0.5.1
Requires-Dist: traceloop-sdk>=0.62.1
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: psutil>=7.2.2
Requires-Dist: autowrapt>=1.0
Provides-Extra: fastapi
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.64b0; extra == "fastapi"
Requires-Dist: opentelemetry-instrumentation-asgi>=0.64b0; extra == "fastapi"
Provides-Extra: flask
Requires-Dist: opentelemetry-instrumentation-flask>=0.64b0; extra == "flask"
Requires-Dist: opentelemetry-instrumentation-wsgi>=0.64b0; extra == "flask"
Provides-Extra: test
Requires-Dist: pytest>=7.4; extra == "test"
Requires-Dist: pytest-asyncio>=0.23; extra == "test"
Requires-Dist: langchain-core>=0.3; extra == "test"
Dynamic: license-file

# genai-instana

`genai-instana` is a Python CLI wrapper built by IBM Instana that adds
OpenTelemetry-compatible GenAI traces and metrics to Python applications using
common LLM SDKs and frameworks — with zero changes to application code.

It can initialize telemetry for a completely uninstrumented application, or
coexist safely with an application that already uses Traceloop/OpenLLMetry or
raw OpenTelemetry.

## Status

**Early alpha, published for evaluation.** Span names, attribute keys and
metric names can change between releases — pin an exact version if you build
dashboards or alerts on them. Several capabilities are unsupported or
unvalidated; read [Known limitations](#known-limitations) before relying on
this anywhere that matters.

## Installation

```bash
pip install genai-instana
```

## Supported SDKs and frameworks

| Category | Covered |
|---|---|
| LLM providers | OpenAI and OpenAI-compatible gateways, LiteLLM, WatsonX, Groq, OpenRouter |
| Frameworks | LangChain, LangGraph, CrewAI |
| Web servers | FastAPI (uvicorn), Flask |

## Required configuration

The wrapper needs to know **where to export**.

### Option 1 — Traceloop aliases

```bash
export TRACELOOP_BASE_URL=https://<otlp-http-host>:443
export TRACELOOP_HEADERS="x-instana-key=<key>"
```

### Option 2 — Standard OTel variables

**Local Instana agent:**
```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
```

**Instana Backend:**
```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=https://<otlp-http-host>:443
export OTEL_EXPORTER_OTLP_HEADERS="x-instana-key=<key>,x-instana-host=<host>"
```

Either set works; the wrapper reads whichever is present.

Optionally set a service name (shown in Instana):
```bash
export OTEL_SERVICE_NAME=my-genai-service   # optional, defaults to auto_genai_service
```

## Content capture

Prompt, completion and tool text is **captured and exported by default**. It
reaches your Instana tenant alongside the model, token and latency data, and is
readable there by anyone who can read traces.

```bash
export GENAI_INSTANA_CAPTURE_CONTENT=false   # topology and metrics only, no text
```

Switching it off removes prompt, completion and tool text while preserving
topology, model, provider, tokens, latency, status and errors.

A span *name* is not content, and this setting does not reach it. Whatever a
framework puts in a span name is exported either way — CrewAI, for one, names
its task span with the task description in full.

## Quick start

Prefix your existing launch command with `genai-instana` — that is the only
change needed. No code modifications, no decorators, no `Traceloop.init()`
required.

**Standalone script** (a one-off Python script that calls an LLM directly):
```bash
genai-instana python app.py
```

**FastAPI app** (ASGI — use uvicorn):
```bash
genai-instana uvicorn main:app --host 0.0.0.0 --port 8000
```

**Flask app** — launch it as a script; the wrapper detects Flask and serves it:
```bash
genai-instana python app.py
```

## Expected trace shape

For one HTTP request containing one LLM call:

```text
POST /invoke                 SERVER  (HTTP entry)
└── gen_ai.chat              CLIENT  (LLM call)
```

Framework workflows and tasks appear between those spans when present. There
is one LLM span per real provider request — no orphan traces, no duplicate
`POST` spans beside the LLM span.

## Known limitations

This is an early alpha. If something is not listed as supported above, assume
it has not been verified.

**Not supported**

- **Streaming responses.** The LLM span is produced, but a streaming HTTP
  response also emits one span per response chunk, which overruns the trace and
  leaves the GenAI task view empty. The cause is upstream OpenTelemetry ASGI
  instrumentation. Use non-streaming calls.
- **IBM WatsonX `ModelInference.chat()` and `achat()`** produce no LLM span.
  This release covers `generate_text` and `generate_text_stream`.

**Not validated — use with caution**

- **Gunicorn and other multi-worker servers.** The launch path exists, but no
  end-to-end telemetry has been confirmed. Not recommended for this release.
- **Concurrent request load, long-running processes, and distributed tracing
  across services** have not been tested.
- **Coexistence with the Instana Python sensor** is preview: one recorded live
  run did not produce a GenAI span for a native Groq call.
- **Google ADK** spans are marked, but LLM calls made through it are not
  recognised as LLM calls, so they do not populate GenAI views.

**Known behaviours that may surprise you**

- **Flask routing is decided partly by file path.** A script whose path
  contains `flask` — including a parent directory such as `flask-demo/` — is
  routed to the in-process Flask launcher, which overrides the port and command
  line the script would otherwise use. Run Flask applications from their own
  directory, and avoid `flask` in the path of scripts that are not Flask
  applications.
- **Cost may show as empty** even when token counts are correct. Cost is
  computed by the backend from the model identifier and a pricing catalogue; a
  model whose reported identifier does not match a configured entry produces
  tokens without cost.
- **CrewAI metric totals read 2x.** CrewAI's instrumentation and the provider
  SDK's both record token usage for the same call, so request counts, token
  totals and cost derived from metrics are doubled. The traces are correct —
  one LLM span per call, carrying the real counts — so take figures that must
  be accurate from the trace view. Measured on crewai 1.x: 10 LLM spans
  reported as 20 requests.
- **An application that sets up its own tracing keeps its own trace root.** If
  that root is an internal-kind span, Instana excludes it from default call
  analysis: GenAI views populate while the Application Monitoring service page
  stays empty.

Where the wrapper cannot do something, it aims to say so at startup rather than
fail silently — check the diagnostic line it prints.

## Documentation

Product documentation is published at
[IBM Instana — Generative AI observability](https://www.ibm.com/docs/en/instana-observability?topic=capabilities-generative-ai-observability).

## License

MIT — see the `LICENSE` file included with this package.

Copyright (c) 2026 IBM Corp.
Copyright (c) 2026 Instana, Inc. https://www.instana.com/
