Unified OpenTelemetry initialization for Petrosa services
Project description
Petrosa OpenTelemetry Package
Unified OpenTelemetry initialization for all Petrosa services. This package eliminates code duplication across services and ensures consistent observability behavior.
Features
- ✅ Unified Setup: Single
setup_telemetry()function for all services - ✅ Multi-Service Support: FastAPI, async services, CronJobs, CLI scripts
- ✅ Comprehensive Instrumentation: HTTP, MySQL, MongoDB, FastAPI
- ✅ Smart Defaults: Auto-configuration from environment variables
- ✅ Automatic Resource Detection: Process, host, and Kubernetes metadata enrichment
- ✅ MongoDB Compatible: AttributeFilterSpanProcessor prevents dict/list attribute errors
- ✅ Flexible Logging: Different strategies for different service types
- ✅ Zero Boilerplate: 5 lines of code vs 300+ lines per service
Installation
# Base installation (traces, metrics, logs, HTTP instrumentation)
pip install petrosa-otel
# With FastAPI support
pip install petrosa-otel[fastapi]
# With MySQL support
pip install petrosa-otel[mysql]
# With MongoDB support
pip install petrosa-otel[mongodb]
# With all optional dependencies
pip install petrosa-otel[all]
Quick Start
FastAPI Service (ta-bot, realtime-strategies, data-manager)
from fastapi import FastAPI
from petrosa_otel import setup_telemetry
from petrosa_otel.instrumentors import instrument_fastapi
# Setup telemetry
setup_telemetry(
service_name="ta-bot",
service_type="fastapi",
enable_fastapi=True,
enable_mysql=True,
enable_mongodb=True,
)
# Create FastAPI app
app = FastAPI()
# Instrument the app
instrument_fastapi(app)
# Your routes here...
@app.get("/health")
async def health():
return {"status": "ok"}
Async Service (socket-client, NATS listeners)
import asyncio
from petrosa_otel import setup_telemetry, attach_logging_handler
# Setup telemetry with auto-logging attachment
setup_telemetry(
service_name="socket-client",
service_type="async",
enable_mongodb=True,
auto_attach_logging=True, # Automatically attach logging handler
)
async def main():
# Your async code here
logger.info("Service started")
await process_messages()
if __name__ == "__main__":
asyncio.run(main())
CronJob (data-extractor batch jobs)
from petrosa_otel import setup_telemetry
# Setup telemetry for batch job
setup_telemetry(
service_name="data-extractor",
service_type="cronjob",
enable_mysql=True,
enable_mongodb=True,
auto_attach_logging=True,
)
# Your batch processing code
def extract_klines():
logger.info("Starting kline extraction")
# ... extraction logic ...
if __name__ == "__main__":
extract_klines()
Trade Engine with Leader Election
from petrosa_otel import setup_telemetry
# Setup telemetry
setup_telemetry(
service_name="tradeengine",
service_type="async",
enable_mongodb=True,
auto_attach_logging=True,
)
# Your trade execution logic
async def process_signals():
# Leader election and signal processing
pass
Automatic Resource Detection
The package automatically enriches telemetry with resource attributes using OpenTelemetry's built-in resource detectors:
- Process attributes:
process.pid,process.command,process.runtime.name,process.runtime.version - Host attributes:
host.name,host.arch - SDK attributes:
telemetry.sdk.name,telemetry.sdk.language,telemetry.sdk.version - OS attributes:
os.type,os.description - Kubernetes metadata: Pod name, namespace (when deployed in k8s)
This happens automatically - no configuration required. See RESOURCE_DETECTION.md for details.
Example: Enriched Telemetry Data
Before resource detection:
{
"service.name": "ta-bot",
"service.version": "2.0.0",
"deployment.environment": "production"
}
After resource detection:
{
"service.name": "ta-bot",
"service.version": "2.0.0",
"deployment.environment": "production",
"process.pid": 1,
"process.runtime.name": "cpython",
"process.runtime.version": "3.11.7",
"host.name": "ta-bot-7d9c8f-xz4k2",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "python",
"os.type": "linux"
}
Configuration
Environment Variables
The package respects standard OpenTelemetry environment variables:
# Required
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway.example.com/otlp
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer token123
# Optional (with defaults)
ENABLE_OTEL=true # Global enable/disable
ENABLE_TRACES=true # Enable trace export
ENABLE_METRICS=true # Enable metrics export
ENABLE_LOGS=true # Enable log export
OTEL_SERVICE_VERSION=1.0.0 # Service version
OTEL_RESOURCE_ATTRIBUTES=key=value # Custom attributes
OTEL_METRIC_EXPORT_INTERVAL=60000 # Metric export interval (ms)
ENVIRONMENT=production # Deployment environment
Service Types
| Type | Description | Use Case | Logging Strategy |
|---|---|---|---|
fastapi |
FastAPI application | Web APIs | Uvicorn handles logging |
async |
Async service | NATS listeners, WebSocket clients | Manual attachment via attach_logging_handler() |
cronjob |
Kubernetes CronJob | Batch processing | Auto-attach with auto_attach_logging=True |
cli |
Command-line script | One-off tasks | Auto-attach with auto_attach_logging=True |
API Reference
setup_telemetry()
Main entry point for OpenTelemetry setup.
def setup_telemetry(
service_name: str,
service_version: str | None = None,
service_type: Literal["fastapi", "async", "cronjob", "cli"] = "async",
otlp_endpoint: str | None = None,
enable_metrics: bool = True,
enable_traces: bool = True,
enable_logs: bool = True,
enable_http: bool = True,
enable_mysql: bool = False,
enable_mongodb: bool = False,
enable_fastapi: bool = False,
auto_attach_logging: bool = False,
) -> bool:
Parameters:
service_name: Name of the service (e.g., "ta-bot")service_version: Version (defaults toOTEL_SERVICE_VERSIONenv var)service_type: Type of service (affects logging behavior)otlp_endpoint: OTLP endpoint (defaults toOTEL_EXPORTER_OTLP_ENDPOINT)enable_metrics: Enable metrics exportenable_traces: Enable trace exportenable_logs: Enable log exportenable_http: Instrument HTTP libraries (requests, urllib3)enable_mysql: Instrument PyMySQLenable_mongodb: Instrument PyMongo (enables AttributeFilterSpanProcessor)enable_fastapi: Whether this is a FastAPI app (callinstrument_fastapi()separately)auto_attach_logging: Auto-attach logging handler (for async/cli/cronjob)
Returns: True if successful, False otherwise
attach_logging_handler()
Attach OTLP logging handler to root logger. Required for async services that don't auto-attach.
from petrosa_otel import attach_logging_handler
# After setup_telemetry()
attach_logging_handler()
get_tracer() and get_meter()
Get tracer and meter instances for custom instrumentation.
from petrosa_otel import get_tracer, get_meter
tracer = get_tracer("my-component")
meter = get_meter("my-component")
# Create custom spans
with tracer.start_as_current_span("my-operation") as span:
span.set_attribute("key", "value")
# ... your code ...
# Create custom metrics
counter = meter.create_counter("my_counter")
counter.add(1, {"label": "value"})
instrument_fastapi(app)
Instrument a FastAPI application.
from petrosa_otel.instrumentors import instrument_fastapi
app = FastAPI()
instrument_fastapi(app)
Migration Guide
Before (per-service otel_init.py - 300+ lines)
# otel_init.py (300+ lines of duplicated code)
from opentelemetry import trace, metrics
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# ... 290 more lines ...
def setup_telemetry(...):
# Complex setup logic
pass
# Auto-init at import
if os.getenv("OTEL_AUTO_SETUP", "true") == "true":
setup_telemetry()
After (using petrosa-otel - 5 lines)
from petrosa_otel import setup_telemetry
setup_telemetry(
service_name="ta-bot",
service_type="fastapi",
enable_mysql=True,
)
Migration Steps
-
Install Package:
pip install petrosa-otel[all]
-
Replace otel_init Import:
# Old from otel_init import setup_telemetry, attach_logging_handler_simple, get_tracer # New from petrosa_otel import setup_telemetry, attach_logging_handler, get_tracer
-
Update setup_telemetry() Call:
# Old (many parameters) setup_telemetry( service_name="ta-bot", service_version="1.0.0", otlp_endpoint=os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT"), enable_metrics=True, enable_traces=True, enable_logs=True, ) # New (simplified with smart defaults) setup_telemetry( service_name="ta-bot", service_type="fastapi", enable_mysql=True, enable_mongodb=True, )
-
Update requirements.txt:
# Remove opentelemetry-* dependencies # Add petrosa-otel with extras petrosa-otel[fastapi,mysql,mongodb]>=1.0.0
-
Remove Local otel_init.py:
rm otel_init.py
Troubleshooting
No traces/metrics/logs appearing
- Check
OTEL_EXPORTER_OTLP_ENDPOINTis set - Check
ENABLE_OTEL=true - Check service has network access to OTLP endpoint
- For async services, ensure
attach_logging_handler()was called
MongoDB dict/list attribute errors
This should not happen with petrosa-otel as it automatically uses AttributeFilterSpanProcessor when enable_mongodb=True.
If you still see errors, verify:
setup_telemetry(
service_name="my-service",
enable_mongodb=True, # ← This must be True
)
FastAPI logs not exported
FastAPI uses Uvicorn's logging configuration. The package automatically handles this when service_type="fastapi".
If logs aren't appearing:
- Ensure Uvicorn is configured with proper log level
- Check
ENABLE_LOGS=true - Verify OTLP endpoint is reachable
Development
Running Tests
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=petrosa_otel --cov-report=html
Linting
# Format and lint
ruff check src/
ruff format src/
Benefits
| Metric | Before | After | Improvement |
|---|---|---|---|
| Lines of Code | ~1,900 | ~400 | 80% reduction |
| Files to Maintain | 6 | 1 | 83% reduction |
| Bug Fix Propagation | Manual (6×) | Automatic | 6× faster |
| Time to Add OTel | 30+ min | < 5 min | 6× faster |
| Consistency | ❌ Divergent | ✅ Uniform | 100% consistent |
License
Internal Petrosa package - not for public distribution.
Support
For issues or questions, contact the Petrosa platform team or create an issue in the repository.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file petrosa_otel-1.0.4.tar.gz.
File metadata
- Download URL: petrosa_otel-1.0.4.tar.gz
- Upload date:
- Size: 30.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3fc35446c6f44c211e3c1dffbbd3d7d46c4c42e46533d28da8bb885dd8da656
|
|
| MD5 |
ad9dd565b708854a665f42268ca1e686
|
|
| BLAKE2b-256 |
8a9e6fc533b7d4c0a66d346cddbb8f7a53e980c7b12febf68523c20e94ae382d
|
File details
Details for the file petrosa_otel-1.0.4-py3-none-any.whl.
File metadata
- Download URL: petrosa_otel-1.0.4-py3-none-any.whl
- Upload date:
- Size: 22.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51952fe491b1787b50ea153526494478cb4a4b860bfb6f037ba2935acabb17bf
|
|
| MD5 |
079a604f20f862fcb5cd7b470d03f2ac
|
|
| BLAKE2b-256 |
38c0c00d3bf08578bf500eb611884249ae185a554e81fb3c2731319a1595f4e2
|