Metadata-Version: 2.4
Name: dta-observability
Version: 0.0.21
Summary: Lightweight wrapper around OpenTelemetry core APIs
Author: dta-observability-utils
Author-email: info@totvs.ai
Requires-Python: >=3.10
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
Requires-Dist: asyncio (>=3.4.3,<4.0.0)
Requires-Dist: billiard (>=4.2.1,<5.0.0)
Requires-Dist: build (>=1.2.2,<2.0.0)
Requires-Dist: celery (>=5.5.2,<6.0.0)
Requires-Dist: docker (>=7.1.0,<8.0.0)
Requires-Dist: flask (>=2.2.3,<4.0.0)
Requires-Dist: httpx (>=0.28.1,<0.29.0)
Requires-Dist: kubernetes (>=32.0.1,<33.0.0)
Requires-Dist: opentelemetry-api (>=1.33.0,<2.0.0)
Requires-Dist: opentelemetry-exporter-gcp-logging (>=1.9.0a0,<2.0.0)
Requires-Dist: opentelemetry-exporter-gcp-monitoring (>=1.9.0a0,<2.0.0)
Requires-Dist: opentelemetry-exporter-gcp-trace (>=1.9.0,<2.0.0)
Requires-Dist: opentelemetry-exporter-otlp (>=1.33.0,<2.0.0)
Requires-Dist: opentelemetry-instrumentation (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-asyncio (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-boto (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-celery (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-django (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-flask (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-httpx (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-logging (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-psycopg2 (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-pymongo (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-requests (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-sqlalchemy (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-system-metrics (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-instrumentation-wsgi (>=0.54b0,<0.55)
Requires-Dist: opentelemetry-propagator-gcp (>=1.9.0,<2.0.0)
Requires-Dist: opentelemetry-resourcedetector-gcp (>=1.9.0a0,<2.0.0)
Requires-Dist: opentelemetry-sdk (>=1.33.0,<2.0.0)
Requires-Dist: python-json-logger (>=3.3.0,<4.0.0)
Requires-Dist: requests (>=2.31.0,<3.0.0)
Requires-Dist: setuptools (>=80.4.0,<81.0.0)
Requires-Dist: twine (>=6.1.0,<7.0.0)
Requires-Dist: types-psutil (>=7.0.0.20250401,<8.0.0.0)
Requires-Dist: types-requests (>=2.32.0.20250328,<3.0.0.0)
Description-Content-Type: text/markdown

# DTA Observability

A lightweight wrapper around OpenTelemetry for Python applications.

## Overview

DTA Observability simplifies the use of OpenTelemetry by providing a streamlined interface for instrumentation. It handles configuration of tracing, metrics, and logging with minimal setup.

## Features

- Single function initialization of all telemetry components
- Automatic instrumentation for Flask, FastAPI, Celery, and other frameworks
- Structured logging with trace context correlation
- Function decoration for easy span creation
- System and application metrics collection
- Support for OTLP, GCP Cloud, and console exporters
- Optional trace-only `none` exporter for log correlation without trace export
- Automatic resource detection
- Configuration via parameters or environment variables

## Installation

```bash
pip install dta-observability
```

Or with Poetry:

```bash
poetry add dta-observability
```

## Basic Usage

```python
import dta_observability
from dta_observability import get_logger, traced

# Initialize telemetry
dta_observability.init_telemetry(
    service_name="my-service",
    service_version="1.0.0",
    otlp_endpoint="http://otel-collector:4317",
    exporter_type="otlp",  # Options: "otlp", "console", "gcp"
)

# Get a logger
logger = get_logger("my-service")

# Use the traced decorator
@traced(name="my_function")
def my_function():
    logger.info("Doing work")
    return "result"

```

## Framework Integration

### Flask

```python
from flask import Flask
import dta_observability

app = Flask(__name__)

dta_observability.init_telemetry(
    service_name="flask-service",
    flask_app=app
)
```

#### Flask Audit Logging

Flask audit logging works with any Flask application, not just DTA-based ones, through two optional resolver callbacks passed to `init_telemetry()`. `auth_resolver` maps the current request to an `(identity, auth_type)` pair, and `context_resolver` returns a dictionary of extra fields to attach to the audit record. If neither resolver is configured, audit logging still emits complete records using the WSGI identity defaults (`REMOTE_USER`/`AUTH_TYPE`) and `request.remote_addr` for the client IP.

```python
from flask import Flask, g

import dta_observability

app = Flask(__name__)


def resolve_auth(request):
    user = getattr(g, "user", None)
    if user is None:
        return None, None
    return str(user.id), "session"


def resolve_context(request):
    return {
        "tenant": getattr(g, "tenant_id", None),
    }


dta_observability.init_telemetry(
    service_name="flask-service",
    flask_app=app,
    auth_resolver=resolve_auth,
    context_resolver=resolve_context,
)
```

#### Audit Log Format

Every audit record — Flask or FastAPI — follows the same schema (`audit_schema: 2`), emitted as structured `extra` fields on the `audit` logger:

```json
{
  "audit_schema": 2,
  "logger": "audit",
  "path": "/api/orders/42",
  "method": "GET",
  "user_id": "user-123",
  "client_ip": "203.0.113.7",
  "client_ip_source": "socket",
  "status_code": 200,
  "outcome": "success",
  "duration_ms": 14,
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "user_agent": "Mozilla/5.0",
  "auth_type": "session",
  "host": "api.example.com",
  "referer": "https://example.com/orders",
  "session_id": null,
  "context": {
    "tenant": "acme"
  }
}
```

`outcome` is derived from `status_code`: `success` (< 400, INFO), `denied` (401/403, WARNING), `client_error` (other 4xx, WARNING), `error` (5xx, ERROR), `unknown` (no status — e.g. a propagated exception, ERROR). `trace_id`, `session_id`, and `context` are `null` when unavailable; they are never omitted from the record.

### FastAPI

```python
from fastapi import FastAPI
import dta_observability

app = FastAPI()

dta_observability.init_telemetry(
    service_name="fastapi-service",
    fastapi_app=app
)
```

### Celery

```python
from celery import Celery
import dta_observability

app = Celery("tasks")

dta_observability.init_telemetry(
    service_name="worker-service",
    celery_app=app
)
```


## GCP Integration

When using the GCP exporter type:

1. For traces: Uses Cloud Trace exporter
2. For metrics: Uses Cloud Monitoring exporter with `workload.googleapis.com` prefix
3. For logs: Uses GCP log format when `log_format` is set to "gcp", sending logs to stdout in the proper format

To use GCP integration:

```python
dta_observability.init_telemetry(
    service_name="my-gcp-service",
    exporter_type="gcp",  # Uses GCP exporters for all signal types
    log_format="gcp"      # Formats logs for GCP
)
```

When `log_format` is set to "gcp", all logs will be formatted for Google Cloud Logging and sent to stdout, while metrics and traces will use their respective GCP exporters.

If you want GCP-formatted logs with trace/span correlation fields but do not want to export traces, set `traces_exporter_type="none"` and keep `enable_traces=True`:

```python
dta_observability.init_telemetry(
    service_name="my-gcp-service",
    exporter_type="gcp",
    log_format="gcp",
    traces_exporter_type="none",
    enable_traces=True,
    enable_logs=True,
    enable_metrics=False,
)
```

This keeps spans active in-process for log correlation, but does not export them to Cloud Trace or to the console.

## OTLP Integration

OTLP exporters send telemetry to an OpenTelemetry Collector:

```python
dta_observability.init_telemetry(
    service_name="my-otlp-service",
    exporter_type="otlp",
    otlp_endpoint="http://otel-collector:4317"
)
```

## Configuration

Configuration options available in `init_telemetry()`:

| Parameter | Environment Variable | Default | Description |
|-----------|---------------------|---------|-------------|
| service_name | SERVICE_NAME | unnamed-service | Name to identify the service |
| service_version | SERVICE_VERSION | 0.0.0 | Version of the service |
| service_instance_id | SERVICE_INSTANCE_ID | | Unique identifier for this service instance |
| resource_attributes | | None | Additional resource attributes (dictionary) |
| configure_auto_instrumentation | AUTO_INSTRUMENTATION_ENABLED | True | Whether to auto-instrument detected libraries |
| log_level | LOG_LEVEL | INFO | Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
| log_format | LOG_FORMAT | default | Log format type (default or gcp) |
| flask_app | | None | Flask application instance to instrument |
| fastapi_app | | None | FastAPI application instance to instrument |
| celery_app | | None | Celery application instance to instrument |
| safe_logging | SAFE_LOGGING | True | Whether to enable safe logging with complex data types |
| excluded_instrumentations | EXCLUDED_INSTRUMENTATIONS | None | Comma-separated list of instrumentations to exclude |
| otlp_endpoint | EXPORTER_OTLP_ENDPOINT | http://localhost:4317 | OTLP exporter endpoint URL |
| otlp_insecure | EXPORTER_OTLP_INSECURE | True | Whether to use insecure connection for OTLP |
| batch_export_delay_ms | BATCH_EXPORT_SCHEDULE_DELAY | 120000 | Milliseconds between batch exports |
| enable_resource_detectors | RESOURCE_DETECTORS_ENABLED | True | Whether to enable automatic resource detection |
| enable_logging_instrumentation | LOGGING_INSTRUMENTATION_ENABLED | True | Whether to enable logging instrumentation |
| propagators | OTEL_PROPAGATORS | w3c,gcp,tracecontext | Comma-separated list of context propagators |
| exporter_type | EXPORTER_TYPE | otlp | Default exporter type for all signals (otlp, console, or gcp) |
| traces_exporter_type | TRACES_EXPORTER_TYPE | otlp | Exporter type for traces (otlp, console, gcp, or none) |
| metrics_exporter_type | METRICS_EXPORTER_TYPE | otlp | Exporter type for metrics (otlp, console, or gcp) |
| logs_exporter_type | LOGS_EXPORTER_TYPE | otlp | Exporter type for logs (otlp, console, or gcp) |
| enable_traces | | True | Whether to enable trace collection |
| enable_metrics | | True | Whether to enable metrics collection |
| enable_logs | | True | Whether to enable logs collection |
| enable_system_metrics | SYSTEM_METRICS_ENABLED | True | Whether to enable system metrics collection |

Environment variables can also be prefixed with `OTEL_` or `DTA_` (e.g., `DTA_SERVICE_NAME`).


## Examples

The [examples](./examples) directory contains sample applications demonstrating usage with different frameworks.

