Metadata-Version: 2.4
Name: tracelit-python
Version: 0.1.1
Summary: Official Python SDK for Tracelit with OpenTelemetry.
Author: Tracelit
License: MIT
Project-URL: Homepage, https://tracelit.io
Project-URL: Repository, https://github.com/Tracelit-AI/tracelit-python
Keywords: tracelit,opentelemetry,tracing,metrics,logs,apm
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: opentelemetry-api>=1.27.0
Requires-Dist: opentelemetry-sdk>=1.27.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27.0
Requires-Dist: opentelemetry-semantic-conventions>=0.48b0
Requires-Dist: opentelemetry-instrumentation>=0.48b0
Provides-Extra: web
Requires-Dist: opentelemetry-instrumentation-asgi>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-wsgi>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-django>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-flask>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-starlette>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-tornado>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-aiohttp-server>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-pyramid>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-falcon>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-bottle>=0.48b0; extra == "web"
Requires-Dist: opentelemetry-instrumentation-cherrypy>=0.48b0; extra == "web"
Provides-Extra: db
Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-psycopg2>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-psycopg>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-asyncpg>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-aiopg>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-pymysql>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-mysql>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-pymssql>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-pymongo>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-redis>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-sqlite3>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-elasticsearch>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-cassandra>=0.48b0; extra == "db"
Requires-Dist: opentelemetry-instrumentation-tortoiseorm>=0.48b0; extra == "db"
Provides-Extra: workers
Requires-Dist: opentelemetry-instrumentation-celery>=0.48b0; extra == "workers"
Requires-Dist: opentelemetry-instrumentation-remoulade>=0.48b0; extra == "workers"
Provides-Extra: http
Requires-Dist: opentelemetry-instrumentation-requests>=0.48b0; extra == "http"
Requires-Dist: opentelemetry-instrumentation-urllib3>=0.48b0; extra == "http"
Requires-Dist: opentelemetry-instrumentation-httpx>=0.48b0; extra == "http"
Requires-Dist: opentelemetry-instrumentation-aiohttp-client>=0.48b0; extra == "http"
Requires-Dist: opentelemetry-instrumentation-urllib>=0.48b0; extra == "http"
Provides-Extra: messaging
Requires-Dist: opentelemetry-instrumentation-kafka-python>=0.48b0; extra == "messaging"
Requires-Dist: opentelemetry-instrumentation-confluent-kafka>=0.48b0; extra == "messaging"
Requires-Dist: opentelemetry-instrumentation-aiokafka>=0.48b0; extra == "messaging"
Requires-Dist: opentelemetry-instrumentation-pika>=0.48b0; extra == "messaging"
Requires-Dist: opentelemetry-instrumentation-aio-pika>=0.48b0; extra == "messaging"
Provides-Extra: cloud
Requires-Dist: opentelemetry-instrumentation-botocore>=0.48b0; extra == "cloud"
Requires-Dist: opentelemetry-instrumentation-boto3sqs>=0.48b0; extra == "cloud"
Requires-Dist: opentelemetry-instrumentation-google-genai>=0.48b0; extra == "cloud"
Provides-Extra: grpc
Requires-Dist: opentelemetry-instrumentation-grpc>=0.48b0; extra == "grpc"
Provides-Extra: graphql
Requires-Dist: opentelemetry-instrumentation-graphql>=0.48b0; extra == "graphql"
Provides-Extra: all
Requires-Dist: opentelemetry-contrib-instrumentations>=0.48b0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: ruff>=0.6.0; extra == "dev"
Requires-Dist: respx>=0.21.0; extra == "dev"
Requires-Dist: httpx>=0.27.0; extra == "dev"
Dynamic: license-file

# Tracelit Python SDK

Drop-in OpenTelemetry SDK for Python that exports traces, metrics, and logs to Tracelit via OTLP/HTTP.

## Install

```bash
pip install tracelit
```

Install OpenTelemetry instrumentation packages for **your** stack (see each framework section below). Tracelit only instruments libraries whose instrumentation package is installed — missing packages are skipped silently.

```bash
pip install opentelemetry-instrumentation-flask      # Flask apps
pip install opentelemetry-instrumentation-django     # Django apps
pip install opentelemetry-instrumentation-fastapi    # FastAPI apps
pip install opentelemetry-instrumentation-celery     # Celery workers
pip install opentelemetry-instrumentation-redis        # Redis
pip install opentelemetry-instrumentation-requests   # requests HTTP client
```

## Which setup do I use?

| App type | How to initialize Tracelit |
|---|---|
| **Django** | Add `tracelit.integrations.django.TracelitConfig` to `INSTALLED_APPS`. Do **not** call `auto_start()` in `settings.py`. |
| **Flask** | Call `tracelit.auto_start()` in `app.py` before routes run. Expose a module-level `app` object. |
| **FastAPI** | Call `tracelit.auto_start()` in `main.py` before the app serves traffic. |
| **Celery worker** | Call `install_celery_hook()` in `celery.py`. |
| **Script / CLI / batch job** | Call `tracelit.auto_start()` at process startup. |

> There is **no** `tracelit.init()` API.

---

## Django

**1. Add to `settings.py`:**

```python
INSTALLED_APPS = [
    "tracelit.integrations.django.TracelitConfig",  # full path required
    "django.contrib.admin",
    # ...
]
```

**2. Set environment variables** (`.env`, deployment config, etc.):

```bash
TRACELIT_API_KEY=your-api-key
TRACELIT_SERVICE_NAME=payments-api
TRACELIT_ENVIRONMENT=production
TRACELIT_ENDPOINT=https://ingest.tracelit.app
```

**3. Install Django instrumentation:**

```bash
pip install opentelemetry-instrumentation-django
```

**4. Restart Django** (`runserver`, gunicorn, uvicorn, etc.).

Tracelit starts automatically in `AppConfig.ready()` after Django is configured.

### python-decouple / django-environ

Bridge secrets into `os.environ` **before** `INSTALLED_APPS`:

```python
import os
from decouple import config

os.environ.setdefault("TRACELIT_API_KEY", config("TRACELIT_API_KEY"))
os.environ.setdefault("TRACELIT_SERVICE_NAME", config("TRACELIT_SERVICE_NAME", default="backend"))
os.environ.setdefault("TRACELIT_ENVIRONMENT", config("TRACELIT_ENVIRONMENT", default="production"))
```

> **Do not** call `tracelit.auto_start()` at the top of `settings.py`.

### Celery (Django projects with background workers)

In `celery.py`:

```python
from tracelit.integrations.celery import install_celery_hook

install_celery_hook()
```

```bash
pip install opentelemetry-instrumentation-celery
```

---

## Flask

**1. `app.py` — complete working example:**

```python
import os

import tracelit

tracelit.auto_start(
    api_key=os.environ["TRACELIT_API_KEY"],
    service_name="my-flask-app",
    environment=os.getenv("FLASK_ENV", "production"),
)

from flask import Flask
from tracelit.integrations.wsgi import TracelitWSGIMiddleware

app = Flask(__name__)
app.wsgi_app = TracelitWSGIMiddleware(app.wsgi_app)


@app.get("/")
def home():
    return "ok"
```

**2. Install Flask instrumentation:**

```bash
pip install opentelemetry-instrumentation-flask opentelemetry-instrumentation-wsgi
```

**3. Run:**

```bash
export TRACELIT_API_KEY=your-api-key
FLASK_APP=app.py flask run
```

`FLASK_APP=app.py` requires a module-level variable named `app`. If your factory is named differently, use `FLASK_APP=app:create_app` instead.

`TracelitWSGIMiddleware` adds HTTP request metrics. Flask route tracing comes from `opentelemetry-instrumentation-flask`.

---

## FastAPI

**1. `main.py` — complete working example:**

```python
import os

import tracelit

tracelit.auto_start(
    api_key=os.environ["TRACELIT_API_KEY"],
    service_name="my-api",
    environment=os.getenv("ENV", "production"),
)

from fastapi import FastAPI
from tracelit.integrations.asgi import TracelitASGIMiddleware

app = FastAPI()
app = TracelitASGIMiddleware(app)


@app.get("/")
def home():
    return {"ok": True}
```

**2. Install FastAPI instrumentation:**

```bash
pip install opentelemetry-instrumentation-fastapi opentelemetry-instrumentation-asgi
```

**3. Run with uvicorn:**

```bash
export TRACELIT_API_KEY=your-api-key
uvicorn main:app
```

---

## Scripts and batch jobs (no web framework)

Use `tracelit.auto_start()` at the top of your entry point. This is for CLIs, cron jobs, and one-off scripts — **not** for Django (use `TracelitConfig` instead).

```python
import os
import tracelit

tracelit.auto_start(
    api_key=os.environ["TRACELIT_API_KEY"],
    service_name="nightly-report",
    environment=os.getenv("ENV", "production"),
)

with tracelit.tracer().start_as_current_span("generate-report"):
    # your logic here
    pass
```

Or rely entirely on environment variables:

```python
import tracelit

tracelit.auto_start()
```

---

## Manual spans and metrics

```python
import tracelit

with tracelit.tracer().start_as_current_span("process-order"):
    tracelit.metrics.counter("orders.processed").add(1)
```

---

## Configuration

| Option | Env var | Default |
|---|---|---|
| api_key | `TRACELIT_API_KEY` | required |
| service_name | `TRACELIT_SERVICE_NAME` | `unknown-service` |
| environment | `TRACELIT_ENVIRONMENT` | `production` |
| endpoint | `TRACELIT_ENDPOINT` | `https://ingest.tracelit.app` |
| sample_rate | `TRACELIT_SAMPLE_RATE` | `1.0` |
| enabled | `TRACELIT_ENABLED` | `true` |

Set `TRACELIT_ENABLED=false` in tests to disable telemetry with no code changes.

## Behavior guarantees

- Non-blocking span export with async error-span queue
- Never raises setup or exporter failures into customer code
- Graceful shutdown flush at process exit
- Error spans are always exported, even when sampling is below `1.0`
- Missing instrumentation packages are skipped silently (no startup warning spam)
