Step-by-step guides for common use cases and best practices
Learn how to safely trace production Python applications and identify runtime issues
Read Guide →Set up automated error tracking and alerting with Python Trace Pro
Read Guide →include_stdlib=False for productionmax_locals and max_variable_length to limit data capturefrom python_trace_pro import TraceClient
client = TraceClient(api_key=os.environ["TRACE_API_KEY"])
Trace only the problematic function
result = client.trace(
script_content="""
import sys
sys.path.insert(0, '/app')
from myapp.buggy_module import problematic_function
Reproduce the issue
problematic_function(user_id=12345)
""",
include_stdlib=False,
max_locals=10, # Limit locals capture
max_variable_length=100 # Prevent large data capture
)
Analyze exceptions
trace = client.get_trace(result.session_id, event_type="exception")
for event in trace.events:
logger.error(f"Exception in production: {event.exception_type}")
logger.error(f"Location: {event.filename}:{event.lineno}")
logger.error(f"Locals: {event.locals}")
# .github/workflows/trace.yml
name: Python Trace Tests
on:
push:
branches: [main, develop]
pull_request:
jobs:
trace-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install python-trace-pro
- name: Run traced tests
env:
PYTHON_TRACE_API_KEY: ${{ secrets.PYTHON_TRACE_API_KEY }}
run: |
python scripts/trace_tests.py
- name: Upload trace results
if: failure()
uses: actions/upload-artifact@v3
with:
name: trace-results
path: trace-*.json
Trace Script
# scripts/trace_tests.py
import os
import sys
import json
from python_trace_pro import TraceClient
client = TraceClient(api_key=os.environ["PYTHON_TRACE_API_KEY"])
Trace test suite
result = client.trace(
script_path="tests/test_suite.py",
argv=["--verbose", "--tb=short"]
)
print(f"Trace started: {result.session_id}")
Wait for completion
import time
max_wait = 300 # 5 minutes
waited = 0
while waited < max_wait:
trace = client.get_trace(result.session_id)
if trace.session.status != "RUNNING":
break
time.sleep(5)
waited += 5
Save results
with open(f"trace-{result.session_id}.json", "w") as f:
json.dump({
"session_id": result.session_id,
"status": trace.session.status,
"total_events": trace.session.total_events,
"exception_count": trace.session.exception_count,
"execution_time_ms": trace.session.execution_time_ms
}, f, indent=2)
Fail if exceptions found
if trace.session.exception_count > 0:
print(f"❌ FAILED: {trace.session.exception_count} exceptions found")
exceptions = client.get_trace(result.session_id, event_type="exception")
for event in exceptions.events[:5]: # Show first 5
print(f" {event.exception_type}: {event.exception_message}")
print(f" at {event.filename}:{event.lineno}")
sys.exit(1)
else:
print(f"✅ SUCCESS: No exceptions in {trace.session.total_events} events")
sys.exit(0)
from python_trace_pro import TraceClient
from collections import defaultdict
client = TraceClient(api_key="your_api_key")
Trace potentially slow script
result = client.trace(script_path="slow_app.py")
Get all function calls
trace = client.get_trace(result.session_id, event_type="call")
Analyze function call frequency
function_calls = defaultdict(int)
for event in trace.events:
function_calls[event.function_name] += 1
Find most called functions
print("Most called functions:")
for func, count in sorted(function_calls.items(), key=lambda x: x[1], reverse=True)[:10]:
print(f" {func}: {count} calls")
Overall execution time
print(f"\nTotal execution time: {trace.session.execution_time_ms}ms")
Optimizing Based on Trace Data
**Identify hot spots**: Functions called most frequently
**Check recursion depth**: Unexpected deep recursion
**Analyze data flow**: Unnecessary data copying
**Cache opportunities**: Functions called with same arguments
Example: Finding N+1 Queries
# Trace database-heavy code
result = client.trace(
script_content="""
from myapp.models import User, Post
This might have N+1 query problem
users = User.query.all()
for user in users:
posts = user.posts.all() # Separate query per user!
print(f"{user.name}: {len(posts)} posts")
""",
include_stdlib=False
)
trace = client.get_trace(result.session_id, event_type="call")
Look for database query patterns
db_calls = [e for e in trace.events if 'query' in e.function_name.lower()]
print(f"Database queries: {len(db_calls)}")
If db_calls is high relative to records, you have N+1 problem
# ❌ BAD - Never do this
client = TraceClient(api_key="sk_live_abc123...")
✅ GOOD - Use environment variables
import os
client = TraceClient(api_key=os.environ["PYTHON_TRACE_API_KEY"])
Store keys in secure locations
**Development**: Use .env files (add to .gitignore)
**Production**: Use environment variables or secrets managers
**CI/CD**: Use encrypted secrets (GitHub Secrets, GitLab CI Variables, etc.)
Protecting Sensitive Data
Limit variable capture
# Trace without capturing sensitive data
result = client.trace(
script_content=sensitive_code,
max_locals=5, # Limit local variables captured
max_variable_length=50, # Limit string lengths
include_stdlib=False # Don't trace standard library
)
Filter sensitive variables before tracing
# Pre-process script to remove sensitive data
def sanitize_script(script: str) -> str:
"""Remove sensitive patterns from script"""
import re
# Remove password assignments
script = re.sub(r'password\s*=\s*["'][^"']*["']', 'password="***"', script)
# Remove API keys
script = re.sub(r'api_key\s*=\s*["'][^"']*["']', 'api_key="***"', script)
return script
sanitized = sanitize_script(original_script)
result = client.trace(script_content=sanitized)
Use separate API keys per environment
Development: sk_dev_...
Staging: sk_staging_...
Production: sk_prod_...
This allows you to:
Revoke keys without affecting other environments
Track usage per environment
Apply different rate limits
Data Retention
Delete traces containing sensitive data:
# Trace sensitive operation
result = client.trace(script_content=sensitive_script)
Get results
trace = client.get_trace(result.session_id)
Process the results...
Delete the trace
client.delete_trace(result.session_id)
print("Trace deleted for security")
from python_trace_pro import TraceClient
import logging
logger = logging.getLogger(__name__)
client = TraceClient(api_key=os.environ["TRACE_API_KEY"])
class TraceErrorMonitor:
def __init__(self, client: TraceClient):
self.client = client
def monitor_script(self, script_path: str) -> dict:
"""Monitor a script and return error summary"""
result = self.client.trace(script_path=script_path)
# Wait for completion
import time
time.sleep(5)
trace = self.client.get_trace(result.session_id, poll=True)
error_summary = {
"session_id": result.session_id,
"script": script_path,
"status": trace.session.status,
"total_events": trace.session.total_events,
"exceptions": []
}
if trace.session.exception_count > 0:
exceptions = self.client.get_trace(
result.session_id,
event_type="exception"
)
for event in exceptions.events:
error_summary["exceptions"].append({
"type": event.exception_type,
"message": event.exception_message,
"file": event.filename,
"line": event.lineno,
"function": event.function_name
})
return error_summary
Use the monitor
monitor = TraceErrorMonitor(client)
results = monitor.monitor_script("app/main.py")
if results["exceptions"]:
logger.error(f"Found {len(results['exceptions'])} errors in {results['script']}")
for exc in results["exceptions"]:
logger.error(f" {exc['type']}: {exc['message']} at {exc['file']}:{exc['line']}")
Integration with Error Tracking Services
Sentry Integration
import sentry_sdk
from python_trace_pro import TraceClient
sentry_sdk.init(dsn="your-sentry-dsn")
client = TraceClient(api_key="your_api_key")
def trace_and_report(script_path: str):
"""Trace script and report errors to Sentry"""
try:
result = client.trace(script_path=script_path)
# Get trace results
trace = client.get_trace(result.session_id)
if trace.session.exception_count > 0:
exceptions = client.get_trace(result.session_id, event_type="exception")
for event in exceptions.events:
# Report to Sentry
with sentry_sdk.push_scope() as scope:
scope.set_context("trace", {
"session_id": result.session_id,
"file": event.filename,
"line": event.lineno,
"function": event.function_name,
"locals": event.locals
})
sentry_sdk.capture_message(
f"{event.exception_type}: {event.exception_message}",
level="error"
)
except Exception as e:
sentry_sdk.capture_exception(e)
raise
trace_and_report("production/worker.py")
Scheduled Monitoring
# monitor_cron.py - Run via cron or scheduler
from python_trace_pro import TraceClient
import os
import smtplib
from email.message import EmailMessage
client = TraceClient(api_key=os.environ["TRACE_API_KEY"])
scripts_to_monitor = [
"jobs/data_sync.py",
"jobs/report_generator.py",
"jobs/cleanup.py"
]
errors_found = []
for script in scripts_to_monitor:
result = client.trace(script_path=script)
trace = client.get_trace(result.session_id)
if trace.session.exception_count > 0:
errors_found.append({
"script": script,
"session_id": result.session_id,
"exception_count": trace.session.exception_count
})
Send alert email if errors found
if errors_found:
msg = EmailMessage()
msg["Subject"] = f"⚠️ Trace Monitoring Alert: {len(errors_found)} scripts with errors"
msg["From"] = "monitor@yourapp.com"
msg["To"] = "team@yourapp.com"
body = "Errors detected in scheduled jobs:\n\n"
for error in errors_found:
body += f"- {error['script']}: {error['exception_count']} exceptions\n"
body += f" Session: {error['session_id']}\n\n"
msg.set_content(body)
with smtplib.SMTP("localhost") as s:
s.send_message(msg)
pip install python-trace-pro
Step 3: Create Your First Trace
Create a file test_trace.py:
from python_trace_pro import TraceClient
Initialize client with your API key
client = TraceClient(api_key="your_api_key_here")
Simple script to trace
script = """
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
This will work
result = fibonacci(5)
print(f"Fibonacci(5) = {result}")
This will cause an error
result = fibonacci(-1) # Uncomment to see exception tracking
"""
Execute the trace
print("Starting trace...")
result = client.trace(
script_content=script,
include_stdlib=False,
max_locals=10
)
print(f"✓ Trace started!")
print(f" Session ID: {result.session_id}")
print(f" Status: {result.status}")
print(f" Credits remaining: {result.credits_remaining}")
Wait a moment for trace to complete
import time
time.sleep(2)
Get the results
print("\nFetching results...")
trace = client.get_trace(result.session_id)
print(f"\n✓ Trace completed!")
print(f" Total events: {trace.session.total_events}")
print(f" Exceptions: {trace.session.exception_count}")
print(f" Execution time: {trace.session.execution_time_ms}ms")
View function calls
print("\nFunction calls:")
calls = client.get_trace(result.session_id, event_type="call")
for event in calls.events[:5]: # Show first 5
print(f" {event.function_name} at line {event.lineno}")
Run it:
python test_trace.py
Step 4: Explore the Dashboard
Visit the dashboard to:
View all your traces
See credit usage
Analyze execution patterns
Download trace data
Step 5: Try Exception Tracking
Modify test_trace.py to trace errors:
# Add an intentional error
script = """
def divide(a, b):
return a / b
This will cause ZeroDivisionError
result = divide(10, 0)
"""
result = client.trace(script_content=script)
trace = client.get_trace(result.session_id)
if trace.session.exception_count > 0:
print(f"\n❌ Found {trace.session.exception_count} exception(s):")
exceptions = client.get_trace(result.session_id, event_type="exception")
for event in exceptions.events:
print(f"\n Exception: {event.exception_type}")
print(f" Message: {event.exception_message}")
print(f" Location: {event.filename}:{event.lineno}")
print(f" Function: {event.function_name}")
print(f" Local variables: {event.locals}")
Next Steps
Read the [API Reference](/docs/api) for all available endpoints
Check out [Advanced Examples](/docs/sdk) for complex use cases
Learn [Best Practices](/docs/guides/security-best-practices) for production use