Python OTEL wrapper by Rebrandly
Project description
rebrandly-otel (Python)
OpenTelemetry SDK for Rebrandly Python services.
Installation
pip install rebrandly-otel
Environment Variables
| Variable | Required | Description |
|---|---|---|
OTEL_SERVICE_NAME |
Yes | Service identifier |
OTEL_SERVICE_APPLICATION |
Yes | Application namespace (groups services) |
OTEL_EXPORTER_OTLP_ENDPOINT |
Yes | OTLP collector endpoint |
OTEL_REPO_NAME |
No | Repository name |
OTEL_COMMIT_ID |
No | Commit ID for version tracking |
Lambda Handler
from rebrandly_otel import lambda_handler, logger
@lambda_handler(name="my-function")
def handler(event, context):
logger.info("Processing", extra={"event_id": event.get("id")})
return {"statusCode": 200}
AWS Message Handler
from rebrandly_otel import aws_message_handler
@aws_message_handler(name="process-message")
def process_record(record):
# trace context automatically extracted from message
return {"success": True}
Framework Middleware
Flask
from flask import Flask
from rebrandly_otel import otel, setup_flask
app = Flask(__name__)
setup_flask(otel, app)
@app.route('/api/users')
def get_users():
return {"users": []}
FastAPI
from fastapi import FastAPI
from rebrandly_otel import otel, setup_fastapi
app = FastAPI()
setup_fastapi(otel, app)
@app.get('/api/users')
async def get_users():
return {"users": []}
Custom Instrumentation
Manual Spans
from rebrandly_otel import otel
with otel.span("operation-name", attributes={"user.id": user_id}):
# your code
Structured Logging
from rebrandly_otel import logger
logger.info("Order processed", extra={"order_id": order_id, "amount": amount})
HTTP Client Tracing
Using requests
from rebrandly_otel import requests_with_tracing
session = requests_with_tracing()
response = session.get('https://api.rebrandly.com/v1/links')
Using httpx
from rebrandly_otel import httpx_with_tracing
client = httpx_with_tracing()
response = client.get('https://api.rebrandly.com/v1/links')
Manual Header Injection
from rebrandly_otel import inject_traceparent
headers = {'Content-Type': 'application/json'}
inject_traceparent(headers)
# headers now includes traceparent
Custom Metrics
from rebrandly_otel import meter
# Counter
request_counter = meter.meter.create_counter(
name='http.requests.total',
description='Total HTTP requests'
)
request_counter.add(1, {'method': 'GET', 'endpoint': '/api/users'})
# Histogram
duration = meter.meter.create_histogram(
name='http.request.duration',
description='Request duration in ms',
unit='ms'
)
duration.record(123, {'endpoint': '/api/users'})
# Gauge
gauge = meter.meter.create_gauge(
name='queue.size',
description='Current queue size'
)
gauge.record(42)
Database Instrumentation
PyMySQL
import pymysql
from rebrandly_otel import otel, instrument_pymysql
connection = pymysql.connect(host='localhost', user='user', password='pass', database='db')
connection = instrument_pymysql(otel, connection)
# All queries now automatically traced
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM users WHERE id = %s", (123,))
SQLite3
import sqlite3
from rebrandly_otel import otel, instrument_sqlite3
# Create connection
connection = sqlite3.connect('database.db') # or ':memory:'
# Instrument connection
connection = instrument_sqlite3(otel, connection, options={
'slow_query_threshold_ms': 1000,
'capture_bindings': False
})
# Use normally - all queries are traced
cursor = connection.cursor()
cursor.execute("SELECT * FROM users WHERE id = ?", (123,))
# SQLite also supports direct connection execution
connection.execute("CREATE TABLE test (id INTEGER)")
Redis
Redis operations are automatically traced - just initialize the SDK:
from rebrandly_otel import otel
import redis
otel.initialize() # Redis instrumentation enabled automatically
client = redis.Redis(host='localhost', port=6379, db=0)
client.set('key', 'value') # Automatically traced
Note: Unlike PyMySQL/SQLite3, Redis requires no explicit instrumentation call. All Redis clients (including async and cluster) are automatically traced when the SDK initializes.
AWS Message Handling (SQS/SNS)
Sending with Trace Context
from rebrandly_otel import otel
trace_attrs = otel.tracer.get_attributes_for_aws_from_context()
sqs.send_message(QueueUrl=url, MessageBody=json.dumps(data), MessageAttributes=trace_attrs)
Receiving with Context Extraction
from rebrandly_otel import aws_message_span
with aws_message_span("process-message", message=record):
# trace context automatically extracted
Force Flush (Critical for Lambda)
from rebrandly_otel import force_flush, shutdown
# Before Lambda exits
force_flush(timeout_millis=5000)
shutdown()
Span Status Methods
from rebrandly_otel import otel
otel.tracer.set_span_error("Operation failed")
otel.tracer.set_span_error("Failed", exception=e)
otel.tracer.set_span_success()
Cost Optimization (Errors-Only Filtering)
For high-volume services, filter out successful spans to reduce costs by 90-99%:
export OTEL_SPAN_ATTRIBUTES="span.filter=errors-only"
This adds the filter attribute to all spans. The OTEL Gateway drops successful spans while keeping all errors. Metrics are still generated from 100% of traces at the agent level.
Tips
- Always call
force_flush()before Lambda exits - Use
OTEL_DEBUG=truefor local debugging - Keep metric cardinality low (< 1000 combinations)
- Add 2-3 seconds buffer to Lambda timeout for flush
Troubleshooting
No Data Exported:
- Verify
OTEL_EXPORTER_OTLP_ENDPOINTis set - Enable
OTEL_DEBUG=truefor console output - Check network connectivity to collector
Missing Traces in Lambda:
- Ensure
force_flush()is called before exit - Add 2-3s buffer to Lambda timeout
- Use
@lambda_handlerdecorator withauto_flush=True
Context Not Propagating:
- Sending: Use
otel.tracer.get_attributes_for_aws_from_context()for SQS/SNS - HTTP: Use
inject_traceparent(headers)before requests - Receiving: Use
aws_message_spancontext manager
Best Practices
Do:
- Use context managers for spans (auto-cleanup)
- Use meaningful span names (
fetch-user-profile, nothandler) - Add business context (
order.id,user.id) to spans - Flush telemetry before Lambda exits
- Use bounded attribute values in metrics
Don't:
- Store large payloads in span attributes (< 1KB)
- Use high-cardinality attributes in metrics (
user_id,request_id) - Hardcode service names (use env vars)
- Skip error recording in except blocks
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 rebrandly_otel-0.4.8.tar.gz.
File metadata
- Download URL: rebrandly_otel-0.4.8.tar.gz
- Upload date:
- Size: 68.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ce649d0c713e83bc80b9587cc68d843f92d68ce961fd89855f9d95735f7b24b
|
|
| MD5 |
b8fc48de2d906237414aa39c0b4facaf
|
|
| BLAKE2b-256 |
a9932f1bfe3be41f58a74e2a6bdd39e3d4e34abb279978c449db7219b7fbebd6
|
File details
Details for the file rebrandly_otel-0.4.8-py3-none-any.whl.
File metadata
- Download URL: rebrandly_otel-0.4.8-py3-none-any.whl
- Upload date:
- Size: 45.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed1cc63ab6126a27a73400e120186e4ba5d464d492caebf4ce0d4350c13bd045
|
|
| MD5 |
3fd4052539250b3274775c7e1cc4672e
|
|
| BLAKE2b-256 |
6fea5b8321fc44ad3f3c291a74305a65c780dd80078210dd862ddb688d62d9c8
|