# OTEL Observability Package
[](https://github.com/Touzi-Mortadha/otel-observability/actions/workflows/pytest.yml)
[](https://github.com/Touzi-Mortadha/otel-observability/actions/workflows/pylint.yml)
[](https://github.com/Touzi-Mortadha/otel-observability/actions/workflows/python-publish.yml)
A unified OpenTelemetry observability package for Python applications that provides easy-to-use logging, metrics, and tracing with best practices.
## Features
- **Unified Configuration**: Configure all observability components through environment variables or programmatic configuration
- **Multiple Exporters**: Support for OTLP (gRPC), HTTP, and Console exporters
- **Thread-Safe**: Singleton pattern ensures thread-safe initialization
- **Easy Integration**: Simple API for logging, metrics, and tracing
- **Decorators**: Built-in decorators for automatic tracing, logging, and trace propagation
## Installation
### From PyPI
```bash
pip install otel-observability
```
### From Source
```bash
git clone https://github.com/Touzi-Mortadha/otel-observability.git
cd otel-observability
pip install -e .
```
## Quick Start
### Basic Usage with Environment Variables
```python
from otel_observability import initialize_observability, get_logger, get_metrics, get_traces
# Initialize observability (reads from environment variables)
manager = initialize_observability()
# Get a logger
logger = get_logger(__name__)
logger.info("Application started")
# Get a meter for metrics
meter = get_metrics("my_app")
request_counter = meter.create_counter("requests_total", description="Total requests")
request_counter.add(1, {"endpoint": "/api"})
# Get a tracer for distributed tracing
tracer = get_traces("my_app")
with tracer.start_as_current_span("process_request") as span:
span.set_attribute("user.id", "123")
logger.info("Processing request")
```
### Programmatic Configuration
```python
from otel_observability import ObservabilityManager, ObservabilityConfig
# Create custom configuration
config = ObservabilityConfig(
app_name="my-app",
component="test-component",
otlp_endpoint="localhost:4317", # OTLP gRPC endpoint
log_level=LogLevel.INFO,
insecure=True,
)
# Initialize with custom config
manager = ObservabilityManager(config)
manager.initialize_all()
# Use the manager directly
logger = manager.get_logger(__name__)
meter = manager.get_meter("my_app")
tracer = manager.get_tracer("my_app")
```
### Using Decorators
```python
from otel_observability import ObservabilityDecorators
@ObservabilityDecorators.trace_method()
@ObservabilityDecorators.log_execution()
def process_data(data):
"""Process data with automatic tracing and logging."""
logger.info(f"Processing data: {data}")
return {"processed": True, **data}
result = process_data({"input": "test"})
```
### Trace Propagation
The `@trace_propagator()` decorator is useful for propagating trace context from incoming requests (e.g., HTTP headers, message queues) and creating child spans:
```python
from otel_observability import ObservabilityDecorators
from opentelemetry.propagate import inject
@ObservabilityDecorators.trace_propagator()
def handle_incoming_request(carrier, payload):
"""
Handle incoming request with trace context propagation.
Args:
carrier: Dictionary containing trace context (e.g., HTTP headers)
payload: The actual request payload
"""
# This function will automatically:
# 1. Extract trace context from the carrier dictionary
# 2. Create a new span as part of the existing trace
# 3. Execute the function within the trace context
# 4. Clean up the context after execution
logger.info(f"Processing payload: {payload}")
return {"status": "success", "data": payload}
# Example usage with W3C trace context
trace_carrier = {}
inject(carrier=trace_carrier)
payload = {"user_id": 123, "action": "login"}
result = handle_incoming_request(trace_carrier, payload)
```
You can also use multiple decorators together:
```python
@ObservabilityDecorators.trace_propagator()
@ObservabilityDecorators.log_execution(logger_name="api_handler")
def api_endpoint_handler(headers, body):
"""Handle API endpoint with trace propagation and logging."""
# The trace_propagator will extract context from headers
# The log_execution will log method entry and exit
return process_business_logic(body)
```
## Configuration
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `OTEL_APP_NAME` | App name for resource attributes | `unknown-service` |
| `OTEL_COMPONENT_NAME` | service name for resource attributes | `unknown-component` |
| `OTEL_GRPC_URL` | OTLP gRPC endpoint URL | None |
| `OTEL_HTTP_URL` | Base HTTP URL for OTLP HTTP exporters | None |
| `OTEL_HTTP_LOGS_URL` | Specific HTTP URL for logs | `{OTEL_HTTP_URL}/v1/logs` |
| `OTEL_HTTP_TRACES_URL` | Specific HTTP URL for traces | `{OTEL_HTTP_URL}/v1/traces` |
| `OTEL_HTTP_METRICS_URL` | Specific HTTP URL for metrics | `{OTEL_HTTP_URL}/v1/metrics` |
| `OTEL_INSECURE` | Use insecure connection for gRPC | `true` |
| `LOG_LEVEL` | Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) | `INFO` |
| `OTEL_METRIC_EXPORT_INTERVAL_MS` | Metrics export interval in milliseconds | `60000` |
| `ENABLE_CONSOLE_DEBUG` | Enable console output for debugging | `false` |
### Programmatic Configuration
Create an `ObservabilityConfig` instance with the following parameters:
- `app_name`: Your app name (required)
- `component`: Your service name (required)
- `otlp_endpoint`: OTLP gRPC endpoint URL
- `http_logs_url`: HTTP endpoint for logs
- `http_traces_url`: HTTP endpoint for traces
- `http_metrics_url`: HTTP endpoint for metrics
- `insecure`: Use insecure connection (default: True)
- `log_level`: Log level (default: LogLevel.INFO)
- `metric_export_interval_ms`: Metrics export interval (default: 60000)
- `enable_console_debug`: Enable console debugging (default: False)
## API Reference
### Core Functions
- `initialize_observability()`: Initialize all components and return manager
- `get_logger(name)`: Get a configured logger instance
- `get_metrics(name, version)`: Get a meter for creating metrics
- `get_traces(name, version)`: Get a tracer for creating spans
### ObservabilityManager
The main manager class providing:
- `get_logger(name)`: Get logger by name
- `get_meter(name, version)`: Get meter by name and version
- `get_tracer(name, version)`: Get tracer by name and version
- `create_counter()`: Create a counter metric
- `create_histogram()`: Create a histogram metric
- `shutdown()`: Gracefully shutdown all providers
### ObservabilityDecorators
- `@trace_method()`: Automatically trace method execution
- `@log_execution()`: Automatically log method execution
- `@trace_propagator()`: Propagate trace context from carrier and create spans
## Examples
### Flask Application
```python
from flask import Flask
from otel_observability import initialize_observability, get_logger, ObservabilityDecorators
app = Flask(__name__)
manager = initialize_observability()
logger = get_logger(__name__)
@app.route('/')
@ObservabilityDecorators.trace_method()
def hello():
logger.info("Hello endpoint called")
return "Hello World!"
if __name__ == '__main__':
app.run()
```
### FastAPI Application
```python
from fastapi import FastAPI
from otel_observability import initialize_observability, get_logger, get_traces
app = FastAPI()
manager = initialize_observability()
logger = get_logger(__name__)
tracer = get_traces("fastapi_app")
@app.get("/")
async def read_root():
with tracer.start_as_current_span("read_root"):
logger.info("Root endpoint called")
return {"Hello": "World"}
Raw data
{
"_id": null,
"home_page": "https://github.com/Touzi-Mortadha/otel-observability",
"name": "otel-observability",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "opentelemetry, observability, logging, metrics, tracing, monitoring",
"author": "Mortada Touzi",
"author_email": "Mortada Touzi <mortada.touzi@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/b3/60/0e4b41681bf011a8baf0530b0e3b8cee684ec0dd7696ba819577e3d7d792/otel_observability-0.1.5.tar.gz",
"platform": null,
"description": "# OTEL Observability Package\n[](https://github.com/Touzi-Mortadha/otel-observability/actions/workflows/pytest.yml)\n[](https://github.com/Touzi-Mortadha/otel-observability/actions/workflows/pylint.yml)\n[](https://github.com/Touzi-Mortadha/otel-observability/actions/workflows/python-publish.yml)\n\nA unified OpenTelemetry observability package for Python applications that provides easy-to-use logging, metrics, and tracing with best practices.\n\n## Features\n\n- **Unified Configuration**: Configure all observability components through environment variables or programmatic configuration\n- **Multiple Exporters**: Support for OTLP (gRPC), HTTP, and Console exporters\n- **Thread-Safe**: Singleton pattern ensures thread-safe initialization\n- **Easy Integration**: Simple API for logging, metrics, and tracing\n- **Decorators**: Built-in decorators for automatic tracing, logging, and trace propagation\n\n## Installation\n\n### From PyPI\n\n```bash\npip install otel-observability\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/Touzi-Mortadha/otel-observability.git\ncd otel-observability\npip install -e .\n```\n\n## Quick Start\n\n### Basic Usage with Environment Variables\n\n```python\nfrom otel_observability import initialize_observability, get_logger, get_metrics, get_traces\n\n# Initialize observability (reads from environment variables)\nmanager = initialize_observability()\n\n# Get a logger\nlogger = get_logger(__name__)\nlogger.info(\"Application started\")\n\n# Get a meter for metrics\nmeter = get_metrics(\"my_app\")\nrequest_counter = meter.create_counter(\"requests_total\", description=\"Total requests\")\nrequest_counter.add(1, {\"endpoint\": \"/api\"})\n\n# Get a tracer for distributed tracing\ntracer = get_traces(\"my_app\")\nwith tracer.start_as_current_span(\"process_request\") as span:\n span.set_attribute(\"user.id\", \"123\")\n logger.info(\"Processing request\")\n```\n\n### Programmatic Configuration\n\n```python\nfrom otel_observability import ObservabilityManager, ObservabilityConfig\n\n# Create custom configuration\nconfig = ObservabilityConfig(\n app_name=\"my-app\",\n component=\"test-component\",\n otlp_endpoint=\"localhost:4317\", # OTLP gRPC endpoint\n log_level=LogLevel.INFO,\n insecure=True,\n)\n\n# Initialize with custom config\nmanager = ObservabilityManager(config)\nmanager.initialize_all()\n\n# Use the manager directly\nlogger = manager.get_logger(__name__)\nmeter = manager.get_meter(\"my_app\")\ntracer = manager.get_tracer(\"my_app\")\n```\n\n### Using Decorators\n\n```python\nfrom otel_observability import ObservabilityDecorators\n\n@ObservabilityDecorators.trace_method()\n@ObservabilityDecorators.log_execution()\ndef process_data(data):\n \"\"\"Process data with automatic tracing and logging.\"\"\"\n logger.info(f\"Processing data: {data}\")\n return {\"processed\": True, **data}\n\nresult = process_data({\"input\": \"test\"})\n```\n\n### Trace Propagation\n\nThe `@trace_propagator()` decorator is useful for propagating trace context from incoming requests (e.g., HTTP headers, message queues) and creating child spans:\n\n```python\nfrom otel_observability import ObservabilityDecorators\nfrom opentelemetry.propagate import inject\n\n@ObservabilityDecorators.trace_propagator()\ndef handle_incoming_request(carrier, payload):\n \"\"\"\n Handle incoming request with trace context propagation.\n \n Args:\n carrier: Dictionary containing trace context (e.g., HTTP headers)\n payload: The actual request payload\n \"\"\"\n # This function will automatically:\n # 1. Extract trace context from the carrier dictionary\n # 2. Create a new span as part of the existing trace\n # 3. Execute the function within the trace context\n # 4. Clean up the context after execution\n \n logger.info(f\"Processing payload: {payload}\")\n return {\"status\": \"success\", \"data\": payload}\n\n# Example usage with W3C trace context\ntrace_carrier = {}\ninject(carrier=trace_carrier)\n\npayload = {\"user_id\": 123, \"action\": \"login\"}\n\nresult = handle_incoming_request(trace_carrier, payload)\n```\n\nYou can also use multiple decorators together:\n\n```python\n@ObservabilityDecorators.trace_propagator()\n@ObservabilityDecorators.log_execution(logger_name=\"api_handler\")\ndef api_endpoint_handler(headers, body):\n \"\"\"Handle API endpoint with trace propagation and logging.\"\"\"\n # The trace_propagator will extract context from headers\n # The log_execution will log method entry and exit\n return process_business_logic(body)\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `OTEL_APP_NAME` | App name for resource attributes | `unknown-service` |\n| `OTEL_COMPONENT_NAME` | service name for resource attributes | `unknown-component` |\n| `OTEL_GRPC_URL` | OTLP gRPC endpoint URL | None |\n| `OTEL_HTTP_URL` | Base HTTP URL for OTLP HTTP exporters | None |\n| `OTEL_HTTP_LOGS_URL` | Specific HTTP URL for logs | `{OTEL_HTTP_URL}/v1/logs` |\n| `OTEL_HTTP_TRACES_URL` | Specific HTTP URL for traces | `{OTEL_HTTP_URL}/v1/traces` |\n| `OTEL_HTTP_METRICS_URL` | Specific HTTP URL for metrics | `{OTEL_HTTP_URL}/v1/metrics` |\n| `OTEL_INSECURE` | Use insecure connection for gRPC | `true` |\n| `LOG_LEVEL` | Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) | `INFO` |\n| `OTEL_METRIC_EXPORT_INTERVAL_MS` | Metrics export interval in milliseconds | `60000` |\n| `ENABLE_CONSOLE_DEBUG` | Enable console output for debugging | `false` |\n\n### Programmatic Configuration\n\nCreate an `ObservabilityConfig` instance with the following parameters:\n\n- `app_name`: Your app name (required)\n- `component`: Your service name (required)\n- `otlp_endpoint`: OTLP gRPC endpoint URL\n- `http_logs_url`: HTTP endpoint for logs\n- `http_traces_url`: HTTP endpoint for traces \n- `http_metrics_url`: HTTP endpoint for metrics\n- `insecure`: Use insecure connection (default: True)\n- `log_level`: Log level (default: LogLevel.INFO)\n- `metric_export_interval_ms`: Metrics export interval (default: 60000)\n- `enable_console_debug`: Enable console debugging (default: False)\n\n## API Reference\n\n### Core Functions\n\n- `initialize_observability()`: Initialize all components and return manager\n- `get_logger(name)`: Get a configured logger instance\n- `get_metrics(name, version)`: Get a meter for creating metrics\n- `get_traces(name, version)`: Get a tracer for creating spans\n\n### ObservabilityManager\n\nThe main manager class providing:\n\n- `get_logger(name)`: Get logger by name\n- `get_meter(name, version)`: Get meter by name and version\n- `get_tracer(name, version)`: Get tracer by name and version\n- `create_counter()`: Create a counter metric\n- `create_histogram()`: Create a histogram metric\n- `shutdown()`: Gracefully shutdown all providers\n\n### ObservabilityDecorators\n\n- `@trace_method()`: Automatically trace method execution\n- `@log_execution()`: Automatically log method execution\n- `@trace_propagator()`: Propagate trace context from carrier and create spans\n\n## Examples\n\n### Flask Application\n\n```python\nfrom flask import Flask\nfrom otel_observability import initialize_observability, get_logger, ObservabilityDecorators\n\napp = Flask(__name__)\nmanager = initialize_observability()\nlogger = get_logger(__name__)\n\n@app.route('/')\n@ObservabilityDecorators.trace_method()\ndef hello():\n logger.info(\"Hello endpoint called\")\n return \"Hello World!\"\n\nif __name__ == '__main__':\n app.run()\n```\n\n### FastAPI Application\n\n```python\nfrom fastapi import FastAPI\nfrom otel_observability import initialize_observability, get_logger, get_traces\n\napp = FastAPI()\nmanager = initialize_observability()\nlogger = get_logger(__name__)\ntracer = get_traces(\"fastapi_app\")\n\n@app.get(\"/\")\nasync def read_root():\n with tracer.start_as_current_span(\"read_root\"):\n logger.info(\"Root endpoint called\")\n return {\"Hello\": \"World\"}\n",
"bugtrack_url": null,
"license": "AGPL-3.0",
"summary": "A unified OpenTelemetry observability package for Python applications",
"version": "0.1.5",
"project_urls": {
"Bug Tracker": "https://github.com/Touzi-Mortadha/otel-observability/issues",
"Homepage": "https://github.com/Touzi-Mortadha/otel-observability"
},
"split_keywords": [
"opentelemetry",
" observability",
" logging",
" metrics",
" tracing",
" monitoring"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "893a7320c95420c241cc4280022e0d6180d012e3d341377b162f2ea644e5d673",
"md5": "32e99d0bfbdaae1764103ffab0c4055a",
"sha256": "7b2e9d31ab4d8edc307f5575f8bdff195b3d9e3c2f8cbe80bd774c66018aaf15"
},
"downloads": -1,
"filename": "otel_observability-0.1.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "32e99d0bfbdaae1764103ffab0c4055a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 25362,
"upload_time": "2025-10-26T19:51:21",
"upload_time_iso_8601": "2025-10-26T19:51:21.054426Z",
"url": "https://files.pythonhosted.org/packages/89/3a/7320c95420c241cc4280022e0d6180d012e3d341377b162f2ea644e5d673/otel_observability-0.1.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "b3600e4b41681bf011a8baf0530b0e3b8cee684ec0dd7696ba819577e3d7d792",
"md5": "ad09a859a66323f9cafb705d61c0a554",
"sha256": "6b15b87f67490d2a6f1a5fe94a0733773e4cc4b89f2eb0f8530796904abbbe40"
},
"downloads": -1,
"filename": "otel_observability-0.1.5.tar.gz",
"has_sig": false,
"md5_digest": "ad09a859a66323f9cafb705d61c0a554",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 30491,
"upload_time": "2025-10-26T19:51:22",
"upload_time_iso_8601": "2025-10-26T19:51:22.610069Z",
"url": "https://files.pythonhosted.org/packages/b3/60/0e4b41681bf011a8baf0530b0e3b8cee684ec0dd7696ba819577e3d7d792/otel_observability-0.1.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-26 19:51:22",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Touzi-Mortadha",
"github_project": "otel-observability",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "opentelemetry-api",
"specs": [
[
"==",
"1.38.0"
]
]
},
{
"name": "opentelemetry-sdk",
"specs": [
[
"==",
"1.38.0"
]
]
},
{
"name": "opentelemetry-exporter-otlp",
"specs": [
[
"==",
"1.38.0"
]
]
},
{
"name": "setuptools",
"specs": [
[
"==",
"80.9.0"
]
]
},
{
"name": "pytest",
"specs": [
[
"==",
"8.4.2"
]
]
},
{
"name": "pytest-cov",
"specs": [
[
"==",
"7.0.0"
]
]
},
{
"name": "pylint",
"specs": [
[
"==",
"4.0.2"
]
]
}
],
"lcname": "otel-observability"
}