TraceKitTraceKit Docs
Backend SDKs

Python Integration Guide

Integrate TraceKit with Python applications for automatic request tracing and live debugging. Monitor Flask, Django, and FastAPI apps in production with live breakpoints.

Learn how to instrument your Python applications with OpenTelemetry to send distributed traces to TraceKit.

Let AI set up TraceKit for you -- AI assistants can guide you through the entire setup process. Try AI Setup

90% Automatic Tracing

With the right libraries, most of your application will be traced automatically with minimal setup. No need to manually instrument every function.

Prerequisites

What Gets Traced Automatically

With proper setup, these operations are traced automatically with zero manual instrumentation:

ComponentSpan TypeCaptured AttributesAuto-Traced?
HTTP EndpointsSERVERmethod, route, status_code, duration, client_ipYes
Database QueriesDBdb.system, db.statement, db.name, durationYes
HTTP Client CallsCLIENTmethod, url, status_code, duration, peer.serviceYes
Redis OperationsDBdb.system (redis), db.statement, durationYes
Celery TasksCustomtask.name, task.id, status, durationYes
LLM (OpenAI/Anthropic)CLIENTgen_ai.system, model, tokens, cost, finish_reason, latencyYes
Custom Business LogicCustomuser-defined attributesManual

Installation

Install the required OpenTelemetry packages:

# Install TraceKit Python SDK
pip install tracekit-apm

# Framework-specific installation
pip install tracekit-apm[flask]    # For Flask
pip install tracekit-apm[django]   # For Django
pip install tracekit-apm[fastapi]  # For FastAPI
pip install tracekit-apm[all]      # All frameworks

Basic Setup

Create a tracing initialization module in your application:

Create tracing.py

# Simple initialization with TraceKit SDK
import tracekit
import os

# Initialize TraceKit with code monitoring enabled
client = tracekit.init(
    api_key=os.getenv('TRACEKIT_API_KEY'),
    service_name=os.getenv('SERVICE_NAME', 'my-python-app'),
    endpoint=os.getenv('TRACEKIT_ENDPOINT', 'https://app.tracekit.dev'),
    enable_code_monitoring=True  # Enable live debugging
)

# That's it! TraceKit handles all OpenTelemetry setup automatically

Verify It Works -- Start your application and make a few requests. Then open the Traces page in your TraceKit dashboard. You should see:

  • SERVER spans for each incoming HTTP request (Django, Flask, or FastAPI)
  • CLIENT spans for outgoing HTTP calls (if instrumented with requests/httpx)
  • DB spans for database queries (if instrumented with SQLAlchemy/psycopg2)

Traces typically appear within 30 seconds. If you don't see them, check the Troubleshooting section.

Framework Integration

TraceKit works seamlessly with popular Python web frameworks through OpenTelemetry instrumentation.

Flask

# app.py
from flask import Flask, request, jsonify
import tracekit
from tracekit.middleware.flask import init_flask_app
import os

# Create Flask app
app = Flask(__name__)

# Initialize TraceKit with code monitoring
client = tracekit.init(
    api_key=os.getenv("TRACEKIT_API_KEY"),
    service_name="my-flask-app",
    endpoint=os.getenv("TRACEKIT_ENDPOINT", "https://app.tracekit.dev"),
    enable_code_monitoring=True  # Enable live debugging
)

# Add TraceKit middleware (auto-traces all routes!)
init_flask_app(app, client)

@app.route("/api/users/<int:user_id>")
def get_user(user_id):
    # Capture snapshot for debugging (optional)
    if client.get_snapshot_client():
        client.capture_snapshot('get-user', {
            'user_id': user_id,
            'request_path': request.path,
            'request_method': request.method
        })

    return jsonify({"id": user_id, "name": "Alice"})

if __name__ == "__main__":
    app.run(port=5000)

Django

# settings.py
from tracing import init_tracer
import os

# Initialize tracing at Django startup
init_tracer(
    service_name="my-django-app",
    endpoint=os.getenv("TRACEKIT_ENDPOINT", "https://app.tracekit.dev"),
    api_key=os.getenv("TRACEKIT_API_KEY")
)

# Add Django instrumentation to INSTALLED_APPS (not required but recommended)
# Then use:
# opentelemetry-instrument python manage.py runserver

# Or instrument manually in your WSGI/ASGI file:
from opentelemetry.instrumentation.django import DjangoInstrumentor
DjangoInstrumentor().instrument()

Django Middleware Setup

# settings.py
MIDDLEWARE = [
    'tracekit.middleware.django.TracekitDjangoMiddleware',
    # ... other middleware
]

FastAPI

# main.py
from fastapi import FastAPI
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
import os
from tracing import init_tracer

# Initialize tracing
init_tracer(
    service_name="my-fastapi-app",
    endpoint=os.getenv("TRACEKIT_ENDPOINT", "https://app.tracekit.dev"),
    api_key=os.getenv("TRACEKIT_API_KEY")
)

# Create FastAPI app
app = FastAPI()

# Auto-instrument FastAPI
FastAPIInstrumentor.instrument_app(app)

@app.get("/api/users")
async def get_users():
    return {"users": ["alice", "bob", "charlie"]}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

FastAPI Middleware Setup

from tracekit.middleware.fastapi import init_fastapi_app

app = FastAPI()
init_fastapi_app(app, client)

Middleware API Reference

Function / ClassParametersReturnsDescription
create_flask_middleware()client: TracekitClient, snapshot_enabled: bool = FalseFlaskMiddlewareLower-level Flask middleware factory. Returns WSGI middleware.
init_flask_app()app: Flask, client: TracekitClientNoneHigh-level Flask setup. Registers middleware, error handlers, and request hooks.
TracekitDjangoMiddlewareDjango middleware class--Add 'tracekit.middleware.django.TracekitDjangoMiddleware' to your MIDDLEWARE list.
create_fastapi_middleware()client: TracekitClientASGIMiddlewareFastAPI/Starlette ASGI middleware factory.
init_fastapi_app()app: FastAPI, client: TracekitClientNoneHigh-level FastAPI setup with ASGI middleware, exception handlers, and shutdown hooks.

Code Monitoring (Live Debugging)

TraceKit includes production-safe code monitoring for live debugging without redeployment. Capture variable state and stack traces at any point in your code.

Key Features:

  • Synchronous API -- No await needed (works in both sync and async code)
  • Auto-Registration -- Breakpoints automatically created on first call
  • Background Sync -- SDK polls for active breakpoints every 30 seconds
  • Rate Limited -- Max 1 capture per second per breakpoint
  • Production Safe -- No performance impact when inactive

Enable Code Monitoring

import tracekit
import os

# Option 1: Direct init with keyword argument
client = tracekit.init(
    api_key=os.getenv("TRACEKIT_API_KEY"),
    service_name="my-flask-app",
    enable_code_monitoring=True,  # default: False
)

# Option 2: Using TracekitConfig dataclass
from tracekit import TracekitConfig

config = TracekitConfig(
    api_key=os.getenv("TRACEKIT_API_KEY"),
    service_name="my-flask-app",
    enable_code_monitoring=True,
)
client = tracekit.init(config=config)

Adding Snapshots

@app.route("/api/checkout")
def checkout():
    cart = request.get_json()
    user_id = cart['user_id']

    # Capture snapshot at this point (synchronous - no await)
    if client.get_snapshot_client():
        client.capture_snapshot('checkout-validation', {
            'user_id': user_id,
            'cart_items': len(cart.get('items', [])),
            'total_amount': cart.get('total', 0),
        })

    # Process payment...
    result = process_payment(cart)

    # Another checkpoint
    if client.get_snapshot_client():
        client.capture_snapshot('payment-complete', {
            'user_id': user_id,
            'payment_id': result['payment_id'],
            'success': result['success'],
        })

    return jsonify({'status': 'success', 'result': result})

What Gets Captured:

  • Variable values at capture point
  • Full call stack with file/line numbers
  • Request context (HTTP method, URL, headers)
  • Execution timestamp

Production Safety

The Python SDK includes multiple layers of protection to ensure code monitoring is safe for production environments:

  • PII Scrubbing -- 13 built-in patterns detect sensitive data (passwords, tokens, API keys, etc.). Enabled by default with typed [REDACTED:type] markers.
  • Crash Isolation -- All SDK entry points are wrapped in try/except blocks. Snapshot failures are silently caught and logged -- your application code is never affected.
  • Circuit Breaker -- After 3 consecutive failures within 60 seconds, the circuit opens and snapshot capture pauses for a 5-minute cooldown. Auto-recovers once the cooldown expires.
  • Remote Kill Switch -- Disable all snapshot capture instantly from the TraceKit dashboard. The kill switch state propagates to SDKs via SSE -- no redeployment required.

Real-Time Updates -- The Python SDK receives real-time configuration updates via Server-Sent Events (SSE). When you toggle breakpoints or activate the kill switch from the dashboard, changes propagate to all connected SDK instances immediately -- no polling delay and no redeployment needed.

Code Monitoring API

Method / ClassParametersReturnsDescription
capture_snapshot()label: str, variables: dictNoneCaptures a snapshot of variable state. Synchronous API. Auto-registers breakpoint on first call. Rate-limited to 1 capture/sec per label.
get_snapshot_client()noneOptional[SnapshotClient]Returns the snapshot client if code monitoring is enabled, or None if disabled.
SnapshotClientclass--Manages breakpoint polling and snapshot uploads. Created automatically when enable_code_monitoring=True.

capture_config Options

KeyTypeDefaultDescription
capture_depthint3Maximum depth for nested object serialization.
max_payloadint16384Maximum payload size in bytes per snapshot.
capture_timeoutfloat5.0Timeout in seconds for sending a snapshot to the server.
pii_scrubbingboolTrueEnable PII detection and redaction with 13 built-in patterns.
circuit_breakerboolTrueEnable the circuit breaker. After 3 failures in 60 seconds, pauses for 5-minute cooldown.

End-to-End Workflow

  1. Enable Code Monitoring -- Set enable_code_monitoring=True in your init config.
  2. Add Capture Points -- Place capture_snapshot calls at code paths you want to debug. The Python API is synchronous -- no await needed.
  3. Deploy and Verify Traces -- Deploy your application and confirm traces are flowing at /traces.
  4. Navigate to Code Monitoring -- Go to /snapshots and click the "Browse Code" tab.
  5. Set Breakpoints -- Breakpoints are auto-registered on the first capture_snapshot call.
  6. Trigger a Capture -- Make a request that hits a code path with capture_snapshot.
  7. View Snapshot -- Go to /snapshots to view captured variables, call stack, and request context.

Full Code Monitoring Documentation

LLM Instrumentation

TraceKit automatically instruments OpenAI and Anthropic SDK calls when detected. LLM calls appear as spans with OTel GenAI semantic convention attributes.

Zero-config auto-instrumentation -- If openai or anthropic is installed, TraceKit patches them automatically at init. Both sync and async methods are covered.

Captured Attributes

AttributeDescription
gen_ai.systemProvider name (openai, anthropic)
gen_ai.request.modelModel name (gpt-4o, claude-sonnet-4-20250514, etc.)
gen_ai.usage.input_tokensPrompt token count
gen_ai.usage.output_tokensCompletion token count
gen_ai.response.finish_reasonsFinish reason (stop, end_turn, tool_calls)

Environment Variable Override

Use TRACEKIT_LLM_CAPTURE_CONTENT=true to enable prompt/completion capture without code changes. Useful for enabling in staging but not production.

Streaming Support

Streaming responses (both sync and async) produce a single span covering the entire stream. Token counts are accumulated from the final event. No special configuration needed.

LLM Dashboard

View LLM cost, token usage, and latency metrics on the dedicated LLM Observability dashboard at /ai/llm in your TraceKit instance.

Nested Spans (Parent-Child Relationships)

Create nested spans to track operations within requests. Parent spans are created automatically by the Flask middleware, and child spans link automatically.

from opentelemetry import trace

@app.route("/api/users/<int:user_id>")
def get_user(user_id):
    # Get the tracer
    tracer = trace.get_tracer(__name__)

    # Parent span is auto-created by Flask middleware
    # Create child span using context manager
    with tracer.start_as_current_span('db.query.user') as span:
        span.set_attributes({
            'db.system': 'postgresql',
            'db.operation': 'SELECT',
            'db.table': 'users',
            'db.statement': 'SELECT * FROM users WHERE id = ?',
            'user.id': user_id
        })

        user = fetch_user_from_db(user_id)

        span.set_attributes({
            'user.found': user is not None,
            'user.role': user.get('role') if user else None
        })

    return jsonify(user)

Trace Hierarchy:

GET /api/users/1 (parent - auto-created)
  +-- db.query.user (child - manually created)

Automatic Instrumentation Libraries

These libraries automatically create child spans for common operations. Set them up once, and every call is traced automatically.

Database Queries

SQLAlchemy

from sqlalchemy import create_engine
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor

# Create engine
engine = create_engine("postgresql://user:pass@localhost/mydb")

# Instrument SQLAlchemy (one line!)
SQLAlchemyInstrumentor().instrument(engine=engine)

# Now all queries are automatically traced
from sqlalchemy.orm import Session
with Session(engine) as session:
    users = session.query(User).all()  # This query is traced!

HTTP Client Calls

from opentelemetry.instrumentation.requests import RequestsInstrumentor
import requests

# Instrument requests library (one line!)
RequestsInstrumentor().instrument()

# Now all HTTP requests are automatically traced
response = requests.get("https://api.example.com/users")  # Traced!

Redis Operations

from redis import Redis
from opentelemetry.instrumentation.redis import RedisInstrumentor

# Instrument Redis
RedisInstrumentor().instrument()

# Create Redis client
redis_client = Redis(host='localhost', port=6379)

# All operations are now traced!
redis_client.set("key", "value")  # Traced!
value = redis_client.get("key")   # Traced!

Auto-Instrumented HTTP Client Libraries

LibrarySpan TypeCaptured AttributesAuto-Instrumented?
requestsCLIENThttp.method, http.url, http.status_code, peer.serviceYes
urllibCLIENThttp.method, http.urlYes
urllib3CLIENThttp.method, http.url, http.status_code, peer.serviceYes

These libraries are instrumented automatically via OpenTelemetry when the SDK is initialized. No additional setup required.

Local UI (Development Mode)

Debug your Python application locally without creating an account. TraceKit Local UI runs on your machine at http://localhost:9999 and automatically receives traces when you run your app in development mode.

Automatic Detection -- The Python SDK automatically detects when Local UI is running on port 9999 and sends traces to both Local UI and cloud (if you have an API key configured).

Quick Start

1. Install the Local UI:

npm install -g @tracekit/local-ui

2. Start the Local UI:

tracekit-local

3. Run your app in development mode:

ENV=development python app.py

4. Open your browser:

http://localhost:9999

Features

  • Auto-Detection -- SDK checks for Local UI at localhost:9999 on startup
  • Real-Time Updates -- See traces instantly with WebSocket live updates
  • Development Only -- Only activates when ENV=development
  • Works Offline -- No internet connection required -- everything runs locally

Benefits

  • See your first trace in under 60 seconds
  • Debug locally without switching to the cloud dashboard
  • Stay in your flow -- everything runs on your machine
  • Works completely offline
  • Perfect for development and demos

Troubleshooting Local UI -- If traces aren't appearing, check:

  • Local UI is running (curl http://localhost:9999/api/health)
  • ENV=development is set
  • SDK version is v0.3.2 or higher
  • Check console for "Local UI detected" message

Service Discovery

TraceKit automatically instruments outgoing HTTP calls to create service dependency graphs. When your service makes an HTTP request to another service, TraceKit creates CLIENT spans and injects trace context headers.

Supported HTTP Clients

  • requests -- Python requests library
  • httpx -- Modern HTTP client
  • aiohttp -- Async HTTP client
  • urllib3 -- Low-level HTTP client

Custom Service Name Mappings

import tracekit
import os

client = tracekit.init(
    api_key=os.getenv('TRACEKIT_API_KEY'),
    service_name='my-service',
    # Map localhost URLs to actual service names
    service_name_mappings={
        'localhost:8082': 'payment-service',
        'localhost:8083': 'user-service',
        'localhost:8084': 'inventory-service',
    }
)

# Now requests to localhost:8082 will show as "payment-service"
import requests
response = requests.get('http://localhost:8082/charge')
# -> Creates CLIENT span with peer.service = "payment-service"

Service Name Detection

URLExtracted Service Name
http://payment-service:3000payment-service
http://payment.internalpayment
http://payment.svc.cluster.localpayment
https://api.example.comapi.example.com

Viewing Service Dependencies -- Visit your TraceKit dashboard to see the Service Map -- a visual graph showing which services call which, with health metrics and latency data.

Manual Instrumentation (Optional)

For custom business logic that isn't covered by auto-instrumentation libraries, you can manually create spans. This is optional and only needed for specific operations you want to measure.

from opentelemetry import trace

@app.route("/api/users/<int:user_id>")
def get_user(user_id):
    # Get the tracer
    tracer = trace.get_tracer(__name__)

    # Parent span is auto-created by Flask middleware
    # Create child span using context manager
    with tracer.start_as_current_span('db.query.user') as span:
        span.set_attributes({
            'db.system': 'postgresql',
            'db.operation': 'SELECT',
            'db.table': 'users',
            'db.statement': 'SELECT * FROM users WHERE id = ?',
            'user.id': user_id
        })

        user = fetch_user_from_db(user_id)

        span.set_attributes({
            'user.found': user is not None,
            'user.role': user.get('role') if user else None
        })

    return jsonify(user)

# Creates a nested trace:
# GET /api/users/1 (parent span - auto-created)
#   +-- db.query.user (child span - manually created)

Core API

SymbolTypeReturnsDescription
get_client()functionTracekitClientReturns the global TracekitClient singleton. Call after tracekit.init().
TracekitClientclass--Main SDK client. Created via tracekit.init(), accessed via tracekit.get_client().
TracekitConfigdataclass--Configuration dataclass with fields: api_key, service_name, endpoint, traces_path, metrics_path, enabled, sample_rate, enable_code_monitoring, auto_instrument_http_client, service_name_mappings.
extract_client_ip_from_headers()functionOptional[str]Extracts client IP from request headers (X-Forwarded-For, X-Real-IP).

TracekitClient Tracing API

MethodParametersReturnsDescription
start_trace()operation_name: str, attributes: Optional[Dict] = NoneSpanCreates a new root trace for top-level operations.
start_server_span()operation_name: str, attributes: Optional[Dict] = None, parent_context = NoneSpanCreates a SERVER span for incoming requests. Extracts trace context from headers.
start_span()operation_name: str, attributes: Optional[Dict] = NoneSpanCreates a child span linked to the current active span.
end_span()span: Span, final_attributes: Optional[Dict] = None, status: str = "OK"NoneEnds a span, recording its duration.
add_event()span: Span, name: str, attributes: Optional[Dict] = NoneNoneRecords a timestamped event on a span.
record_exception()span: Span, exception: ExceptionNoneRecords an exception on a span with message, type, and traceback. Sets span status to ERROR.

Lifecycle Methods

MethodParametersReturnsDescription
flush()noneNoneForces an immediate flush of all pending spans to the backend.
shutdown()noneNoneGracefully shuts down the SDK.
is_enabled()noneboolReturns whether the SDK is currently enabled.
should_sample()noneboolReturns whether the current request should be sampled.

Complete Tracing Lifecycle Example

from tracekit import get_client

client = get_client()
span = client.start_trace("process-order", {"order.id": order_id})

try:
    child = client.start_span("validate-payment")
    client.add_event(child, "payment-validated", {"amount": total})
    client.end_span(child)
    client.end_span(span, {"order.status": "completed"})
except Exception as e:
    client.record_exception(span, e)
    client.end_span(span, status="ERROR")
finally:
    client.flush()

Environment Variables

Best practice: Store sensitive configuration in environment variables:

# .env
TRACEKIT_API_KEY=ctxio_your_generated_api_key_here
TRACEKIT_ENDPOINT=https://app.tracekit.dev
SERVICE_NAME=my-python-app

Configuration Reference

OptionTypeDefaultEnv VariableDescription
api_keystrrequiredTRACEKIT_API_KEYYour TraceKit API key for authentication
service_namestr"python-app"TRACEKIT_SERVICE_NAMEName of your service in the trace dashboard
endpointstr"app.tracekit.dev"TRACEKIT_ENDPOINTTraceKit collector endpoint URL
traces_pathstr"/v1/traces"TRACEKIT_TRACES_PATHHTTP path for trace data export
metrics_pathstr"/v1/metrics"TRACEKIT_METRICS_PATHHTTP path for metrics data export
enabledboolTrueTRACEKIT_ENABLEDEnable or disable tracing globally
sample_ratefloat1.0TRACEKIT_SAMPLE_RATETrace sampling rate (0.0 to 1.0)
enable_code_monitoringboolFalseTRACEKIT_CODE_MONITORING_ENABLEDEnable live code debugging / snapshot capture
auto_instrument_http_clientboolTrue--Auto-instrument outgoing HTTP calls (requests, httpx)
service_name_mappingsOptional[Dict]None--Map host:port to service names for service discovery

The Python SDK does not auto-read environment variables. Read them with os.getenv() and pass to init().

Production Configuration

Production Checklist:

  • Use HTTPS/TLS for the OTLP endpoint
  • Store API keys in a secrets manager (AWS Secrets Manager, HashiCorp Vault)
  • Set appropriate service names and versions
  • Configure resource attributes (deployment.environment, host.name, etc.)
  • Adjust sampling rates if needed for high-traffic services

Custom Metrics

Track custom metrics like request counts, queue sizes, and response times using the TraceKit metrics API.

Counter

Track monotonically increasing values (requests, events):

import tracekit

client = tracekit.init(
    api_key="your-api-key",
    service_name="my-service"
)

# Create a counter with optional tags
counter = client.counter("http.requests.total", tags={"service": "api"})

# Increment by 1
counter.inc()

# Add a specific value
counter.add(5)

Gauge

Track values that can go up or down (queue size, connections):

# Create a gauge
gauge = client.gauge("http.connections.active")

# Set to specific value
gauge.set(42)

# Increment/decrement
gauge.inc()
gauge.dec()

Histogram

Track value distributions (latencies, sizes):

# Create a histogram with tags
histogram = client.histogram("http.request.duration", tags={"unit": "ms"})

# Record values
histogram.record(45.2)
histogram.record(123.5)

View Custom Metrics Guide

Troubleshooting

Traces not appearing?

Cause: The SDK is misconfigured or not initialized before request handling.

Fix:

  • Call tracekit.init() at the top of your application before any framework setup
  • Verify API key: print(os.getenv('TRACEKIT_API_KEY'))
  • Check that enabled is True
  • Review stderr for OpenTelemetry export errors

Connection refused errors?

Cause: The TraceKit endpoint is unreachable.

Fix:

  • Test with curl -X POST https://app.tracekit.dev/v1/traces (expect 401)
  • Check that your Python environment can reach external HTTPS endpoints (proxy, firewall)
  • Verify the endpoint URL

Code monitoring not working?

Cause: Code monitoring defaults to disabled in the Python SDK.

Fix:

  • Set enable_code_monitoring=True in init()
  • Add capture_snapshot() calls in target code paths
  • Ensure the polling interval has elapsed before expecting snapshots
  • Verify API key permissions

Authentication errors (401/403)?

Cause: The API key is invalid or malformed.

Fix:

  • Strip whitespace: api_key=os.getenv('TRACEKIT_API_KEY', '').strip()
  • Regenerate in the dashboard
  • Confirm the key matches the target environment

Missing dependency errors?

Cause: Python OTel packages must be explicitly installed -- they are not bundled with the SDK.

Fix:

  • Install all required packages: pip install tracekit opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation-flask (or the framework-specific package)
  • Use pip list | grep opentelemetry to verify installed versions

Complete Example

Here's a complete working example with Flask:

# Complete Flask example with TraceKit SDK
from flask import Flask, request, jsonify
from opentelemetry import trace
import tracekit
from tracekit.middleware.flask import init_flask_app
import os
import time

# Create Flask app
app = Flask(__name__)

# Initialize TraceKit with code monitoring
client = tracekit.init(
    api_key=os.getenv("TRACEKIT_API_KEY"),
    service_name=os.getenv("SERVICE_NAME", "flask-api"),
    endpoint=os.getenv("TRACEKIT_ENDPOINT", "https://app.tracekit.dev"),
    enable_code_monitoring=True
)

# Add TraceKit middleware
init_flask_app(app, client)

@app.route("/api/users")
def get_users():
    return jsonify({"users": ["alice", "bob", "charlie"]})

@app.route("/api/users/<int:user_id>")
def get_user(user_id):
    # Capture snapshot for debugging
    if client.get_snapshot_client():
        client.capture_snapshot('get-user', {
            'user_id': user_id,
            'request_path': request.path,
            'request_method': request.method
        })

    # Create nested span for database query
    tracer = trace.get_tracer(__name__)
    with tracer.start_as_current_span('db.query.user') as span:
        span.set_attributes({
            'db.system': 'postgresql',
            'db.operation': 'SELECT',
            'db.table': 'users',
            'user.id': user_id
        })
        time.sleep(0.01)  # Simulate DB query

    return jsonify({"id": user_id, "name": "Alice"})

if __name__ == "__main__":
    print("Flask app starting with TraceKit tracing and code monitoring enabled")
    app.run(host="0.0.0.0", port=5000)

Migrating from OpenTelemetry

If you are currently using OpenTelemetry directly, TraceKit wraps it with a simpler API. Replace your OTel setup with tracekit.init() and remove manual exporter configuration. TraceKit handles the OTel pipeline internally.

Performance Overhead

TraceKit is built on OpenTelemetry's efficient batch processing pipeline. The SDK adds minimal overhead to your Python application.

MetricImpactDetails
Request Tracing< 1ms per requestSpans are batched and exported asynchronously
Code Monitoring (Idle)Zero overheadNo performance impact when no active breakpoints
Code Monitoring (Capture)< 5ms per snapshotIncludes variable serialization and security scanning
Memory Footprint~10-20 MBSDK runtime and span buffer

Best Practices

  • DO: Initialize TraceKit at the top of your application -- Call tracekit.init() before any framework setup.
  • DO: Use environment variables for configuration -- Keep API keys, endpoints, and service names in environment variables.
  • DO: Add auto-instrumentation for your dependencies -- SQLAlchemy, requests, Redis, and other libraries can be instrumented with one line.
  • DON'T: Forget to flush before process exit -- Call client.flush() in serverless or short-lived processes.
  • DON'T: Capture sensitive data in snapshots -- Use the built-in PII scrubbing or be selective about what variables you capture.

Next Steps

  • Add auto-instrumentation libraries for components you use (Redis, Celery, MongoDB, etc.)
  • Explore your traces on the Traces page to identify performance bottlenecks
  • Optionally add custom spans for specific business logic you want to measure
  • Configure sampling for high-traffic services to reduce overhead
  • Set up alert rules to get notified when issues occur

On this page