autonomize-sdk-telemetry-beta 0.0.47
Telemetry package for Autonomize SDK
Requires Python: <4.0,>=3.12

# Autonomize Telemetry SDK

A comprehensive OpenTelemetry-based SDK for application monitoring and observability in Python applications. This SDK provides unified APIs for metrics, logging, and tracing, making it easier to instrument your applications with observability features.

## Features

- **Unified Telemetry**: Seamlessly integrate metrics, logs, and traces
- **OpenTelemetry Integration**: Built on top of OpenTelemetry's robust observability standards
- **Auto-instrumentation**: Support for FastAPI instrumentation
- **Simple API**: Easy-to-use interface for all telemetry operations
- **Configurable**: Flexible configuration options for different environments
- **Service-Based Architecture**: Clean separation of metrics, logging, and tracing functionalities

## Prerequisites

- Python 3.8 or higher
- A running OpenTelemetry collector (default endpoint: http://localhost:4317)

## Installation

To install the package locally:

```bash
poetry add autonomize-sdk-telemetry-beta
```

## Quick Start

Here's a simple example to get you started:

```python
from autonomize_sdk import Telemetry, TelemetryConfig, MetricOptions

# Initialize with configuration
config = TelemetryConfig(
    service_name="my-service",
    environment="production",
    otlp_endpoint="http://localhost:4317",
    version="1.0.0",
    metric_interval_ms=5000,
    log_level="INFO"
)

# Start telemetry services
telemetry = Telemetry(config)
await telemetry.start()

try:
    # Create and use metrics
    request_counter = telemetry.metrics.create_counter(
        MetricOptions(
            name="http.requests",
            description="Number of HTTP requests"
        )
    )
    request_counter.add(1)

    # Log information
    telemetry.logging.info("Application started", {"version": "1.0.0"})

    # Create traced operation
    async def my_operation():
        return "result"

    result = await telemetry.tracing.create_span(
        "my-operation",
        my_operation,
        attributes={"custom.attribute": "value"}
    )
finally:
    # Ensure proper shutdown
    await telemetry.shutdown()
```

## Configuration

The SDK is configured using the `TelemetryConfig` class:

```python
TelemetryConfig(
    service_name: str,                                      # Required: Name of your service
    environment: str,                                       # Required: Deployment environment
    version: Optional[str] = "1.0.0",                       # Service version
    otlp_endpoint: Optional[str] = "http://localhost:4317", # OpenTelemetry collector endpoint
    metric_interval_ms: Optional[int] = 5000,               # Metrics export interval
    log_level: Optional[str] = "INFO",                      # Logging level
    resource_attributes: Optional[Dict[str, str]] = None    # Additional resource attributes
)
```

## Services

### Metrics Service

Create and use different types of metrics:

```python
# Counter
counter = telemetry.metrics.create_counter(
    MetricOptions(
        name="requests.total",
        description="Total requests",
        unit="requests"
    )
)
counter.add(1)

# Histogram
latency = telemetry.metrics.create_histogram(
    MetricOptions(
        name="request.latency",
        description="Request latency",
        unit="ms"
    )
)
latency.record(0.025)

# Up/Down Counter
active_requests = telemetry.metrics.create_up_down_counter(
    MetricOptions(
        name="requests.active",
        description="Active requests"
    )
)
active_requests.add(1)
active_requests.add(-1)
```

### Logging Service

Various logging levels available:

```python
# Info logging
telemetry.logging.info("Operation completed", {"operation_id": "123"})

# Error logging with exception
try:
    raise ValueError("Invalid input")
except Exception as e:
    telemetry.logging.error("Operation failed", e, {"operation_id": "123"})

# Warning logging
telemetry.logging.warn("Resource running low", {"resource": "memory"})

# Debug logging
telemetry.logging.debug("Processing request", {"request_id": "abc"})
```

### Tracing Service

Create spans and manage trace context:

```python
# Create a span for an operation
async def process_request():
    async def operation():
        # Your operation logic here
        return "processed"
    
    return await telemetry.tracing.create_span(
        "process-request",
        operation,
        {"request_type": "user_data"}
    )

# Add attributes to current span
telemetry.tracing.add_attributes({"user_id": "456"})

# Record errors in current span
try:
    raise ValueError("Invalid input")
except Exception as e:
    telemetry.tracing.record_error(e)
```

### FastAPI Integration

To instrument FastAPI applications:

1. First ensure you have the required package:
```bash
poetry add opentelemetry-instrumentation-fastapi
```

2. Then instrument your FastAPI app:
```python
from fastapi import FastAPI
from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    telemetry = Telemetry(
        TelemetryConfig(
            service_name="user-service",
            environment="production"
        )
    )
    await telemetry.start()
    telemetry.tracing.instrument_fastapi(app)
    yield
    # Shutdown
    await telemetry.shutdown()

app = FastAPI(lifespan=lifespan)
```

## Best Practices

1. **Always Use Context Managers or Proper Shutdown**
```python
try:
    await telemetry.start()
    # Your application code
finally:
    await telemetry.shutdown()
```

2. **Use Structured Logging**
```python
telemetry.logging.info("API request processed", {
    "request_id": "req_123",
    "method": "POST",
    "path": "/api/v1/users",
    "status_code": 200,
    "duration_ms": 45.2
})
```

3. **Create Meaningful Metrics**
```python
latency_histogram = telemetry.metrics.create_histogram(
    MetricOptions(
        name="http.response_time",
        description="HTTP request latency distribution",
        unit="ms"
    )
)
```

4. **Use Spans for Operation Context**
```python
async def process_user_request(user_id: str):
    async def operation():
        result = await db.fetch_user(user_id)
        telemetry.tracing.add_attributes({
            "db.result": "success",
            "user.found": "true"
        })
        return result

    return await telemetry.tracing.create_span(
        "process-user-request",
        operation,
        attributes={
            "user.id": user_id,
            "operation.type": "read"
        }
    )
```

## Error Handling

The SDK provides a `TelemetryError` class for handling telemetry-specific errors:

```python
from autonomize_sdk import TelemetryError

try:
    await telemetry.start()
except TelemetryError as e:
    print(f"Telemetry error: {e}")
    print(f"Caused by: {e.cause}")
```

## Contributing

We welcome contributions! Here's how you can help:

Please read our [**Contributing Guide**](../CONTRIBUTING.md) before making any changes.

## Acknowledgments

- Built with [OpenTelemetry](https://opentelemetry.io/docs/languages/python)
- Inspired by best practices in observability and monitoring

Together, we can make Autonomize SDK better! 🌟