Metadata-Version: 2.4
Name: onflow-otel
Version: 0.1.0
Summary: Shared OpenTelemetry bootstrap and tracing helpers for Django and FastAPI services
Author: Onflow Engineering
License: MIT
Project-URL: Homepage, https://github.com/ITNHL/onflow-otel
Project-URL: Repository, https://github.com/ITNHL/onflow-otel
Project-URL: Issues, https://github.com/ITNHL/onflow-otel/issues
Keywords: django,fastapi,opentelemetry,otel,observability,tracing
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Framework :: Django
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-api<2,>=1.23
Requires-Dist: opentelemetry-sdk<2,>=1.23
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc<2,>=1.23
Requires-Dist: opentelemetry-instrumentation<1,>=0.44b0
Requires-Dist: opentelemetry-instrumentation-django<1,>=0.44b0
Requires-Dist: opentelemetry-instrumentation-psycopg2<1,>=0.44b0
Requires-Dist: opentelemetry-instrumentation-redis<1,>=0.44b0
Requires-Dist: opentelemetry-instrumentation-pymongo<1,>=0.44b0
Requires-Dist: opentelemetry-instrumentation-botocore<1,>=0.44b0
Requires-Dist: opentelemetry-instrumentation-celery<1,>=0.44b0
Requires-Dist: opentelemetry-instrumentation-requests<1,>=0.44b0
Provides-Extra: fastapi
Requires-Dist: fastapi<1,>=0.110; extra == "fastapi"
Requires-Dist: opentelemetry-instrumentation-fastapi<1,>=0.44b0; extra == "fastapi"

# onflow-otel

`onflow-otel` provides shared OpenTelemetry bootstrap helpers for Onflow services.
It supports Django, FastAPI, Celery, PostgreSQL, Redis, MongoDB, Botocore, and
outbound HTTP requests.

## Installation

Install the base package:

```bash
pip install onflow-otel
```

Install with FastAPI support:

```bash
pip install "onflow-otel[fastapi]"
```

Install from a git tag:

```bash
pip install "onflow-otel @ git+ssh://git@github.com:N-H-Logistics/onflow-otel.git@v0.1.0"
```

Install in editable mode for local development:

```bash
pip install -e .
```

## Configuration

The library ships with built-in defaults, but tracing is only enabled when:

- `OTEL_ENABLED=True`
- `OTEL_EXPORTER_OTLP_ENDPOINT` is explicitly provided

If `OTEL_ENABLED=True` but `OTEL_EXPORTER_OTLP_ENDPOINT` is missing, the library
skips OpenTelemetry initialization.

Example runtime config:

```python
OTEL_CONFIG = {
    "OTEL_ENABLED": True,
    "OTEL_SERVICE_NAME": "onflow-wms-api",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
}
```

Full example:

```python
OTEL_CONFIG = {
    "OTEL_ENABLED": True,
    "OTEL_SERVICE_NAME": "onflow-wms-api",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
    "OTEL_EXPORTER_OTLP_INSECURE": True,
    "OTEL_TRACES_SAMPLER": "parentbased_always_on",
    "OTEL_TRACES_SAMPLER_ARG": 1.0,
    "OTEL_BSP_MAX_QUEUE_SIZE": 2048,
    "OTEL_BSP_MAX_EXPORT_BATCH_SIZE": 512,
    "OTEL_BSP_SCHEDULE_DELAY": 5000,
    "OTEL_BSP_EXPORT_TIMEOUT": 30000,
    "OTEL_DEPLOYMENT_ENVIRONMENT": "development",
    "OTEL_SERVICE_INSTANCE_ID": "api-1",
    "OTEL_PROPAGATORS": "tracecontext,baggage",
    "OTEL_PYTHON_DJANGO_EXCLUDED_URLS": "^/metrics$,^/favicon.ico$",
    "OTEL_PYTHON_FASTAPI_EXCLUDED_URLS": "^/metrics$,^/health$",
    "OTEL_TRACE_CAPTURE_USER_CONTEXT": True,
    "OTEL_TRACE_CAPTURE_DB_STATS": True,
    "OTEL_TRACE_FORCE_DEBUG_CURSOR": True,
    "OTEL_TRACE_CAPTURE_DB_QUERY_DETAIL": True,
    "OTEL_TRACE_DB_QUERY_DETAIL_LIMIT": 5,
    "OTEL_TRACE_DB_QUERY_DETAIL_SQL_MAX_CHARS": 240,
    "OTEL_TRACE_DB_SLOW_QUERY_THRESHOLD_MS": 100.0,
    "OTEL_TRACE_CAPTURE_HTTP_HEADERS": True,
    "OTEL_TRACE_CAPTURE_CLIENT_IP": False,
    "OTEL_TRACE_CAPTURE_USER_PII": False,
    "OTEL_TRACE_CAPTURE_REQUEST_FIELDS": (
        "tracking_code,carrier_tracking_code,order_code,partner_id,"
        "merchant_id,shop_id,store_id,warehouse_id,request_id"
    ),
    "OTEL_TRACE_PAYLOAD_MAX_BYTES": 4096,
    "OTEL_TRACE_RESPONSE_TRACEPARENT": True,
    "OTEL_TRACE_LAYER_BREAKDOWN": True,
}
```

Configuration priority:

- Runtime config passed to `setup_opentelemetry(..., config=...)`
- Library defaults from `onflow_otel.telemetry.DEFAULT_CONFIG`

Example defaults:

```python
DEFAULT_CONFIG = {
    "OTEL_ENABLED": False,
    "OTEL_SERVICE_NAME": "onflow-wms-api",
    "OTEL_EXPORTER_OTLP_ENDPOINT": None,
    "OTEL_EXPORTER_OTLP_INSECURE": True,
}
```

Framework-specific settings:

- `OTEL_PYTHON_DJANGO_EXCLUDED_URLS` applies to Django
- `OTEL_PYTHON_FASTAPI_EXCLUDED_URLS` applies to FastAPI

### Configuration Keys

#### Required to enable tracing

- `OTEL_ENABLED`: Master switch. Must be `True` for any instrumentation to run.
- `OTEL_EXPORTER_OTLP_ENDPOINT`: Required OTLP gRPC endpoint, for example `http://localhost:4317`.

#### Service identity

- `OTEL_SERVICE_NAME`: Logical service name shown in traces.
- `OTEL_DEPLOYMENT_ENVIRONMENT`: Environment label such as `development`, `staging`, or `production`.
- `OTEL_SERVICE_INSTANCE_ID`: Optional instance identifier such as hostname, pod name, or container name.

#### Exporter behavior

- `OTEL_EXPORTER_OTLP_INSECURE`: Set to `True` for local/plaintext OTLP; set to `False` when TLS is required.
- `OTEL_PROPAGATORS`: Text map propagators to use. Default is `tracecontext,baggage`.

#### Sampling

- `OTEL_TRACES_SAMPLER`: Supported values are `parentbased_always_on`, `always_on`, `always_off`, `traceidratio`, and `parentbased_traceidratio`.
- `OTEL_TRACES_SAMPLER_ARG`: Ratio value from `0.0` to `1.0`. Only used by ratio-based samplers.

#### Batch span processor

- `OTEL_BSP_MAX_QUEUE_SIZE`: Maximum number of spans buffered before export.
- `OTEL_BSP_MAX_EXPORT_BATCH_SIZE`: Maximum number of spans exported in one batch.
- `OTEL_BSP_SCHEDULE_DELAY`: Export interval in milliseconds.
- `OTEL_BSP_EXPORT_TIMEOUT`: Export timeout in milliseconds.

#### Framework filters

- `OTEL_PYTHON_DJANGO_EXCLUDED_URLS`: Comma-separated regex list of Django paths to exclude.
- `OTEL_PYTHON_FASTAPI_EXCLUDED_URLS`: Comma-separated regex list of FastAPI paths to exclude.

#### Request and user enrichment

- `OTEL_TRACE_CAPTURE_USER_CONTEXT`: Adds user identifiers such as `enduser.id` when available.
- `OTEL_TRACE_CAPTURE_USER_PII`: Adds sensitive user fields such as email. Keep this off unless explicitly needed.
- `OTEL_TRACE_CAPTURE_HTTP_HEADERS`: Captures selected request headers such as `x-request-id`.
- `OTEL_TRACE_CAPTURE_CLIENT_IP`: Captures client IP-related fields.
- `OTEL_TRACE_CAPTURE_REQUEST_FIELDS`: Comma-separated list of business keys to extract from request payloads and query params.
- `OTEL_TRACE_PAYLOAD_MAX_BYTES`: Maximum request body size to inspect when extracting request fields.

#### Database diagnostics

- `OTEL_TRACE_CAPTURE_DB_STATS`: Records DB query count and total DB time on request spans.
- `OTEL_TRACE_FORCE_DEBUG_CURSOR`: Forces Django debug cursor collection so SQL timing can be captured.
- `OTEL_TRACE_CAPTURE_DB_QUERY_DETAIL`: Records top SQL statements as span attributes and events.
- `OTEL_TRACE_DB_QUERY_DETAIL_LIMIT`: Maximum number of top queries attached to a span.
- `OTEL_TRACE_DB_QUERY_DETAIL_SQL_MAX_CHARS`: Maximum SQL statement length stored in span data.
- `OTEL_TRACE_DB_SLOW_QUERY_THRESHOLD_MS`: Slow-query threshold in milliseconds.

#### Response and breakdown helpers

- `OTEL_TRACE_RESPONSE_TRACEPARENT`: Adds a `traceparent` header to HTTP responses when possible.
- `OTEL_TRACE_LAYER_BREAKDOWN`: Adds best-effort per-layer duration summaries such as DB, Redis, Celery, and framework time.

## Django Usage

Call `setup_opentelemetry()` during application startup:

```python
from django.conf import settings
from onflow_otel import setup_opentelemetry

setup_opentelemetry(config=getattr(settings, "OTEL_CONFIG", None))
```

Recommended locations:

- `wsgi.py`
- `asgi.py`

For Celery workers:

```python
from django.conf import settings
from onflow_otel import setup_celery_opentelemetry, setup_opentelemetry

setup_opentelemetry(config=getattr(settings, "OTEL_CONFIG", None))
setup_celery_opentelemetry(config=getattr(settings, "OTEL_CONFIG", None))
```

## FastAPI Usage

Use the FastAPI-specific helper:

```python
from fastapi import FastAPI
from onflow_otel import setup_fastapi_opentelemetry

app = FastAPI()

setup_fastapi_opentelemetry(
    app,
    config={
        "OTEL_ENABLED": True,
        "OTEL_SERVICE_NAME": "onflow-fastapi-api",
        "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
    },
)
```

You can also use the generic API:

```python
from fastapi import FastAPI
from onflow_otel import setup_opentelemetry

app = FastAPI()

setup_opentelemetry(
    framework="fastapi",
    app=app,
    config={
        "OTEL_ENABLED": True,
        "OTEL_SERVICE_NAME": "onflow-fastapi-api",
        "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
    },
)
```

## Public Helpers

The package also exposes helper utilities for manual instrumentation:

- `traced_block`
- `add_span_event`
- `record_span_exception`
- `record_span_failure`
- `set_span_attributes`
- `set_baggage_attributes`
- `get_current_trace_context`

## Release

GitHub Actions is configured to:

- build and validate the package on every pull request
- build on pushes to `main`
- publish to PyPI when a tag matching `v*` is pushed

One-time setup:

1. Create a PyPI API token with permission to publish this package.
2. Add the token to GitHub repository secrets as `PYPI_API_TOKEN`.
3. Keep the workflow file at `.github/workflows/publish.yml`.

Release flow:

```bash
git tag v0.2.1
git push origin v0.2.1
```

The pushed tag version must match `project.version` in `pyproject.toml`.
