SwisperStudio Complete Setup & Deployment Guide¶
Version: 1.0
Last Updated: 2025-11-20
Status: Production Ready
Audience: DevOps, Backend Engineers, System Administrators
📋 Table of Contents¶
- Overview
- Architecture
- Prerequisites
- Part 1: SwisperStudio Deployment
- Part 2: Swisper Backend Integration
- Part 3: Testing & Verification
- Part 4: Production Deployment
- Part 5: Monitoring & Operations
- Troubleshooting
- Reference
Overview¶
What is SwisperStudio?¶
SwisperStudio is an observability and configuration management platform for Swisper applications. It provides:
- 🔍 Tracing - Track LangGraph agent execution flows
- 🛠️ Tool Monitoring - Capture all tool calls with parameters and results
- 💬 LLM Observability - Record prompts, responses, and reasoning
- ⚡ Redis Streams - 50x faster than HTTP polling (1-2ms latency)
- 🔒 Fire-and-Forget - Never blocks Swisper application
System Components¶
┌──────────────────────────────────────────────────────────────┐
│ Same Data Center │
│ │
│ ┌─────────────────┐ ┌──────────────────┐ │
│ │ Swisper │ │ SwisperStudio │ │
│ │ Backend │ │ │ │
│ │ │ │ ┌────────────┐ │ │
│ │ • SDK │ │ │ Frontend │ │ │
│ │ • Agents │ │ │ (React) │ │ │
│ │ │ │ └────────────┘ │ │
│ │ │ │ ┌────────────┐ │ │
│ └────────┬────────┘ │ │ Backend │ │ │
│ │ │ │ (FastAPI) │ │ │
│ │ Publishes │ └────────────┘ │ │
│ │ (<2ms) │ ┌────────────┐ │ │
│ │ │ │ PostgreSQL │ │ │
│ ▼ │ └────────────┘ │ │
│ ┌─────────────────┐ │ │ │ │
│ │ Redis (Studio) │◄───────────────┼─────────┘ │ │
│ │ :6380 │ Consumes │ │ │
│ └─────────────────┘ └──────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────┘
Architecture¶
Design Principles¶
- Isolation - SwisperStudio has its own infrastructure (Redis, DB, services)
- Fire-and-Forget - Swisper publishes events without waiting (1-2ms)
- Graceful Degradation - Swisper works even if Studio is down
- Co-location - Both services in same data center for minimal latency
Data Flow¶
1. User Request → Swisper
2. Agent Execution → SDK captures events
3. SDK publishes to Redis Streams (<2ms)
4. Swisper returns response (continues normally)
[Async, separate process]
5. Studio consumer reads from Redis
6. Events written to PostgreSQL
7. Available in Studio UI
Key Technologies¶
| Component | Technology | Purpose |
|---|---|---|
| Swisper SDK | Python 3.11+ | Captures events, publishes to Redis |
| Redis Streams | Redis 7.2+ | Event transport (fire-and-forget) |
| Studio Backend | FastAPI + Python | Event consumer, API server |
| Studio DB | PostgreSQL 15+ | Trace storage |
| Studio Frontend | React 18 + Vite | Visualization UI |
Prerequisites¶
Required Software¶
- ✅ Docker 20.10+ with Docker Compose
- ✅ Python 3.11+ (for Swisper backend)
- ✅ Node.js 20+ (for Studio frontend development)
- ✅ Git (for cloning repositories)
Required Access¶
- ✅ Access to Swisper backend repository
- ✅ Access to SwisperStudio repository
- ✅ Network connectivity between services (same data center)
System Requirements¶
Minimum (Development): - 4 CPU cores - 8 GB RAM - 20 GB disk space
Recommended (Production): - 8+ CPU cores - 16+ GB RAM - 100+ GB SSD storage
Part 1: SwisperStudio Deployment¶
Step 1.1: Clone Repository¶
# Clone SwisperStudio
cd /root/projects # Or your projects directory
git clone https://github.com/Fintama/swisper_studio.git
cd swisper_studio
Step 1.2: Review Configuration¶
File: docker-compose.yml
The deployment includes: - PostgreSQL (port 5433) - Studio database - Redis (port 6380) - Observability events - Backend (port 8001) - FastAPI API server - Frontend (port 3000) - React development server (optional)
services:
redis:
image: redis:7.2-alpine
ports:
- "6380:6379" # External port 6380
postgres:
image: postgres:15-alpine
ports:
- "5433:5432" # External port 5433
backend:
build: ./backend
ports:
- "8001:8000" # External port 8001
Step 1.3: Environment Configuration¶
Create: .env file in project root
# SwisperStudio Configuration
# Database
POSTGRES_DB=swisper_studio
POSTGRES_USER=studio_user
POSTGRES_PASSWORD=<CHANGE_IN_PRODUCTION>
# Security
SECRET_KEY=<GENERATE_RANDOM_KEY>
API_KEY=<GENERATE_API_KEY>
# CORS (adjust for your domains)
CORS_ORIGINS='["http://localhost:3000","http://localhost:5173","https://swisper-studio.fintama.com"]'
# Environment
ENVIRONMENT=development # development | staging | production
LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR
# Observability
OBSERVABILITY_ENABLED=true
OBSERVABILITY_REDIS_URL=redis://redis:6379
OBSERVABILITY_STREAM_NAME=observability:events
OBSERVABILITY_GROUP_NAME=swisper_studio_consumers
OBSERVABILITY_CONSUMER_NAME=consumer_1
OBSERVABILITY_BATCH_SIZE=100
Generate secure keys:
# Generate SECRET_KEY
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# Generate API_KEY
python3 -c "import secrets; print('studio_' + secrets.token_hex(32))"
Step 1.4: Deploy Services¶
# Start all services
docker compose up -d
# Check status
docker compose ps
# Expected output:
# NAME STATUS PORTS
# swisper_studio_redis Up (healthy) 0.0.0.0:6380->6379/tcp
# swisper_studio_postgres Up (healthy) 0.0.0.0:5433->5432/tcp
# swisper_studio_backend Up 0.0.0.0:8001->8000/tcp
Step 1.5: Initialize Database¶
# Run database migrations
docker compose exec backend alembic upgrade head
# Verify migrations
docker compose exec postgres psql -U studio_user -d swisper_studio -c "\dt"
# Should show tables: traces, observations, projects, users, etc.
Step 1.6: Create Admin User (Optional)¶
# Create initial admin user
docker compose exec backend python -m app.scripts.create_admin \
--email admin@fintama.com \
--password <secure-password>
# Or use the API
curl -X POST http://localhost:8001/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "admin@fintama.com",
"password": "<secure-password>",
"name": "Admin User"
}'
Step 1.7: Verify Deployment¶
# 1. Check backend health
curl http://localhost:8001/health
# Expected: {"status":"healthy","version":"0.1.0"}
# 2. Check Redis
docker exec swisper_studio_redis redis-cli ping
# Expected: PONG
# 3. Check Redis port exposure
docker port swisper_studio_redis
# Expected: 6379/tcp -> 0.0.0.0:6380
# 4. Check PostgreSQL
docker exec swisper_studio_postgres pg_isready -U studio_user
# Expected: /var/run/postgresql:5432 - accepting connections
Step 1.8: Access UI (Optional - Development)¶
# Start frontend development server
cd frontend
npm install
npm run dev
# Access at: http://localhost:3000
Production: Build static assets and serve via nginx/CDN.
Part 2: Swisper Backend Integration¶
Step 2.1: Install SwisperStudio SDK¶
In Swisper backend directory:
# Activate your Python environment
cd /path/to/swisper/backend
source .venv/bin/activate # Or your venv path
# Install SDK from PyPI
pip install swisper-studio-sdk==0.5.0
# Verify installation
python -c "from swisper_studio_sdk import create_traced_graph; print('✅ SDK Ready')"
Add to requirements.txt:
Step 2.2: Configure Swisper Backend¶
File: apps/backend/swisper/core/config.py
Add these settings to your Settings class:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
# ... existing settings ...
# SwisperStudio Integration
SWISPER_STUDIO_ENABLED: bool = True
SWISPER_STUDIO_REDIS_URL: str = "redis://172.17.0.1:6380" # Docker host IP
SWISPER_STUDIO_STREAM_NAME: str = "observability:events"
SWISPER_STUDIO_PROJECT_ID: str = "" # Get from Studio UI
SWISPER_STUDIO_CAPTURE_REASONING: bool = True
SWISPER_STUDIO_REASONING_MAX_LENGTH: int = 50000
class Config:
env_file = ".env"
case_sensitive = True
settings = Settings()
Create: .env file in Swisper backend
# SwisperStudio Observability
SWISPER_STUDIO_ENABLED=true
SWISPER_STUDIO_REDIS_URL=redis://172.17.0.1:6380
SWISPER_STUDIO_PROJECT_ID=<GET_FROM_STUDIO_UI>
Step 2.3: Get Project ID from Studio¶
# 1. Access Studio UI
# Development: http://localhost:3000
# Production: https://swisper-studio.fintama.com
# 2. Navigate to "Projects" → "Create New Project"
# - Name: "Swisper Production" (or "Swisper Development")
# - Description: Main Swisper application
# - Click "Create"
# 3. Click on the project, copy UUID from URL
# URL: /projects/{THIS_IS_YOUR_PROJECT_ID}/traces
# Example: /projects/0d7aa606-cb29-4a31-8a59-50fa61151a32/traces
# 4. Update .env file
echo "SWISPER_STUDIO_PROJECT_ID=0d7aa606-cb29-4a31-8a59-50fa61151a32" >> .env
Step 2.4: Initialize SDK in Swisper¶
File: apps/backend/app/main.py
Add to your startup function (lifespan or @app.on_event("startup")):
import logging
from fastapi import FastAPI
from contextlib import asynccontextmanager
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan"""
# ===== STARTUP =====
# ... existing startup code ...
# Initialize SwisperStudio observability
if settings.SWISPER_STUDIO_ENABLED:
try:
from swisper_studio_sdk import initialize_redis_publisher, wrap_llm_adapter
# Initialize Redis publisher
verification = await initialize_redis_publisher(
redis_url=settings.SWISPER_STUDIO_REDIS_URL,
stream_name=settings.SWISPER_STUDIO_STREAM_NAME,
project_id=settings.SWISPER_STUDIO_PROJECT_ID,
max_stream_length=100000,
verify_consumer=True,
)
logger.info("✅ SwisperStudio observability initialized")
logger.info(f" Redis: {settings.SWISPER_STUDIO_REDIS_URL}")
logger.info(f" Project ID: {settings.SWISPER_STUDIO_PROJECT_ID}")
logger.info(f" Verification: {verification}")
# Enable LLM prompt capture
try:
wrap_llm_adapter()
logger.info("✅ LLM prompt capture enabled")
except Exception as e:
logger.warning(f"⚠️ LLM capture disabled: {e}")
except ImportError:
logger.warning("⚠️ SwisperStudio SDK not installed")
except Exception as e:
logger.error(f"❌ SwisperStudio initialization failed: {e}")
logger.warning(" Continuing without observability")
yield # Application runs
# ===== SHUTDOWN =====
# Close SwisperStudio publisher
if settings.SWISPER_STUDIO_ENABLED:
try:
from swisper_studio_sdk import close_redis_publisher
await close_redis_publisher()
logger.info("✅ SwisperStudio publisher closed")
except Exception as e:
logger.warning(f"⚠️ Failed to close publisher: {e}")
# ... existing shutdown code ...
app = FastAPI(lifespan=lifespan)
Step 2.5: Wrap Agent Graphs¶
For each agent (example: GlobalSupervisor):
File: apps/backend/swisper/agents/supervisor/agent.py
from langgraph.graph import StateGraph
def build_graph(self):
"""Build LangGraph workflow"""
# Wrap with SwisperStudio tracing
try:
from swisper_studio_sdk import create_traced_graph
workflow = create_traced_graph(
GlobalSupervisorState,
trace_name="global_supervisor"
)
self.logger.info("✅ GlobalSupervisor wrapped with tracing")
except ImportError:
workflow = StateGraph(GlobalSupervisorState)
self.logger.warning("⚠️ Tracing disabled (SDK not available)")
# Add nodes (existing code)
workflow.add_node("start", self.start_node)
workflow.add_node("route", self.route_node)
# ... etc
return workflow.compile()
Repeat for all agents:
- GlobalSupervisor
- ResearchAgent
- ProductivityAgent
- WealthAgent
- DocumentAgent
Step 2.6: Update Agent States¶
Add standard observability fields to each agent state:
from typing import TypedDict, List, Dict, Any, Optional
class YourAgentState(TypedDict):
# ... existing fields ...
# SwisperStudio observability (add these)
_tools_executed: List[Dict[str, Any]]
_tools_executed_by: Optional[str]
Step 2.7: Update Tool Execution Nodes¶
For each tool execution node:
from datetime import datetime, timezone
async def execute_tools(self, state):
"""Execute tools and populate observability data"""
# Execute tool (your existing logic)
result = await self.execute_tool(tool_name, params)
# Create standardized tool entry
tool_entry = {
"tool_name": tool_name,
"parameters": params,
"result": result,
"timestamp": datetime.now(timezone.utc).isoformat(),
"status": "success" if result else "failure"
}
# Append to _tools_executed
existing = state.get("_tools_executed", [])
updated = existing + [tool_entry]
# Update state
return {
**state,
"_tools_executed": updated,
"_tools_executed_by": "tool_execution", # MUST match node name!
}
⚠️ Critical: _tools_executed_by must match the node name in workflow.add_node()
Step 2.8: Restart Swisper Backend¶
# If using Docker
docker compose restart backend
# If running locally
# Stop the server (Ctrl+C)
# Start again
uvicorn app.main:app --reload
# Check logs for confirmation
# Should see:
# ✅ SwisperStudio observability initialized
# ✅ LLM prompt capture enabled
# ✅ GlobalSupervisor wrapped with tracing
# ✅ ResearchAgent wrapped with tracing
# ... etc
Part 3: Testing & Verification¶
Step 3.1: Automated Verification¶
Run the deployment verification script:
cd /root/projects/swisper_studio
./scripts/verify_deployment.sh
# Expected output:
# ✅ SwisperStudio Redis is running
# ✅ SwisperStudio Backend is running
# ✅ Redis responds to PING
# ✅ Redis exposed on host port 6380
# ✅ Backend health endpoint OK
# ... etc
Step 3.2: Test Event Flow¶
1. Send test request through Swisper:
curl -X POST http://localhost:8000/api/chat \
-H "Content-Type: application/json" \
-d '{
"message": "Search for Python tutorials"
}'
2. Check events in Redis:
docker exec swisper_studio_redis redis-cli XLEN observability:events
# Should show: 10 (or some number > 0)
3. Check Studio UI:
# Open in browser: http://localhost:3000
# Navigate to: Projects > Your Project > Traces
# Should see your test trace with:
# - Agent execution graph
# - State transitions
# - Tool executions
# - LLM prompts/responses
Step 3.3: Verify Fire-and-Forget¶
Test that Swisper works even if Studio is down:
# 1. Stop Studio backend
docker compose stop backend
# 2. Send request through Swisper
curl -X POST http://localhost:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "Test without Studio"}'
# 3. Swisper should respond normally ✅
# Events will queue in Redis (up to 100k)
# 4. Restart Studio
docker compose start backend
# 5. Studio will process queued events
docker logs swisper_studio_backend | grep "Processing batch"
# Should see: "Processing batch of N events"
Step 3.4: Performance Verification¶
Measure SDK overhead:
# Without SDK (baseline)
time curl -X POST http://localhost:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "Hello"}'
# Record time: ~500ms (example)
# With SDK enabled (should be nearly identical)
# Overhead should be < 2ms per request
Part 4: Production Deployment¶
Step 4.1: Environment-Specific Configuration¶
Development:
Staging:
ENVIRONMENT=staging
LOG_LEVEL=INFO
SWISPER_STUDIO_REDIS_URL=redis://swisper-studio-redis.staging.internal:6379
Production:
ENVIRONMENT=production
LOG_LEVEL=WARNING
SWISPER_STUDIO_REDIS_URL=redis://swisper-studio-redis.prod.internal:6379
Step 4.2: Security Hardening¶
1. Generate strong secrets:
2. Update passwords:
# PostgreSQL password (16+ characters)
openssl rand -base64 16
# Update in docker-compose.yml and .env
3. Configure CORS:
4. Enable HTTPS:
# Add nginx reverse proxy
services:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
Step 4.3: Database Backup Strategy¶
Set up automated backups:
# Add to crontab
0 2 * * * docker exec swisper_studio_postgres pg_dump \
-U studio_user swisper_studio | \
gzip > /backups/swisper_studio_$(date +\%Y\%m\%d).sql.gz
# Retention: Keep 30 days
find /backups -name "swisper_studio_*.sql.gz" -mtime +30 -delete
Step 4.4: Resource Limits¶
Update docker-compose.yml:
services:
redis:
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
postgres:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
backend:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
Step 4.5: Monitoring Setup¶
Add Prometheus metrics:
# apps/backend/swisper/services/metrics.py
from prometheus_client import Counter, Histogram
events_published = Counter(
'swisper_studio_events_published_total',
'Total events published to Redis'
)
event_publish_duration = Histogram(
'swisper_studio_event_publish_duration_seconds',
'Time to publish event to Redis'
)
Export metrics endpoint:
# apps/backend/swisper/api/routes/metrics.py
from fastapi import APIRouter
from prometheus_client import generate_latest
router = APIRouter()
@router.get("/metrics")
async def metrics():
return Response(
generate_latest(),
media_type="text/plain"
)
Step 4.6: Logging Configuration¶
Structured logging:
# apps/backend/swisper/core/logging_config.py
import logging
import json
class JSONFormatter(logging.Formatter):
def format(self, record):
log_data = {
"timestamp": self.formatTime(record),
"level": record.levelname,
"message": record.getMessage(),
"module": record.module,
"function": record.funcName,
}
return json.dumps(log_data)
# Configure
logging.basicConfig(
level=logging.INFO,
handlers=[logging.StreamHandler()],
format='%(message)s'
)
Step 4.7: Health Checks¶
Enhanced health endpoint:
@router.get("/health/detailed")
async def detailed_health():
"""Comprehensive health check"""
health = {
"status": "healthy",
"timestamp": datetime.utcnow().isoformat(),
"version": "0.1.0",
"components": {}
}
# Check database
try:
await db.execute("SELECT 1")
health["components"]["database"] = {"status": "up"}
except Exception as e:
health["components"]["database"] = {"status": "down", "error": str(e)}
health["status"] = "degraded"
# Check Redis
try:
await redis.ping()
health["components"]["redis"] = {"status": "up"}
except Exception as e:
health["components"]["redis"] = {"status": "down", "error": str(e)}
health["status"] = "degraded"
# Check consumer
try:
heartbeat = await redis.get("swisper_studio:consumer:heartbeat")
if heartbeat:
health["components"]["consumer"] = {"status": "up"}
else:
health["components"]["consumer"] = {"status": "down"}
health["status"] = "degraded"
except Exception as e:
health["components"]["consumer"] = {"status": "unknown"}
return health
Part 5: Monitoring & Operations¶
Step 5.1: Key Metrics to Monitor¶
| Metric | Target | Alert Threshold |
|---|---|---|
| Stream length | < 50k | > 80k (warning) |
| Redis memory | < 400MB | > 450MB (critical) |
| Consumer lag | < 1 min | > 5 min (critical) |
| Publish latency | < 2ms | > 10ms (warning) |
| Backend CPU | < 70% | > 85% (warning) |
| Backend memory | < 80% | > 90% (critical) |
| DB connections | < 80 | > 90 (warning) |
Step 5.2: Prometheus Queries¶
# Stream length
swisper_studio_stream_length{stream="observability:events"}
# Consumer lag
swisper_studio_consumer_lag_seconds
# Event publish rate
rate(swisper_studio_events_published_total[5m])
# P99 publish latency
histogram_quantile(0.99,
rate(swisper_studio_event_publish_duration_seconds_bucket[5m])
)
Step 5.3: Grafana Dashboard¶
Import dashboard JSON:
{
"dashboard": {
"title": "SwisperStudio Observability",
"panels": [
{
"title": "Event Publish Rate",
"targets": [{
"expr": "rate(swisper_studio_events_published_total[5m])"
}]
},
{
"title": "Stream Length",
"targets": [{
"expr": "swisper_studio_stream_length"
}]
},
{
"title": "P99 Latency",
"targets": [{
"expr": "histogram_quantile(0.99, rate(swisper_studio_event_publish_duration_seconds_bucket[5m]))"
}]
}
]
}
}
Step 5.4: Alerts¶
Alertmanager rules:
groups:
- name: swisper_studio
rules:
- alert: StreamNearCapacity
expr: swisper_studio_stream_length > 80000
for: 5m
labels:
severity: warning
annotations:
summary: "Stream near capacity ({{ $value }} / 100k)"
- alert: ConsumerDown
expr: absent(swisper_studio_consumer_heartbeat) == 1
for: 2m
labels:
severity: critical
annotations:
summary: "Consumer heartbeat missing"
- alert: HighPublishLatency
expr: histogram_quantile(0.99, rate(swisper_studio_event_publish_duration_seconds_bucket[5m])) > 0.01
for: 5m
labels:
severity: warning
annotations:
summary: "P99 latency > 10ms"
Step 5.5: Operational Runbooks¶
Runbook 1: Consumer Down
# 1. Check if consumer is running
docker logs swisper_studio_backend | grep consumer
# 2. Check for errors
docker logs swisper_studio_backend | grep ERROR
# 3. Restart backend
docker compose restart backend
# 4. Verify recovery
curl http://localhost:8001/health/detailed
Runbook 2: Stream Near Capacity
# 1. Check stream length
docker exec swisper_studio_redis redis-cli XLEN observability:events
# 2. Check consumer lag
docker logs swisper_studio_backend | tail -100
# 3. If consumer stuck, restart
docker compose restart backend
# 4. If persistent, check DB performance
docker exec swisper_studio_postgres pg_stat_activity
Runbook 3: High Memory Usage
# 1. Check Redis memory
docker exec swisper_studio_redis redis-cli INFO memory
# 2. Check stream length
docker exec swisper_studio_redis redis-cli XLEN observability:events
# 3. If needed, trim stream (CAUTION: data loss)
docker exec swisper_studio_redis redis-cli XTRIM observability:events MAXLEN 50000
# 4. Monitor recovery
watch docker stats swisper_studio_redis
Troubleshooting¶
Issue 1: Swisper Cannot Connect to Studio Redis¶
Symptoms:
Solution:
# 1. Check Studio Redis is running
docker ps | grep swisper_studio_redis
# 2. Check port exposure
docker port swisper_studio_redis
# Should show: 6379/tcp -> 0.0.0.0:6380
# 3. Test from host
redis-cli -h 127.0.0.1 -p 6380 ping
# Should return: PONG
# 4. Find Docker host IP
docker network inspect bridge | grep Gateway
# Use this IP in SWISPER_STUDIO_REDIS_URL
# 5. Update Swisper config
SWISPER_STUDIO_REDIS_URL=redis://<GATEWAY_IP>:6380
Issue 2: Events Not Appearing in UI¶
Symptoms: - Events in Redis but not in Studio UI - Consumer not processing events
Solution:
# 1. Check events are in Redis
docker exec swisper_studio_redis redis-cli XLEN observability:events
# Should be > 0
# 2. Check Studio backend is running
docker ps | grep swisper_studio_backend
# 3. Check consumer logs
docker logs swisper_studio_backend | grep "Processing batch"
# Should see periodic processing
# 4. Check for errors
docker logs swisper_studio_backend | grep ERROR
# 5. If no processing, restart
docker compose restart backend
# 6. Verify project ID matches
# In Swisper config vs Studio UI
Issue 3: High Latency¶
Symptoms: - Publish latency > 10ms - Slow Swisper response times
Solution:
# 1. Check if Redis is overloaded
docker exec swisper_studio_redis redis-cli INFO stats
# Look for: instantaneous_ops_per_sec
# 2. Check network latency
docker exec swisper-backend ping -c 10 172.17.0.1
# 3. Check if Studio Redis is in same data center
# If cross-DC, implement bridge relay (see architecture docs)
# 4. Verify MAXLEN is set in SDK
# Should be 100k in SDK initialization
# 5. Scale Redis if needed
# Add read replicas or increase resources
Issue 4: Database Performance¶
Symptoms: - Slow UI queries - Consumer lag increasing - High DB CPU
Solution:
# 1. Check slow queries
docker exec swisper_studio_postgres psql -U studio_user -d swisper_studio -c \
"SELECT query, calls, total_time FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;"
# 2. Check DB size
docker exec swisper_studio_postgres psql -U studio_user -d swisper_studio -c \
"SELECT pg_size_pretty(pg_database_size('swisper_studio'));"
# 3. Check indexes
docker exec swisper_studio_postgres psql -U studio_user -d swisper_studio -c \
"SELECT schemaname, tablename, indexname FROM pg_indexes WHERE schemaname = 'public';"
# 4. Run VACUUM if needed
docker exec swisper_studio_postgres psql -U studio_user -d swisper_studio -c \
"VACUUM ANALYZE;"
# 5. Consider partitioning (for large datasets)
# Partition traces table by date
Reference¶
Environment Variables Reference¶
| Variable | Required | Default | Description |
|---|---|---|---|
SWISPER_STUDIO_ENABLED |
No | true |
Enable/disable observability |
SWISPER_STUDIO_REDIS_URL |
Yes | - | Redis connection URL |
SWISPER_STUDIO_PROJECT_ID |
Yes | - | Studio project UUID |
SWISPER_STUDIO_STREAM_NAME |
No | observability:events |
Redis stream name |
SWISPER_STUDIO_CAPTURE_REASONING |
No | true |
Capture LLM reasoning |
DATABASE_URL |
Yes | - | PostgreSQL connection string |
SECRET_KEY |
Yes | - | JWT signing key |
API_KEY |
Yes | - | API authentication key |
CORS_ORIGINS |
No | [] |
Allowed CORS origins |
LOG_LEVEL |
No | INFO |
Logging level |
Port Reference¶
| Service | Internal Port | External Port | Purpose |
|---|---|---|---|
| Studio Redis | 6379 | 6380 | Observability events |
| Studio PostgreSQL | 5432 | 5433 | Trace storage |
| Studio Backend | 8000 | 8001 | API server |
| Studio Frontend | 3000 | 3000 | Development UI |
File Locations¶
swisper_studio/
├── docker-compose.yml # Service orchestration
├── .env # Environment config
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI app
│ │ ├── core/config.py # Configuration
│ │ └── services/ # Business logic
│ ├── alembic/ # DB migrations
│ └── Dockerfile
├── frontend/
│ ├── src/ # React app
│ ├── package.json
│ └── vite.config.ts
├── docs/
│ ├── architecture/ # Architecture docs
│ ├── deployment/ # Deployment guides
│ └── guides/ # Integration guides
└── scripts/
└── verify_deployment.sh # Verification script
Command Reference¶
# Deployment
docker compose up -d # Start all services
docker compose down # Stop all services
docker compose restart backend # Restart backend
docker compose logs -f backend # Follow backend logs
# Database
alembic upgrade head # Run migrations
alembic downgrade -1 # Rollback one migration
pg_dump -U studio_user swisper_studio # Backup database
# Redis
redis-cli -h 127.0.0.1 -p 6380 XLEN observability:events # Stream length
redis-cli -h 127.0.0.1 -p 6380 INFO memory # Memory usage
redis-cli -h 127.0.0.1 -p 6380 FLUSHALL # Clear all data (DANGER!)
# Health Checks
curl http://localhost:8001/health # Basic health
curl http://localhost:8001/health/detailed # Detailed health
docker exec swisper_studio_redis redis-cli ping # Redis health
docker exec swisper_studio_postgres pg_isready # PostgreSQL health
# Verification
./scripts/verify_deployment.sh # Full verification
Additional Documentation¶
- SDK Integration:
docs/guides/swisper_studio_sdk_integration_guide.md - Architecture:
docs/architecture/redis_separation_architecture.md - Configuration:
docs/deployment/swisper_backend_configuration.md - Quick Reference:
docs/deployment/configuration_quick_reference.md - Deployment Summary:
DEPLOYMENT_SUMMARY.md - Team Instructions:
SWISPER_TEAM_INSTRUCTIONS.md
Support¶
Questions or Issues?
- Check documentation in
docs/directory - Review troubleshooting section above
- Check GitHub issues
- Contact SwisperStudio team
Changelog¶
v1.0 - 2025-11-20¶
- Initial comprehensive guide
- Covers setup, deployment, testing, production
- Includes monitoring and operations
- Complete troubleshooting guide
Document Status: ✅ Production Ready
Last Reviewed: 2025-11-20
Next Review: 2025-12-20