Skip to main content

Python Package - Handit AI

🐍 Python API and packaging for Handit tracing system

This directory contains the Python interface to the Rust-powered Handit tracing engine. It provides both high-level APIs for easy integration and low-level bindings for advanced usage, packaged as handit-ai on PyPI.

📦 Package Structure

python/
├── pyproject.toml           # 📋 Package configuration & build settings
├── dist/                    # 📦 Built wheels and source distributions
├── handit_ai/              # 🎯 High-level Python API
│   ├── __init__.py         # Main public API
│   └── fastapi.py          # FastAPI middleware integration
└── handit_core/            # ⚙️ Low-level Rust bindings
    ├── __init__.py         # Core tracing functionality
    ├── http_instrumentation.py    # HTTP client patching
    ├── openai_instrumentation.py  # OpenAI API tracing
    └── handit_core_native.so      # Compiled Rust extension

🎯 High-Level API (handit_ai)

Purpose

Provides a clean, developer-friendly interface for integrating Handit into Python applications.

Key Features

  • Zero-config operation with sensible defaults
  • Decorator-based tracing for functions
  • Context manager sessions for request boundaries
  • FastAPI middleware for automatic web app tracing
  • Automatic instrumentation enabling on import

Usage Examples

Basic Function Tracing

import handit

@handit.tracing(agent="payment-processor")
def process_payment(amount: float, token: str) -> dict:
    # Business logic here
    return {"status": "success", "charge_id": "ch_123"}

# Alternative using context manager
with handit.session(tag="checkout-flow"):
    result = process_payment(100.0, "tok_abc123")

Configuration

import handit

# Configure endpoints and API keys
handit.configure(
    HANDIT_ENDPOINT="https://your-endpoint.com/events",
    HANDIT_API_KEY="your-api-key",
    HANDIT_SAMPLE_RATE="0.1",  # Sample 10% of traces
    HANDIT_MAX_STR="500"       # Limit string capture length
)

FastAPI Integration

from fastapi import FastAPI
from handit_ai import HanditMiddleware

app = FastAPI()
app.add_middleware(HanditMiddleware, agent="api-server")

@app.get("/users/{user_id}")
async def get_user(user_id: str):
    # Automatically traced with request context
    return {"user_id": user_id, "name": "John Doe"}

⚙️ Low-Level Bindings (handit_core)

Purpose

Provides direct access to the Rust engine with full control over tracing behavior.

Key Components

Core Session Management

from handit_core import session, start_session, on_call, on_return

# Manual session control
session_id = start_session(tag="custom-session", attrs={"env": "prod"})

# Manual event recording
on_call(session_id, "my_function", "__main__", "/app/main.py", 42, time_ns)
on_return(session_id, "my_function", end_time_ns, duration_ns)

Configuration Access

import handit_core

# Low-level configuration
handit_core.configure(
    HANDIT_INCLUDE="myapp\..*",  # Only trace functions in 'myapp' module
    HANDIT_EXCLUDE="^(requests|urllib3)::",  # Exclude HTTP libraries
    HANDIT_CAPTURE_ONLY_CWD=True,  # Only trace current working directory
    HANDIT_REDACT="(?i)(password|token|secret)"  # PII redaction pattern
)

🌐 HTTP Instrumentation

Automatic Patching

The system automatically instruments popular HTTP clients:

Supported Libraries

  • requests - Synchronous HTTP client
  • httpx - Modern async/sync HTTP client
  • aiohttp - Async HTTP client/server framework

What's Captured

import requests  # Automatically patched on handit import

# This call is automatically traced:
response = requests.post(
    "https://api.stripe.com/v1/charges",
    headers={"Authorization": "Bearer sk_..."},  # Automatically redacted
    json={"amount": 10000, "currency": "usd"}
)

# Generates events:
# 1. http_request - method, URL, headers, body, timestamp
# 2. http_response - status, headers, body, duration, errors

Custom Instrumentation

from handit_core.http_instrumentation import patch_requests

# Manual patching control
patch_requests(capture_request_body=True, capture_response_body=False)

🤖 OpenAI Integration

Automatic API Tracing

import openai  # Automatically patched
import handit

client = openai.OpenAI(api_key="sk-...")

with handit.session(tag="ai-assistant"):
    # Automatically traces both function calls AND HTTP requests
    completion = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": "Hello!"}],
        temperature=0.7
    )

Captured Data

  • Function calls: client.chat.completions.create() with full parameters
  • HTTP requests: Raw OpenAI API calls with request/response bodies
  • Return values: Complete ChatCompletion objects
  • Timing: Precise duration of LLM calls
  • Error handling: Failed requests and API errors

🏗️ Build System

PyO3 + Maturin

The package uses modern Rust-Python integration:

# pyproject.toml
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

[tool.maturin]
bindings = "pyo3"
manifest-path = "../handit-runtime/crates/py/Cargo.toml"
module-name = "handit_core.handit_core_native"
python-packages = ["handit_ai", "handit_core"]

Building from Source

# Install build dependencies
pip install maturin

# Development build (with Python bindings)
maturin develop --features python

# Release build for distribution
maturin build --release --features python --sdist

# Create wheels for multiple platforms
# Linux
maturin build --release --features python --target x86_64-unknown-linux-gnu

# macOS
maturin build --release --features python --target x86_64-apple-darwin
maturin build --release --features python --target aarch64-apple-darwin

# Windows
maturin build --release --features python --target x86_64-pc-windows-msvc

Local Development

# Install in development mode
cd python/
pip install -e .

# Run with local changes
python examples/basic_demo.py

Windows-Specific Setup

Prerequisites

  1. Visual Studio Build Tools or Visual Studio Community with C++ workload
  2. Rust toolchain installed via rustup
  3. Python 3.8+ installed

Installation Steps

# Install Rust (if not already installed)
# Download and run rustup-init.exe from https://rustup.rs/

# Install build dependencies
pip install maturin

# For development builds
maturin develop --features python

# For release builds targeting Windows
maturin build --release --features python --target x86_64-pc-windows-msvc

Troubleshooting Windows Builds

  • Ensure you have the Microsoft C++ Build Tools installed
  • If you encounter linking errors, try installing the Windows SDK
  • For Python 3.11+, you may need to install the Microsoft Visual C++ 14.0 redistributable

📊 Event Processing

Event Flow

  1. Python code execution triggers native profiler callbacks
  2. Rust engine captures events with minimal overhead
  3. Background thread processes and buffers events
  4. Export system flushes to files or HTTP endpoints

Event Types Generated

Function Calls

{
  "type": "call",
  "session_id": "sess_abc123",
  "func": "process_payment",
  "module": "myapp.payments",
  "file": "/app/payments.py",
  "line": 45,
  "t0_ns": 1703123456789000000,
  "args_preview": {
    "amount": "100.0",
    "token": "<redacted>"
  }
}

HTTP Requests

{
  "type": "http_request", 
  "session_id": "sess_abc123",
  "method": "POST",
  "url": "https://api.stripe.com/v1/charges",
  "t0_ns": 1703123456789000000,
  "headers": {"authorization": "<redacted>"},
  "bytes_out": 1024,
  "request_body": "{\"amount\": 10000}"
}

Return Values

{
  "type": "return",
  "session_id": "sess_abc123", 
  "func": "process_payment",
  "t1_ns": 1703123456890000000,
  "dt_ns": 101000000,
  "locals_preview": {
    "return": "{\"id\": \"ch_123\", \"status\": \"succeeded\"}"
  }
}

🔧 Configuration Options

Environment Variables

# Core behavior
HANDIT_INCLUDE=".*"                    # Function inclusion pattern
HANDIT_EXCLUDE="^(requests|urllib3)::" # Function exclusion pattern
HANDIT_SAMPLE_RATE="1.0"               # Sampling rate (0.0-1.0)

# Data capture limits
HANDIT_MAX_STR="1000"                  # Max string length
HANDIT_MAX_LOCALS="50"                 # Max local variables to capture

# Export configuration  
HANDIT_OUTPUT_FILE="./handit_events.jsonl"  # Local file output
HANDIT_ENDPOINT="https://api.handit.ai/events"  # HTTP endpoint
HANDIT_API_KEY="your-api-key"          # API authentication

# Security
HANDIT_REDACT="(?i)(api_key|token|password|secret)"  # PII redaction
HANDIT_CAPTURE_ONLY_CWD="false"       # Restrict to current directory

Programmatic Configuration

import handit

handit.configure(
    # Export settings
    HANDIT_ENDPOINT="https://your-endpoint.com/events",
    HANDIT_API_KEY="your-key",
    
    # Performance tuning
    HANDIT_SAMPLE_RATE=0.1,  # 10% sampling
    HANDIT_MAX_STR=500,      # Shorter string previews
    
    # Security
    HANDIT_REDACT=r"(?i)(password|token|key|secret|auth)",
    
    # Filtering
    HANDIT_INCLUDE="myapp\..*",  # Only trace your app
    HANDIT_EXCLUDE="^(requests|urllib3|json)::"  # Skip common libraries
)

🚀 Performance Considerations

Overhead Profile

  • Function calls: ~0.5-1μs per call
  • HTTP requests: ~5-10μs additional overhead
  • Memory usage: ~1-2MB baseline + configurable buffers
  • CPU impact: <1% for typical applications

Optimization Tips

# Reduce data capture for high-volume functions
handit.configure(
    HANDIT_MAX_STR=100,      # Shorter previews
    HANDIT_MAX_LOCALS=10,    # Fewer variables
    HANDIT_SAMPLE_RATE=0.01, # 1% sampling for hot paths
)

# Exclude noisy libraries
handit.configure(
    HANDIT_EXCLUDE=r"^(requests|urllib3|json|logging|threading)::"
)

# Restrict to application code only
handit.configure(
    HANDIT_INCLUDE="myapp\..*",
    HANDIT_CAPTURE_ONLY_CWD=True
)

🧪 Testing

Unit Tests

# Test Python components
cd python/
python -m pytest tests/

# Test specific modules
python -m pytest tests/test_instrumentation.py -v

Integration Tests

# Test with real HTTP calls
python examples/nested_http_demo.py

# Test OpenAI integration (requires API key)
OPENAI_API_KEY=sk-... python examples/openai_test.py

# Test FastAPI middleware
python examples/fastapi_demo.py

Performance Testing

# Benchmark overhead
python benchmarks/function_call_overhead.py

# Memory usage profiling
python -m memory_profiler examples/memory_benchmark.py

📚 Examples Usage

Web Framework Integration

# FastAPI
from fastapi import FastAPI
from handit_ai import HanditMiddleware

app = FastAPI()
app.add_middleware(HanditMiddleware, agent="api")

# Flask (manual)
from flask import Flask
import handit

app = Flask(__name__)

@app.route('/api/users')
@handit.tracing(agent="user-api")
def get_users():
    return {"users": []}

Background Task Tracing

import handit
from celery import Celery

app = Celery('tasks')

@app.task
@handit.tracing(agent="background-worker")
def process_upload(file_id: str):
    # Task processing automatically traced
    return {"status": "processed", "file_id": file_id}

Database Query Tracing

import handit
import psycopg2

@handit.tracing(agent="database")
def get_user_orders(user_id: str):
    with psycopg2.connect(DATABASE_URL) as conn:
        # SQL queries can be traced by decorating helper functions
        return fetch_orders(conn, user_id)

@handit.tracing(agent="sql-query") 
def fetch_orders(conn, user_id):
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM orders WHERE user_id = %s", (user_id,))
    return cursor.fetchall()

🔮 Future Enhancements

Planned Features

  • Database instrumentation for SQLAlchemy, Django ORM
  • Message queue tracing for Celery, RQ, Kafka
  • Template engine instrumentation for Jinja2, Django templates
  • Custom metrics collection beyond function calls

API Improvements

  • Async context managers for better async/await support
  • Type hints for better IDE integration
  • Plugin system for custom instrumentation
  • Real-time streaming for live monitoring dashboards

The Python package provides the friendly developer interface while leveraging Rust's performance for the heavy lifting.

Metadata

Release files for handit-ai 1.0.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for handit-ai 1.0.13
File Size Uploaded
handit_ai-1.0.13.tar.gz 58.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for handit-ai 1.0.13
File Interpreter ABI Platform
handit_ai-1.0.13-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details

Total release size: 2.3 MB

Release files / handit_ai-1.0.13.tar.gz

Download URL handit_ai-1.0.13.tar.gz
Size 58.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5c2bdc2106a436415c5a3b7a8b1c3230a34540b489c3bb7b10ad9a5840c6469b
BLAKE2b-256 checksum
How to use checksums
5cb34b0b8c39c55ad40c67e0be35485006c712209ce5c305375dc98306e211f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.8

Release files / handit_ai-1.0.13-cp312-cp312-macosx_11_0_arm64.whl

Download URL handit_ai-1.0.13-cp312-cp312-macosx_11_0_arm64.whl
Size 2.3 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ac534766a42b62009be3295d8b29b0d3e055804938d19cc5d4e9c1a588e7b5c9
BLAKE2b-256 checksum
How to use checksums
e9c0fe502f6d6af35fa8ccf95b306d12304683ec2d4b83bc5dbdbdaededbe350
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.8

Release history Release notifications | RSS feed

This release

1.0.13 This release

2 release files

1.0.12

1 release file

1.0.11

2 release files

1.0.10

1 release file

1.0.9

1 release file

1.0.8

1 release file

1.0.7

1 release file

1.0.6

1 release file

1.0.4

2 release files

1.0.3

3 release files

1.0.2

2 release files

1.0.1

1 release file

1.0.0

2 release files

0.0.62

1 release file

0.0.61

1 release file

0.0.60

1 release file

0.0.59

1 release file

0.0.58

1 release file

0.0.57

1 release file

0.0.56

1 release file

0.0.55

1 release file

0.0.54

1 release file

0.0.53

1 release file

0.0.52

1 release file

0.0.51

1 release file

0.0.50

1 release file

0.0.49

1 release file

0.0.48

1 release file

0.0.47

1 release file

0.0.46

1 release file

0.0.45

1 release file

0.0.44

1 release file

0.0.43

1 release file

0.0.42

1 release file

0.0.41

1 release file

0.0.40

1 release file

0.0.39

1 release file

0.0.38

1 release file

0.0.37

1 release file

0.0.36

1 release file

0.0.35

1 release file

0.0.34

1 release file

0.0.33

1 release file

0.0.32

1 release file

0.0.26

1 release file

0.0.25

1 release file

0.0.24

1 release file

0.0.23

1 release file

0.0.22

1 release file

0.0.21

1 release file

0.0.20

1 release file

0.0.19

2 release files

0.0.18

3 release files

0.0.17

3 release files

0.0.16

3 release files

0.0.15

3 release files

0.0.14

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page