Metadata-Version: 2.5
Name: sophonz-opentelemetry
Version: 0.1.0
Summary: Sophonz OpenTelemetry distro for Python
Project-URL: Homepage, https://sophonz.ai
Project-URL: Documentation, https://sophonz.ai/docs/python/installation
Author: Sophonz
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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.9
Requires-Dist: opentelemetry-api<2.0.0,>=1.30.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http<2.0.0,>=1.30.0
Requires-Dist: opentelemetry-instrumentation<1.0.0,>=0.51b0
Requires-Dist: opentelemetry-sdk<2.0.0,>=1.30.0
Provides-Extra: django
Requires-Dist: opentelemetry-instrumentation-django<1.0.0,>=0.51b0; extra == 'django'
Provides-Extra: fastapi
Requires-Dist: opentelemetry-instrumentation-fastapi<1.0.0,>=0.51b0; extra == 'fastapi'
Provides-Extra: flask
Requires-Dist: opentelemetry-instrumentation-flask<1.0.0,>=0.51b0; extra == 'flask'
Provides-Extra: grpc
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc<2.0.0,>=1.30.0; extra == 'grpc'
Provides-Extra: httpx
Requires-Dist: opentelemetry-instrumentation-httpx<1.0.0,>=0.51b0; extra == 'httpx'
Provides-Extra: logging
Requires-Dist: opentelemetry-instrumentation-logging<1.0.0,>=0.51b0; extra == 'logging'
Provides-Extra: psycopg
Requires-Dist: opentelemetry-instrumentation-psycopg<1.0.0,>=0.51b0; extra == 'psycopg'
Provides-Extra: psycopg2
Requires-Dist: opentelemetry-instrumentation-psycopg2<1.0.0,>=0.51b0; extra == 'psycopg2'
Provides-Extra: requests
Requires-Dist: opentelemetry-instrumentation-requests<1.0.0,>=0.51b0; extra == 'requests'
Provides-Extra: sqlalchemy
Requires-Dist: opentelemetry-instrumentation-sqlalchemy<1.0.0,>=0.51b0; extra == 'sqlalchemy'
Description-Content-Type: text/markdown

# Sophonz OpenTelemetry Distro for Python

An OpenTelemetry distro that sends traces, metrics and logs from Python services to Sophonz over OTLP. Its API follows the Sophonz Node SDK (`@sophonz/node-sdk`).

Forked from hyperdx-opentelemetry-python (itself a fork of honeycomb-opentelemetry-python), Apache-2.0. See the NOTICE file included in this distribution.

## Requirements

- Python 3.9 or later
- A Sophonz API key (`sk_...`) from the Sophonz console

## Install

```bash
pip install "sophonz-opentelemetry[flask,psycopg]"
```

Extras install the matching OpenTelemetry instrumentation: `flask`, `fastapi`, `django`, `psycopg`, `psycopg2`, `sqlalchemy`, `requests`, `httpx`, `logging`. The `grpc` extra adds the gRPC exporters for `OTEL_EXPORTER_OTLP_PROTOCOL=grpc`. `opentelemetry-bootstrap -a install` installs instrumentations for every library it detects instead.

## Usage

In code, before the web framework and database driver are imported:

```python
import os

from sophonz.opentelemetry import init

init(
    service="checkout-api",
    api_key=os.getenv("SOPHONZ_API_KEY"),
    instrumentations={"psycopg": {"enable_commenter": True}},
)
```

`init()` loads every installed instrumentation and turns on logging and exception capture. `init_sdk()` takes the same arguments with only the per-option defaults. Without an API key (and no `OTEL_EXPORTER_OTLP_HEADERS`) both log a warning and skip initialization.

Without code changes:

```bash
export SOPHONZ_API_KEY=sk_...
export OTEL_SERVICE_NAME=checkout-api
opentelemetry-instrument gunicorn app:app
```

### Framework helpers

```python
# Flask
from sophonz.opentelemetry.flask import setup_flask_error_handler, sophonz_flask_middleware

sophonz_flask_middleware(app)
setup_flask_error_handler(app)

# FastAPI / Starlette
from sophonz.opentelemetry.fastapi import setup_fastapi_error_handler, sophonz_fastapi_middleware

sophonz_fastapi_middleware(app)
setup_fastapi_error_handler(app)

# Django: settings.MIDDLEWARE
"sophonz.opentelemetry.django.SophonzMiddleware"
```

They add baggage (`baggage.<key>`), `http.client.ip`, `http.user_agent` and your own `attributes` to every span of a request, and record exceptions escaping a route once.

## What it configures

- Tracer, meter and logger providers with OTLP/HTTP exporters to `https://in.sophonz.ai`, set as the globals, sharing one resource.
- The API key as the `authorization` header on every export and as the `service.key` resource attribute; `OTEL_RESOURCE_ATTRIBUTES` still applies.
- Parent-based sampling (`OTEL_TRACES_SAMPLER`, default `parentbased_always_on`) and the `tracecontext,baggage` propagators, so a browser trace is continued.
- Baggage copied onto every span as `baggage.<key>`, and `session.id` as `session.id`.
- `set_trace_attributes()`: attributes applied to every span of the current request.
- An error log record for every span that ends with an ERROR status.
- An OTLP handler on the root logger, without breaking the application's own `basicConfig`/`dictConfig`.
- `SIGTERM`/`SIGINT` handlers that flush and then run the previous handler; `shutdown()` and `force_flush()`.
- Exclusion of its own export URLs from HTTP client instrumentation.

## API

| Function | Purpose |
| --- | --- |
| `init(**options) -> bool` | Start with Sophonz defaults |
| `init_sdk(**options) -> bool` | Start with per-option defaults only |
| `shutdown(timeout_millis=5000)` | Flush and stop every provider |
| `force_flush(timeout_millis=5000) -> bool` | Export buffered telemetry |
| `set_trace_attributes(attributes)` | Attributes on every span of the request |
| `record_exception(exc, attributes=None, span=None)` | Exception event and ERROR status |
| `enable_debug_payload_exporters()` | Print exported spans and logs |
| `is_initialized() -> bool` | Whether the SDK is running |

## Configuration

Arguments win over environment variables.

| Argument | Environment variable | Default |
| --- | --- | --- |
| `service` | `OTEL_SERVICE_NAME` | `unknown_service:python` |
| `api_key` | `SOPHONZ_API_KEY` | none |
| `service_version` | `OTEL_SERVICE_VERSION` | none |
| `service_namespace` | `SOPHONZ_SERVICE_NAMESPACE` | none |
| `deployment_environment` | `SOPHONZ_DEPLOYMENT_ENVIRONMENT` | none |
| `console_capture` | `SOPHONZ_PYTHON_CONSOLE_CAPTURE` | `true` |
| `experimental_exception_capture` | `SOPHONZ_PYTHON_EXPERIMENTAL_EXCEPTION_CAPTURE` | `false` (`init()`: `true`) |
| `error_log_capture` | `SOPHONZ_PYTHON_ERROR_LOG_CAPTURE` | `true` |
| `advanced_network_capture` | `SOPHONZ_PYTHON_ADVANCED_NETWORK_CAPTURE` | `false` |
| `beta_mode` | `SOPHONZ_PYTHON_BETA_MODE` | `false` (reserved) |
| `stop_on_termination_signals` | `SOPHONZ_PYTHON_STOP_ON_TERMINATION_SIGNALS` | `true` |
| `detect_resources` | `SOPHONZ_PYTHON_DETECT_RESOURCES` | `true` |
| `disable_startup_logs` | `SOPHONZ_STARTUP_LOGS=false` | `false` |
| `disable_tracing`, `disable_metrics`, `disable_logs` | `OTEL_{TRACES,METRICS,LOGS}_EXPORTER=none` | enabled |
| `instrumentations` | `SOPHONZ_PYTHON_INSTRUMENTATIONS` (JSON) | `{}` |
| none | `SOPHONZ_PYTHON_SQLCOMMENTER` | `false` (psycopg, psycopg2) |
| `additional_instrumentations` | none | `[]` |
| `promote_baggage_keys` | none | `["session.id"]` |
| `sampler` | `OTEL_TRACES_SAMPLER`, `OTEL_TRACES_SAMPLER_ARG` | `parentbased_always_on` |
| `endpoint` | `OTEL_EXPORTER_OTLP_ENDPOINT` | `https://in.sophonz.ai` |
| `traces_endpoint`, `metrics_endpoint`, `logs_endpoint` | `OTEL_EXPORTER_OTLP_{TRACES,METRICS,LOGS}_ENDPOINT` | base + `/v1/<signal>` |
| `exporter_protocol` | `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf` |
| `endpoint_insecure` | `OTEL_EXPORTER_OTLP_INSECURE` | `false` (gRPC only) |
| `debug` | `SOPHONZ_DEBUG` | `false` (SDK loggers at DEBUG) |
| `debug_payload` | `SOPHONZ_DEBUG_PAYLOAD` | `false` (print exported telemetry) |
| `log_level` | `OTEL_LOG_LEVEL` | unchanged |

`OTEL_EXPORTER_OTLP_HEADERS` is merged into export headers; the API key replaces any `authorization` in it.

## Development

```bash
uv sync
uv run pytest
uv run ruff check src tests
uv run pylint src
uv build
```

## License

Apache 2.0. See the LICENSE file included in this distribution.
