Skip to content

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

  1. Overview
  2. Architecture
  3. Prerequisites
  4. Part 1: SwisperStudio Deployment
  5. Part 2: Swisper Backend Integration
  6. Part 3: Testing & Verification
  7. Part 4: Production Deployment
  8. Part 5: Monitoring & Operations
  9. Troubleshooting
  10. 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

  1. Isolation - SwisperStudio has its own infrastructure (Redis, DB, services)
  2. Fire-and-Forget - Swisper publishes events without waiting (1-2ms)
  3. Graceful Degradation - Swisper works even if Studio is down
  4. 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:

# SwisperStudio Observability
swisper-studio-sdk==0.5.0

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:

ENVIRONMENT=development
LOG_LEVEL=DEBUG
SWISPER_STUDIO_REDIS_URL=redis://172.17.0.1:6380

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:

# SECRET_KEY (64 characters)
openssl rand -base64 48

# API_KEY
openssl rand -hex 32

2. Update passwords:

# PostgreSQL password (16+ characters)
openssl rand -base64 16

# Update in docker-compose.yml and .env

3. Configure CORS:

# Only allow your domains
CORS_ORIGINS='["https://swisper-studio.fintama.com"]'

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:

⚠️ SwisperStudio initialization failed: Connection refused

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?

  1. Check documentation in docs/ directory
  2. Review troubleshooting section above
  3. Check GitHub issues
  4. 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