Advanced Configuration Guide
Overview
This tutorial covers advanced configuration patterns for the HoneyHive SDK, including multi-instance setups, environment-based configuration, and production deployment strategies.
Prerequisites
Completed the Set Up Your First Tracer tutorial
Understanding of Python environment variables
Familiarity with configuration management concepts
What You’ll Learn
By the end of this tutorial, you’ll understand:
Advanced Configuration Patterns: Complex configuration scenarios
Multi-Instance Architecture: Running multiple tracers simultaneously
Environment-Based Configuration: Different configs for dev/staging/prod
Production Best Practices: Secure, scalable configuration strategies
Configuration Validation: Type safety and error handling
Configuration Patterns
Basic Configuration Review
The HoneyHive SDK supports three configuration approaches:
from honeyhive import HoneyHiveTracer
from honeyhive.config.models import TracerConfig
config = TracerConfig(
api_key="hh_1234567890abcdef",
project="my-project",
verbose=True
)
tracer = HoneyHiveTracer(config=config)
from honeyhive import HoneyHiveTracer
tracer = HoneyHiveTracer(
api_key="hh_1234567890abcdef",
project="my-project",
verbose=True
)
from honeyhive.config.models import TracerConfig
config = TracerConfig(api_key="hh_key", project="my-project")
tracer = HoneyHiveTracer(config=config, verbose=True)
Advanced Configuration Patterns
1. Environment-Based Configuration
Scenario: Different configurations for development, staging, and production environments.
Implementation:
import os
from honeyhive import HoneyHiveTracer
from honeyhive.config.models import TracerConfig
def create_tracer_for_environment() -> HoneyHiveTracer:
"""Create tracer based on current environment."""
environment = os.getenv("ENVIRONMENT", "development")
if environment == "production":
config = TracerConfig(
api_key=os.getenv("HH_PROD_API_KEY"),
project="production-llm-app",
source="production",
verbose=False, # Minimal logging in prod
disable_http_tracing=True, # Reduce overhead
cache_enabled=True,
cache_max_size=5000
)
elif environment == "staging":
config = TracerConfig(
api_key=os.getenv("HH_STAGING_API_KEY"),
project="staging-llm-app",
source="staging",
verbose=True,
disable_http_tracing=False,
cache_enabled=True,
cache_max_size=2000
)
else: # development
config = TracerConfig(
api_key=os.getenv("HH_DEV_API_KEY"),
project="dev-llm-app",
source="development",
verbose=True,
disable_http_tracing=False,
test_mode=True, # Don't send data to backend in dev
cache_enabled=False # Disable caching for testing
)
return HoneyHiveTracer(config=config)
# Usage
tracer = create_tracer_for_environment()
Environment Variables Setup:
# Development
export ENVIRONMENT="development"
export HH_DEV_API_KEY="hh_dev_1234567890abcdef"
# Staging
export ENVIRONMENT="staging"
export HH_STAGING_API_KEY="hh_staging_1234567890abcdef"
# Production
export ENVIRONMENT="production"
export HH_PROD_API_KEY="hh_prod_1234567890abcdef"
2. Multi-Instance Configuration
Scenario: Running multiple tracers for different services or workflows.
Implementation:
from honeyhive import HoneyHiveTracer
from honeyhive.config.models import TracerConfig
from typing import Dict
class MultiTracerManager:
"""Manages multiple HoneyHive tracer instances."""
def __init__(self):
self.tracers: Dict[str, HoneyHiveTracer] = {}
self._initialize_tracers()
def _initialize_tracers(self):
"""Initialize tracers for different services."""
# Data Pipeline Tracer
self.tracers["data_pipeline"] = HoneyHiveTracer(
config=TracerConfig(
api_key=os.getenv("HH_DATA_API_KEY"),
project="data-pipeline",
source="etl-service",
verbose=False,
cache_enabled=True,
cache_max_size=10000
)
)
# LLM Inference Tracer
self.tracers["llm_inference"] = HoneyHiveTracer(
config=TracerConfig(
api_key=os.getenv("HH_INFERENCE_API_KEY"),
project="llm-inference",
source="inference-service",
verbose=True,
disable_http_tracing=False,
cache_enabled=True,
cache_max_size=5000
)
)
# Evaluation Tracer
self.tracers["evaluation"] = HoneyHiveTracer(
config=TracerConfig(
api_key=os.getenv("HH_EVAL_API_KEY"),
project="model-evaluation",
source="evaluation-service",
verbose=True,
test_mode=False
)
)
def get_tracer(self, service: str) -> HoneyHiveTracer:
"""Get tracer for specific service."""
if service not in self.tracers:
raise ValueError(f"Unknown service: {service}")
return self.tracers[service]
def trace_data_pipeline(self, func):
"""Decorator for data pipeline functions."""
return self.tracers["data_pipeline"].trace(func)
def trace_llm_inference(self, func):
"""Decorator for LLM inference functions."""
return self.tracers["llm_inference"].trace(func)
def trace_evaluation(self, func):
"""Decorator for evaluation functions."""
return self.tracers["evaluation"].trace(func)
# Global tracer manager
tracer_manager = MultiTracerManager()
# Usage examples
@tracer_manager.trace_data_pipeline
def process_raw_data(data):
"""Process raw data through ETL pipeline."""
# Data processing logic
return processed_data
@tracer_manager.trace_llm_inference
def generate_response(prompt):
"""Generate LLM response."""
# LLM inference logic
return response
@tracer_manager.trace_evaluation
def evaluate_model_performance(model, dataset):
"""Evaluate model performance."""
# Evaluation logic
return metrics
3. Session-Based Configuration
Scenario: Different session configurations for various user interactions.
Implementation:
from honeyhive import HoneyHiveTracer
from honeyhive.config.models import TracerConfig, SessionConfig
from typing import Optional, Dict, Any
class SessionAwareTracer:
"""Tracer with dynamic session configuration."""
def __init__(self, base_config: TracerConfig):
self.base_tracer = HoneyHiveTracer(config=base_config)
def create_user_session(
self,
user_id: str,
session_type: str = "chat",
user_metadata: Optional[Dict[str, Any]] = None
) -> HoneyHiveTracer:
"""Create tracer with user-specific session."""
# session_name goes in TracerConfig, not SessionConfig
tracer_config = self.base_tracer.config.model_copy(update={
"session_name": f"{session_type}-{user_id}"
})
# SessionConfig only has: session_id, inputs, link_carrier
session_config = SessionConfig(
inputs={
"user_id": user_id,
"session_type": session_type,
"timestamp": datetime.now().isoformat(),
**(user_metadata or {})
}
)
return HoneyHiveTracer(
config=tracer_config,
session_config=session_config
)
def create_batch_session(
self,
batch_id: str,
batch_size: int
) -> HoneyHiveTracer:
"""Create tracer for batch processing."""
# Update tracer config with session_name
tracer_config = self.base_tracer.config.model_copy(update={
"session_name": f"batch-{batch_id}"
})
# SessionConfig only has: session_id, inputs, link_carrier
session_config = SessionConfig(
inputs={
"batch_id": batch_id,
"batch_size": batch_size,
"processing_type": "batch"
}
)
return HoneyHiveTracer(
config=tracer_config,
session_config=session_config
)
# Usage
base_config = TracerConfig(
api_key="hh_1234567890abcdef",
project="chat-application",
source="production"
)
session_tracer = SessionAwareTracer(base_config)
# Create user-specific tracer
user_tracer = session_tracer.create_user_session(
user_id="user_123",
session_type="support_chat",
metadata={"priority": "high", "department": "technical"}
)
@user_tracer.trace
def handle_user_query(query: str):
"""Handle user query with session context."""
# Query handling logic
return response
4. Configuration Validation and Error Handling
Scenario: Robust configuration with validation and graceful error handling.
Implementation:
from honeyhive.config.models import TracerConfig
from pydantic import ValidationError
import logging
logger = logging.getLogger(__name__)
def create_validated_tracer(
api_key: str,
project: str,
**kwargs
) -> Optional[HoneyHiveTracer]:
"""Create tracer with comprehensive validation."""
try:
# Attempt to create configuration
config = TracerConfig(
api_key=api_key,
project=project,
**kwargs
)
# Validate API key format
if not api_key.startswith("hh_"):
logger.warning("API key doesn't follow expected format (hh_*)")
# Create tracer
tracer = HoneyHiveTracer(config=config)
# Test tracer initialization
if hasattr(tracer, 'test_connection'):
if not tracer.test_connection():
logger.warning("Tracer connection test failed")
logger.info(f"Successfully created tracer for project: {project}")
return tracer
except ValidationError as e:
logger.error(f"Configuration validation failed: {e}")
# Create fallback tracer with minimal config
try:
fallback_config = TracerConfig(
api_key=api_key,
project=project,
test_mode=True, # Safe fallback
verbose=False
)
logger.info("Created fallback tracer in test mode")
return HoneyHiveTracer(config=fallback_config)
except Exception as fallback_error:
logger.error(f"Fallback tracer creation failed: {fallback_error}")
return None
except Exception as e:
logger.error(f"Unexpected error creating tracer: {e}")
return None
# Usage with error handling
tracer = create_validated_tracer(
api_key="hh_1234567890abcdef",
project="my-project",
cache_max_size=-100, # Invalid value - will be handled gracefully
server_url="invalid-url" # Invalid URL - will use default
)
if tracer:
@tracer.trace
def my_function():
return "Hello, World!"
else:
logger.error("Failed to create tracer - running without tracing")
def my_function():
return "Hello, World!"
Production Configuration Strategies
1. Docker Environment Configuration
Dockerfile:
FROM python:3.11-slim
# Install dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
# Copy application
COPY . /app
WORKDIR /app
# Set environment variables with defaults
ENV ENVIRONMENT=production
ENV HH_VERBOSE=false
ENV HH_CACHE_ENABLED=true
ENV HH_CACHE_MAX_SIZE=5000
CMD ["python", "app.py"]
docker-compose.yml:
version: '3.8'
services:
app:
build: .
environment:
- ENVIRONMENT=production
- HH_API_KEY=${HH_PROD_API_KEY}
- HH_PROJECT=production-app
- HH_SOURCE=docker-compose
- HH_VERBOSE=false
- HH_CACHE_ENABLED=true
env_file:
- .env.production
Application Code:
from honeyhive.config.models import TracerConfig
from honeyhive import HoneyHiveTracer
# Configuration loaded from environment
config = TracerConfig() # Automatically loads from HH_* env vars
tracer = HoneyHiveTracer(config=config)
2. Kubernetes Configuration
ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: honeyhive-config
data:
HH_PROJECT: "k8s-production-app"
HH_SOURCE: "kubernetes"
HH_VERBOSE: "false"
HH_CACHE_ENABLED: "true"
HH_CACHE_MAX_SIZE: "10000"
Secret:
apiVersion: v1
kind: Secret
metadata:
name: honeyhive-secrets
type: Opaque
data:
HH_API_KEY: <base64-encoded-api-key>
Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: honeyhive-config
- secretRef:
name: honeyhive-secrets
3. AWS Lambda Configuration
Lambda Environment Variables:
import json
import os
from honeyhive import HoneyHiveTracer
from honeyhive.config.models import TracerConfig
# Initialize tracer once (outside handler for reuse)
config = TracerConfig(
api_key=os.environ["HH_API_KEY"],
project=os.environ.get("HH_PROJECT", "lambda-app"),
source="aws-lambda",
verbose=os.environ.get("HH_VERBOSE", "false").lower() == "true",
cache_enabled=False, # Lambda is stateless
disable_batch=True # Immediate export for short-lived functions
)
tracer = HoneyHiveTracer(config=config)
@tracer.trace
def lambda_handler(event, context):
"""AWS Lambda handler with tracing."""
# Your Lambda logic here
result = process_event(event)
return {
'statusCode': 200,
'body': json.dumps(result)
}
@tracer.trace
def process_event(event):
"""Process the Lambda event."""
# Processing logic
return {"processed": True}
Configuration Best Practices
1. Security Best Practices
✅ DO:
Store API keys in environment variables or secure secret management systems
Use different API keys for different environments
Rotate API keys regularly
Use
test_mode=Truein development to avoid sending data
❌ DON’T:
Hardcode API keys in source code
Commit API keys to version control
Use production API keys in development/testing
Log API keys in application logs
Example Secure Configuration:
import os
from honeyhive.config.models import TracerConfig
def create_secure_config():
"""Create configuration with security best practices."""
# Validate API key is present
api_key = os.getenv("HH_API_KEY")
if not api_key:
raise ValueError("HH_API_KEY environment variable is required")
# Validate API key format
if not api_key.startswith("hh_"):
raise ValueError("Invalid API key format")
# Create configuration
config = TracerConfig(
api_key=api_key,
project=os.getenv("HH_PROJECT", "default-project"),
source=os.getenv("HH_SOURCE", "application"),
test_mode=os.getenv("ENVIRONMENT") != "production"
)
return config
2. Performance Best Practices
Production Configuration:
# High-performance production configuration
production_config = TracerConfig(
api_key=os.getenv("HH_API_KEY"),
project="production-app",
source="production",
verbose=False, # Reduce logging overhead
disable_http_tracing=True, # Reduce HTTP tracing overhead
cache_enabled=True, # Enable caching
cache_max_size=10000, # Large cache for high throughput
cache_ttl=3600, # 1 hour cache TTL
disable_batch=False # Use batching for efficiency
)
Development Configuration:
# Development configuration with debugging
development_config = TracerConfig(
api_key=os.getenv("HH_DEV_API_KEY"),
project="dev-app",
source="development",
verbose=True, # Enable verbose logging
test_mode=True, # Don't send data to backend
disable_http_tracing=False, # Enable HTTP tracing for debugging
cache_enabled=False, # Disable caching for testing
disable_batch=True # Immediate export for debugging
)
3. Monitoring and Observability
Configuration with Monitoring:
import logging
from honeyhive.config.models import TracerConfig
from honeyhive import HoneyHiveTracer
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class MonitoredTracer:
"""Tracer wrapper with monitoring capabilities."""
def __init__(self, config: TracerConfig):
self.config = config
self.tracer = HoneyHiveTracer(config=config)
self._setup_monitoring()
def _setup_monitoring(self):
"""Set up monitoring for tracer operations."""
# Log configuration (without sensitive data)
logger.info(f"Initialized tracer for project: {self.config.project}")
logger.info(f"Source: {self.config.source}")
logger.info(f"Verbose mode: {self.config.verbose}")
logger.info(f"Test mode: {self.config.test_mode}")
# Set up health checks
if hasattr(self.tracer, 'health_check'):
try:
health_status = self.tracer.health_check()
logger.info(f"Tracer health check: {health_status}")
except Exception as e:
logger.warning(f"Tracer health check failed: {e}")
def trace(self, func):
"""Trace function with monitoring."""
def wrapper(*args, **kwargs):
try:
return self.tracer.trace(func)(*args, **kwargs)
except Exception as e:
logger.error(f"Tracing error in {func.__name__}: {e}")
# Continue execution without tracing
return func(*args, **kwargs)
return wrapper
Troubleshooting
Common Configuration Issues
Issue 1: API Key Validation Errors
# Problem: Invalid API key format
config = TracerConfig(api_key="invalid_key") # Missing 'hh_' prefix
# Solution: Validate API key format
api_key = "hh_1234567890abcdef"
if not api_key.startswith("hh_"):
raise ValueError("API key must start with 'hh_'")
config = TracerConfig(api_key=api_key)
Issue 2: Environment Variable Not Loading
# Problem: Environment variables not being loaded
config = TracerConfig() # Expected to load from HH_* env vars
# Solution: Verify environment variables are set
import os
required_vars = ["HH_API_KEY", "HH_PROJECT"]
for var in required_vars:
if not os.getenv(var):
raise ValueError(f"Required environment variable {var} is not set")
config = TracerConfig()
Issue 3: Configuration Conflicts
# Problem: Mixed configuration with conflicts
config = TracerConfig(verbose=False)
tracer = HoneyHiveTracer(config=config, verbose=True) # Which takes precedence?
# Solution: Understand precedence order
# 1. Individual parameters (highest)
# 2. Config object values
# 3. Environment variables
# 4. Default values (lowest)
# In this case, verbose=True (individual parameter) wins
Next Steps
Now that you understand advanced configuration patterns:
Implement Environment-Based Config: Set up different configurations for your environments
Try Multi-Instance Setup: Experiment with multiple tracers for different services
Add Configuration Validation: Implement robust error handling in your applications
Review Security Practices: Ensure your API keys and configurations are secure
Related Documentation:
Hybrid Configuration Approach - Complete configuration reference
Configuration Models API - Configuration models API
Tracer Architecture Overview - Tracer architecture details
Migration Guide: v0.1.0+ Architecture - Migration guide with multi-instance examples