Troubleshooting SSE streaming
This guide helps diagnose and resolve common issues with SSE (Server-Sent Events) streaming for real-time operation tracking.
Table of Contents
Section titled “Table of Contents”- Connection Failures
- Missed Events (Gap Events)
- High Memory Usage
- Slow Clients
- Metrics Interpretation
- Log Analysis
Connection Failures
Section titled “Connection Failures”Symptom
Section titled “Symptom”Client cannot connect to SSE endpoint:
GET /api/method/shc.operation.stream/{operation_id}→ 404 Not FoundCauses
Section titled “Causes”- Operation expired: Operation completed >5 minutes ago and was cleaned up
- Invalid operation_id: Wrong operation_id or typo
- Server restart: Operations lost (stored in memory, not persisted)
Resolution
Section titled “Resolution”# Check if operation existsGET /api/method/shc.operation.state/{operation_id}
# If 404, query current stack state insteadGET /api/stacks/{tenant}/{stack}/{environment}/statusPrevention:
- Reduce
sse.operation_ttlif clients need longer replay windows - Persist operations to database (future enhancement)
Missed Events (Gap Events)
Section titled “Missed Events (Gap Events)”Symptom
Section titled “Symptom”Client receives a gap event:
{ "event_type": "gap", "sequence": 99, "missing_sequences": [50, 51, 52, ..., 99], "message": "Missed 50 events. Query current state to resync."}Causes
Section titled “Causes”- Slow client: Client couldn’t process events fast enough, buffer overflowed
- Network disruption: Client disconnected for too long
- Small buffer:
sse.buffer_sizetoo small for operation event rate
Resolution
Section titled “Resolution”Client-side:
if event.EventType == "gap" { // Query current state from database state, _ := api.GetStackStatus(ctx, tenant, stack, env) updateDisplay(state) // Continue streaming (already at latest buffer)}Server-side:
- Increase
sse.buffer_sizeinconfig.yaml(default: 1000) - Check metrics:
shc_sse_slow_clients_total
Prevention:
- Size buffer for expected event rate:
events_per_operation × 2 - Example: 50 containers × 5 events each = 250 events → buffer_size: 500
High Memory Usage
Section titled “High Memory Usage”Symptom
Section titled “Symptom”Alert: SSEHighMemoryUsage fires
shc_sse_memory_bytes > 100MBCauses
Section titled “Causes”- Too many operations: More than 100 concurrent long-running operations
- Large buffer size:
sse.buffer_sizetoo high - Operations not cleaning up: Bug preventing cleanup
Resolution
Section titled “Resolution”Check current usage:
# Query Prometheusshc_sse_memory_bytesshc_sse_operations{status="running"}Tune configuration:
sse: buffer_size: 500 # Reduce from 1000 max_operations: 500 # Reduce from 1000 operation_ttl: 180 # Reduce from 300Emergency cleanup:
- Emergency cleanup triggers automatically at limit
- Removes oldest 25% of completed operations
- Running operations are NOT affected
Prevention:
- Set buffer_size based on workload
- Monitor
shc_sse_operationsregularly
Slow Clients
Section titled “Slow Clients”Symptom
Section titled “Symptom”Metric increasing: shc_sse_slow_clients_total
Logs show:
[WARN] SSE buffer near full for operation abc-123Causes
Section titled “Causes”- Network latency: Slow network between client and server
- Client processing: Client can’t process events fast enough
- Server overload: Too many concurrent operations
Resolution
Section titled “Resolution”Check client:
- Profile client event processing
- Add async processing if blocking
- Reduce display refresh rate
Check network:
# Test latencycurl -w "@curl-format.txt" http://server/api/method/shc.operation.stream/{operation_id}Check server:
# Check concurrent operationsshc_sse_operations{status="running"}
# Check event emission raterate(shc_sse_events_emitted_total[1m])Prevention:
- Clients should process events asynchronously
- Batch display updates (max 10 Hz)
- Filter unnecessary events client-side
Metrics Interpretation
Section titled “Metrics Interpretation”Key Metrics
Section titled “Key Metrics”Connection Metrics
Section titled “Connection Metrics”# Active connections by operation typeshc_sse_connections{operation_type="install"}
# Alert when approaching limitshc_sse_connections > 450 # 90% of 500 defaultEvent Metrics
Section titled “Event Metrics”# Events emitted per secondrate(shc_sse_events_emitted_total[5m])
# Events by typerate(shc_sse_events_emitted_total{event_type="container_status"}[5m])Performance Metrics
Section titled “Performance Metrics”# Event latency (p95)histogram_quantile(0.95, rate(shc_sse_event_latency_seconds_bucket[5m]))
# Slow clients detectedrate(shc_sse_slow_clients_total[5m])Healthy Baselines
Section titled “Healthy Baselines”| Metric | Healthy Range | Warning Threshold |
|---|---|---|
| Event latency (p95) | <100ms | >1s |
| Slow clients | 0/min | >5/min |
| Memory usage | <50MB | >100MB |
| Connection count | <300 | >450 |
| Event drop rate | 0/sec | >1/sec |
Log Analysis
Section titled “Log Analysis”Useful Log Filters
Section titled “Useful Log Filters”Operation lifecycle:
# Operations createdgrep "Operation created" shc.log
# Operations completedgrep "Operation completed" shc.log
# Operations failedgrep "Operation failed" shc.logSSE events:
# Event emissions (DEBUG level)grep "SSE event emitted" shc.log
# Gap detectionsgrep "Gap detected" shc.log
# Memory warningsgrep "SSE memory usage" shc.logClient connections:
# New connectionsgrep "Client reconnecting" shc.log
# Connection errorsgrep "Too many concurrent SSE connections" shc.logLog Levels
Section titled “Log Levels”- DEBUG: Event emissions, reconnections, cache cleanup
- INFO: Operation lifecycle, stack status changes
- WARN: Buffer near full, memory limit approaching
- ERROR: Operation failures, cleanup errors
Example Log Entry
Section titled “Example Log Entry”{ "level": "INFO", "message": "Operation created: install", "operation_id": "abc-123-def", "operation_type": "install", "timestamp": "2026-01-24T12:00:00.123Z"}Common Scenarios
Section titled “Common Scenarios”Scenario 1: Client Missed Events During Network Outage
Section titled “Scenario 1: Client Missed Events During Network Outage”Problem: Client disconnected for 2 minutes, received gap event on reconnect
Solution:
- Client queries
/api/stacks/{tenant}/{stack}/{env}/status - Updates display with current state
- Continues streaming from current sequence
- ✅ No action needed server-side
Scenario 2: Memory Alert Fires During Large Deployment
Section titled “Scenario 2: Memory Alert Fires During Large Deployment”Problem: Deploying 100-container stack triggered memory alert
Solution:
- Emergency cleanup triggered automatically (oldest 25% removed)
- Large deployments generate many events
- Consider increasing buffer:
sse.max_memory_mb: 200 - Or reduce buffer size per operation:
sse.buffer_size: 500
Scenario 3: Too Many Concurrent Operations
Section titled “Scenario 3: Too Many Concurrent Operations”Problem: 1000+ operations tracked, server slowing down
Root Cause: Operations not completing or cleanup not running
Solution:
# Check operation cleanup taskgrep "Cleaned up" shc.log
# Manually trigger cleanup via API (future enhancement)# POST /api/admin/sse/cleanup
# Restart server to clear all operationssystemctl restart shcScenario 4: Events Not Appearing in SSE Stream
Section titled “Scenario 4: Events Not Appearing in SSE Stream”Problem: Client connected, but not receiving container/service events
Checklist:
- ✅ Is SSE enabled? Check
config.yaml→sse.enabled: true - ✅ Is operation_id set? Check operation context in compose operations
- ✅ Are events being emitted? Check
shc_sse_events_emitted_totalmetric - ✅ Is client parsing events correctly? Check event_type field
Debug:
# Enable DEBUG loggingexport SHC_LOG_LEVEL=DEBUG
# Check if events are being routedgrep "SSE event emitted" shc.log | grep "operation_id=YOUR_OP_ID"Feature Flags
Section titled “Feature Flags”Disable SSE
Section titled “Disable SSE”If SSE is causing issues, disable it:
sse: enabled: falseThen restart server:
systemctl restart shcClients will use DB polling (DeploymentTracker) instead of SSE.
Gradual Rollout
Section titled “Gradual Rollout”Enable SSE for specific operations only:
// In code (future enhancement)import "gitlab.com/bitspur/selfhosted-cloud/ce/modules/app"if config.SSEEnabled && (operationType == "install" || operationType == "backup") { context.SetOperation(operationID)}Getting Help
Section titled “Getting Help”If this guide doesn’t resolve your issue:
-
Check metrics in Grafana
-
Collect logs (DEBUG level for 5 minutes)
-
Run diagnostics:
Terminal window # Check active operationscurl http://localhost:8000/api/method/shc.health.get# Check memory usageps aux | grep shc -
File issue with:
- Log excerpt (DEBUG level)
- Metrics snapshot
- Reproduction steps