Observability integration with Spinal
Project description
SP-OBS: Spinal OpenTelemetry Integration
SP-OBS is Spinal's cost tracking library built on top of OpenTelemetry. It works by automatically instrumenting HTTP libraries (httpx, requests) and attaching a processor to existing OpenTelemetry setups. This dual approach allows it to integrate seamlessly with existing observability frameworks while selectively forwarding AI/LLM operations and billing events to Spinal's platform.
Features
- Seamlessly integrates with existing OpenTelemetry setups
- Works with Logfire, vanilla OpenTelemetry, or any OTEL-compatible framework
- Automatic instrumentation of httpx and requests libraries
- Adds user and workflow context to spans for better tracking
- Selective span processing - only sends relevant AI/billing spans
- Built-in data scrubbing for sensitive information
Installation
pip install sp-obs
Quick Start
Configuration
Configure SP-OBS with your endpoint and API key. Instrumentation happens automatically when you call configure():
import sp_obs
# Configure globally (recommended)
sp_obs.configure(
api_key="your-api-key"
# endpoint defaults to "https://cloud.withspinal.com" if not specified
)
Or use environment variables:
SPINAL_TRACING_ENDPOINT(defaults to "https://cloud.withspinal.com")SPINAL_API_KEY
That's it! SP-OBS will automatically instrument httpx and requests to capture AI/LLM operations and HTTP requests.
Adding Tags to Traces
Use the tag class to add user, workflow, and custom information to traces:
import sp_obs
# As a context manager
with sp_obs.tag(
workflow_id="workflow-123",
user_id="user-456",
aggregation_id="session-789", # optional, reserved keyword
custom_field="value", # any additional tags
environment="production"
):
# All spans created here will have these tags
response = client.chat.completions.create(...)
# As a function call (applies tags to current context)
sp_obs.tag(
workflow_id="workflow-123",
user_id="user-456",
custom_metadata="example"
)
Note: Only aggregation_id is a reserved keyword parameter. All other keyword arguments are added as custom tags with the spinal. prefix.
Configuration Options
Environment Variables
SPINAL_TRACING_ENDPOINT: HTTP endpoint to send spans to (default: "https://cloud.withspinal.com")SPINAL_API_KEY: API key for authenticationSPINAL_PROCESS_MAX_QUEUE_SIZE: Max spans in queue (default: 2048)SPINAL_PROCESS_SCHEDULE_DELAY: Export delay in ms (default: 5000)SPINAL_PROCESS_MAX_EXPORT_BATCH_SIZE: Batch size (default: 512)SPINAL_PROCESS_EXPORT_TIMEOUT: Export timeout in ms (default: 30000)
Advanced Configuration
sp_obs.configure(
api_key="your-api-key",
endpoint="https://cloud.withspinal.com", # Optional - this is the default
headers={"Custom-Header": "value"},
timeout=5,
max_queue_size=2048,
max_export_batch_size=512,
schedule_delay_millis=5000,
export_timeout_millis=30000,
scrubber=my_custom_scrubber # Optional
)
Data Scrubbing
SP-OBS includes automatic scrubbing of sensitive data:
from sp_obs import DefaultScrubber, NoOpScrubber
# Use default scrubber (redacts tokens, keys, passwords)
sp_obs.configure(scrubber=DefaultScrubber())
# Or disable scrubbing
sp_obs.configure(scrubber=NoOpScrubber())
# Or implement custom scrubbing
class MyCustomScrubber:
def scrub_attributes(self, attributes: dict) -> dict:
# Your scrubbing logic
return attributes
sp_obs.configure(scrubber=MyCustomScrubber())
Performance Considerations
SP-OBS uses a BatchSpanProcessor to minimize performance impact:
- Spans are batched and sent asynchronously in a background thread
- Default batch size: 512 spans
- Default flush interval: 5 seconds
- Spans are dropped if queue exceeds max size (default: 2048)
To tune for high-volume applications:
sp_obs.configure(
max_queue_size=5000, # Increase queue size
max_export_batch_size=1000, # Larger batches
schedule_delay_millis=2000 # More frequent exports
)
What Spans Are Captured?
SP-OBS automatically captures:
- AI/LLM spans (identified by
gen_ai.systemattribute) - HTTPX and request spans
- Explicitly created billing event spans
- Spans with attached user/workflow context
All other spans are ignored to minimize overhead and data transfer.
Integration Examples
FastAPI Application
from fastapi import FastAPI
import sp_obs
from openai import AsyncOpenAI
app = FastAPI()
client = AsyncOpenAI()
# Configure on startup
@app.on_event("startup")
async def startup():
sp_obs.configure()
@app.post("/generate")
async def generate(user_id: str, workflow_id: str):
with sp_obs.tag(user_id=user_id, workflow_id=workflow_id):
response = await client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}]
)
return response
License
MIT License - see LICENSE file for details.
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 sp_obs-0.2.2.tar.gz.
File metadata
- Download URL: sp_obs-0.2.2.tar.gz
- Upload date:
- Size: 76.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
761767cd8ce453e582a69391748abbcf4c19a9116456c984fa24097638532796
|
|
| MD5 |
36c6442daf723c13676e0f19269acb6e
|
|
| BLAKE2b-256 |
da3af7e9785b6403045f9807a01ace5eaf5731a0d51efbcb9c97763334fc7f1b
|
File details
Details for the file sp_obs-0.2.2-py3-none-any.whl.
File metadata
- Download URL: sp_obs-0.2.2-py3-none-any.whl
- Upload date:
- Size: 23.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7600c83683c927825b05f10898d0f00e0251ab747d9296940aee511f2b4d729
|
|
| MD5 |
6207a3690e00125a64f142be6bd4e112
|
|
| BLAKE2b-256 |
8d8f28ee55b2a9e99bc44ba4a8c82d97deece62cc3b001710072e41c0b6be516
|