title, description, template, version, last_updated, author, tags, categories, difficulty, prerequisites, related_docs, dependencies, llm_context, search_keywords
| title | description | template | version | last_updated | author | tags | categories | difficulty | prerequisites | related_docs | dependencies | llm_context | search_keywords | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| SystemMonitor Architecture and Operations Guide | Comprehensive guide to SystemMonitor implementation, deployment, and troubleshooting | TEMPLATE.documentation-standard | 2.1.0 | 2025-10-07 | Sirius Development Team |
|
|
intermediate |
|
|
|
high |
|
SystemMonitor Architecture and Operations Guide
Overview
The SystemMonitor is a critical component that provides real-time system resource monitoring for all Sirius containers. It collects CPU, memory, network, disk, and process metrics from within containerized environments and stores them in Valkey for centralized monitoring and alerting.
Key Features:
- Real-time metrics collection every 5 seconds
- Support for both development (
go run) and production (binary) modes - Multi-architecture support (amd64, arm64)
- CPU drift-free monitoring with time-based calculations
- Automatic fallback mechanisms for missing metrics
Architecture
Core Components
1. Main SystemMonitor Project
- Location:
/minor-projects/app-system-monitor/ - Language: Go 1.23
- Purpose: Single source of truth for all SystemMonitor implementations
- Dependencies:
github.com/SiriusScan/go-apifor Valkey connectivity
2. Deployment Modes
Development Mode:
- Uses
go run main.goto run SystemMonitor from source - Automatically picks up code changes without rebuild
- Enabled when
GO_ENV=developmentenvironment variable is set - Used in sirius-engine and sirius-ui development containers
Production Mode:
- Uses pre-compiled binary built from GitHub source
- Compiled during Docker image build process
- Better performance and smaller runtime footprint
- Used in all production deployments
3. Container Integration
All Containers (PostgreSQL, RabbitMQ, Valkey, Engine, UI):
- Build SystemMonitor from GitHub source during Docker image build
- Use multi-stage build to compile from
github.com/SiriusScan/app-system-monitor - Copy compiled binary to final image
- Start SystemMonitor alongside main service
Development Mode (Engine, UI):
- Volume-mount
../minor-projects/app-system-monitorfor live development - Run with
go run main.goinstead of binary - Enables rapid iteration without container rebuilds
SystemMonitor Implementation
CPU Monitoring (Fixed in v2.0)
The SystemMonitor uses a sophisticated CPU utilization calculation that eliminates drift:
// Time-based CPU utilization calculation
cpuPercent := (float64(cpuDiff) / 1000000.0) / timeDiff / float64(sm.cpuCores) * 100.0
Key Features:
- State Tracking: Maintains previous CPU usage and timestamp
- Core Detection: Automatically detects available CPU cores from cgroups
- Drift Prevention: Uses time-based differences instead of cumulative values
- Architecture Support: Works across different CPU architectures
Memory Monitoring
Uses cgroups v2 for accurate container memory metrics:
// Read from cgroups v2
currentBytes := readCgroupFile("/sys/fs/cgroup/memory.current")
maxBytes := readCgroupFile("/sys/fs/cgroup/memory.max")
percent := float64(currentBytes) / float64(maxBytes) * 100.0
Network Monitoring
Tracks network I/O from container interfaces:
// Network statistics
rxBytes := readCgroupFile("/sys/class/net/eth0/statistics/rx_bytes")
txBytes := readCgroupFile("/sys/class/net/eth0/statistics/tx_bytes")
Disk Monitoring
Calculates container filesystem usage:
// Walk container filesystem (excluding mounted volumes)
filepath.WalkDir("/", func(path string, d os.DirEntry, err error) error {
// Skip mounted volumes and system directories
if strings.HasPrefix(path, "/api") || strings.HasPrefix(path, "/proc") {
return filepath.SkipDir
}
// Calculate total size
})
Deployment Architecture
Build Process
Production Builds (All Containers)
All containers use a multi-stage Docker build to compile SystemMonitor from source:
# Builder stage - Clone and build SystemMonitor
FROM golang:1.23-alpine AS builder
RUN apk add --no-cache git
RUN git clone https://github.com/SiriusScan/app-system-monitor.git && \
cd app-system-monitor && \
go mod download && \
CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o system-monitor main.go
# Runtime stage - Copy binary
FROM <base-image>
COPY --from=builder /go/app-system-monitor/system-monitor /usr/local/bin/system-monitor
RUN chmod +x /usr/local/bin/system-monitor
Benefits:
- Always builds from latest source code
- No pre-compiled binary distribution needed
- Architecture-specific compilation
- Smaller final image size
Development Mode (Engine & UI)
Development containers use go run for live development:
# docker-compose.dev.yaml
volumes:
- ../minor-projects/app-system-monitor:/system-monitor
environment:
- GO_ENV=development
Startup logic checks environment:
if [ "$GO_ENV" = "development" ] && [ -f "/system-monitor/main.go" ]; then
CONTAINER_NAME=sirius-engine go run main.go &
elif [ -f "/system-monitor/system-monitor" ] && [ -x "/system-monitor/system-monitor" ]; then
CONTAINER_NAME=sirius-engine ./system-monitor &
fi
Container Startup Integration
PostgreSQL/RabbitMQ/Valkey Pattern (Production Only)
# In start-with-monitor.sh
echo "📊 Starting system monitor..."
cd /usr/local/bin
CONTAINER_NAME=sirius-postgres ./system-monitor &
These containers always use the compiled binary from the Docker build.
Engine Pattern (Development & Production)
# In start-enhanced.sh
if [ -d "/system-monitor" ]; then
echo "Starting system monitor..."
cd /system-monitor
if [ "$GO_ENV" = "development" ] && [ -f "main.go" ]; then
echo "Running system monitor with go run (development mode)"
CONTAINER_NAME=sirius-engine go run main.go &
elif [ -f "./system-monitor" ] && [ -x "./system-monitor" ]; then
echo "Running system monitor binary (production mode)"
CONTAINER_NAME=sirius-engine ./system-monitor &
else
echo "Error: System monitor not found (neither main.go nor binary)"
exit 1
fi
SYSTEM_MONITOR_PID=$!
sleep 2
check_service "System Monitor" $SYSTEM_MONITOR_PID
fi
Key Features:
- Checks
GO_ENVenvironment variable - Prefers
go runin development mode - Falls back to binary in production
- Provides clear error messages if neither is available
UI Pattern (Development & Production)
# In start-dev.sh
if [ -d "/system-monitor" ] && [ -f "/system-monitor/main.go" ]; then
echo "📊 Starting System Monitor..."
cd /system-monitor
CONTAINER_NAME=sirius-ui go run main.go &
SYSTEM_MONITOR_PID=$!
echo "✅ System Monitor started with PID: $SYSTEM_MONITOR_PID"
cd /app
fi
# In start-prod.sh
if [ -f "/system-monitor/system-monitor" ] && [ -x "/system-monitor/system-monitor" ]; then
echo "📊 Starting system monitor..."
cd /system-monitor
CONTAINER_NAME=sirius-ui ./system-monitor &
SYSTEM_MONITOR_PID=$!
echo "✅ System monitor started with PID: $SYSTEM_MONITOR_PID"
cd /app
fi
Configuration
Environment Variables
| Variable | Purpose | Default | Example |
|---|---|---|---|
CONTAINER_NAME |
Container identifier | unknown |
sirius-postgres |
VALKEY_HOST |
Valkey server hostname | sirius-valkey |
localhost |
VALKEY_PORT |
Valkey server port | 6379 |
6379 |
Metrics Storage
Valkey Keys:
system:metrics:{container_name}- Latest metricssystem:logs:{container_name}:{timestamp}- Log entries
Metrics Structure:
{
"container_name": "sirius-postgres",
"timestamp": "2025-01-07T12:00:00Z",
"cpu_percent": 15.2,
"memory_usage_bytes": 67108864,
"memory_percent": 1.8,
"network_rx_bytes": 1048576,
"network_tx_bytes": 524288,
"disk_usage_bytes": 134217728,
"disk_percent": 1.3,
"process_count": 12,
"file_descriptors": 45,
"load_average_1m": 0.15,
"load_average_5m": 0.12,
"load_average_15m": 0.1,
"uptime_seconds": 3600,
"status": "running"
}
Troubleshooting Guide
Common Issues and Solutions
1. SystemMonitor Not Starting / Exec Format Error
Symptoms:
- Container starts but no metrics appear in monitoring dashboard
- Logs show "System Monitor failed to start or crashed"
- "cannot execute binary file: Exec format error" (most common in development mode)
- Container stuck in crash loop restarting every few seconds
Most Likely Causes:
-
Development Mode Binary Mismatch (95% of cases):
- Volume-mounted
/system-monitorcontains pre-compiled binary for wrong architecture - Development container trying to execute x86_64 binary on ARM64 (or vice versa)
- Solution: Use
go runinstead of pre-compiled binary
- Volume-mounted
-
Missing Binary: SystemMonitor binary not present in container
-
Permission Issues: Binary not executable
-
Go Not Available: Development mode but Go not installed in container
Diagnostic Steps:
# Check if binary exists and architecture
docker exec <container> ls -la /system-monitor/
docker exec <container> file /system-monitor/system-monitor
# Check container architecture
docker exec <container> uname -m
# Check if Go is available (for development mode)
docker exec <container> which go
docker exec <container> go version
# Check environment mode
docker exec <container> env | grep GO_ENV
# Check container logs for startup mode
docker logs <container> | grep -i "system monitor\|go run\|development"
Solutions:
For Development Mode (Engine/UI):
-
Verify startup script uses
go run:# Check if start-enhanced.sh or start-dev.sh has: if [ "$GO_ENV" = "development" ] && [ -f "main.go" ]; then go run main.go & fi -
Rebuild container to pick up updated startup script:
docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml build <service> docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml up -d <service> -
Verify development environment is set:
# In docker-compose.dev.yaml environment: - GO_ENV=development
For Production Mode:
-
Rebuild container (rebuilds SystemMonitor from source):
docker-compose build <service> docker-compose up -d <service> -
Verify Dockerfile has multi-stage build:
FROM golang:1.23-alpine AS builder RUN git clone https://github.com/SiriusScan/app-system-monitor.git # ... build steps ...
2. CPU Utilization Drift
Symptoms:
- CPU usage gradually increases over time
- Metrics don't match Docker's performance data
- CPU percentages exceed 100%
Root Cause:
- Old SystemMonitor versions used cumulative CPU time incorrectly
- Missing time-based calculation logic
Solution:
- Ensure using SystemMonitor v2.0+ with proper CPU calculation
- Verify
lastCPUUsageandlastCPUTimestate tracking
3. Valkey Connection Issues
Symptoms:
- SystemMonitor starts but metrics not stored
- "Error storing metrics" in logs
- Empty metrics in monitoring dashboard
Diagnostic Steps:
# Check Valkey connectivity
docker exec <container> nc -zv sirius-valkey 6379
# Check Valkey logs
docker logs sirius-valkey
# Test Valkey connection from container
docker exec <container> redis-cli -h sirius-valkey ping
Solutions:
- Network Issues: Check Docker network connectivity
- Valkey Down: Restart Valkey container
- Firewall: Check port 6379 accessibility
4. Service Crash Loop Due to Scanner/Other Service Failures
Symptoms:
- SystemMonitor starts successfully but then container restarts
- Logs show "Scanner failed to start or crashed"
- Container repeatedly cycles through startup sequence
- SystemMonitor unable to maintain connection
Root Cause:
- In early implementations, any service failure (like scanner) would trigger
cleanupfunction - This shutdown ALL services including SystemMonitor
- Created unnecessary crash loops when only one service had issues
Solution (Implemented in v2.1):
The scanner and other non-critical services are now non-fatal:
# In start-enhanced.sh
if [ -n "$SCANNER_PATH" ]; then
cd "$SCANNER_PATH"
echo "Starting scanner service..."
go run main.go &
SCANNER_PID=$!
sleep 2
# Check if scanner started, but don't fail if it didn't
if ! kill -0 $SCANNER_PID 2>/dev/null; then
echo "Warning: Scanner failed to start, but continuing with other services"
SCANNER_PID=""
fi
fi
Key Changes:
- Scanner failure no longer calls
cleanupfunction - Other services (SystemMonitor, Terminal, Agent) continue running
- Warning logged but container remains operational
- Allows investigation of scanner issues without affecting monitoring
5. Memory Metrics Inaccurate
Symptoms:
- Memory usage doesn't match container limits
- Memory percentage calculations seem wrong
Diagnostic Steps:
# Check cgroups v2 files
docker exec <container> cat /sys/fs/cgroup/memory.current
docker exec <container> cat /sys/fs/cgroup/memory.max
# Compare with Docker stats
docker stats <container> --no-stream
Solutions:
- Cgroups v2: Ensure container supports cgroups v2
- Fallback Values: Check if using fallback memory estimates
- Container Limits: Verify memory limits are set correctly
Performance Issues
High CPU Usage from SystemMonitor
Symptoms:
- SystemMonitor itself consuming significant CPU
- Container performance degraded
Causes:
- Frequent Polling: Metrics collection interval too short
- Inefficient Calculations: Complex disk usage calculations
- Memory Leaks: Go runtime issues
Solutions:
- Adjust Polling: Increase collection interval (default: 5 seconds)
- Optimize Disk Scanning: Limit filesystem traversal
- Memory Profiling: Use Go profiling tools
Memory Leaks
Symptoms:
- SystemMonitor memory usage grows over time
- Container memory limits exceeded
Diagnostic Steps:
# Monitor SystemMonitor memory usage
docker exec <container> ps aux | grep system-monitor
# Check for goroutine leaks
docker exec <container> curl http://localhost:6060/debug/pprof/goroutine
Log Analysis
SystemMonitor Logs
Location: Container stdout/stderr Format: Standard Go log format
Key Log Messages:
"Starting system monitor for container: {name}"- Successful startup"Error reading cpu.stat: {error}"- CPU monitoring issues"Error storing metrics: {error}"- Valkey connectivity problems"Warning: metrics channel full, dropping metrics"- Performance issues
Log Patterns for Issues
# CPU monitoring problems
grep -i "cpu.stat\|cpu.max" <container_logs>
# Memory monitoring issues
grep -i "memory.current\|memory.max" <container_logs>
# Network connectivity
grep -i "valkey\|redis" <container_logs>
# Performance warnings
grep -i "channel full\|dropping" <container_logs>
Maintenance and Updates
Updating SystemMonitor
For Development Mode (Local Changes)
-
Modify Source Code:
cd /minor-projects/app-system-monitor/ # Make changes to main.go -
Test Changes (no rebuild needed in development mode):
# Restart container to pick up changes docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml restart sirius-engine # SystemMonitor will recompile with go run on startup -
Verify Changes:
# Check logs for SystemMonitor startup docker logs sirius-engine | grep -i "system monitor" # Verify metrics in Valkey docker exec sirius-valkey redis-cli get "system:metrics:sirius-engine"
For Production Deployment
-
Push Changes to GitHub:
cd /minor-projects/app-system-monitor/ git add . git commit -m "feat(monitoring): update SystemMonitor metrics" git push origin main -
Rebuild All Containers (they fetch latest from GitHub):
# Full rebuild with no cache to get latest source docker-compose build --no-cache sirius-postgres sirius-rabbitmq sirius-valkey sirius-engine sirius-ui -
Deploy Updates:
docker-compose up -d
Testing in Development Before Production
- Make changes locally in
/minor-projects/app-system-monitor/ - Test in development mode with
docker-compose.dev.yaml - Verify metrics are collecting correctly
- Commit and push to GitHub
- Rebuild production images to fetch from GitHub
- Deploy to production
Monitoring SystemMonitor Health
Health Check Endpoints
Valkey Metrics Check:
# Check if metrics are being stored
redis-cli -h sirius-valkey get "system:metrics:sirius-postgres"
Container Process Check:
# Verify SystemMonitor is running
docker exec <container> ps aux | grep system-monitor
Automated Monitoring
Metrics Collection Frequency: Every 5 seconds Log Generation: Every 30 seconds Health Check: Monitor Valkey key updates
Development Guidelines
Adding New Metrics
-
Update SystemMetrics struct:
type SystemMetrics struct { // ... existing fields ... NewMetric float64 `json:"new_metric"` } -
Implement Collection Logic:
func (sm *SystemMonitor) readNewMetric() float64 { // Implementation } -
Update gatherSystemMetrics:
return SystemMetrics{ // ... existing fields ... NewMetric: sm.readNewMetric(), }
Testing Changes
-
Local Testing:
cd /minor-projects/app-system-monitor/ go run main.go -
Container Testing:
# Build and test in container docker run --rm -it <container_image> /usr/local/bin/system-monitor -
Integration Testing:
# Deploy to development environment docker-compose -f docker-compose.dev.yaml up -d
Security Considerations
Container Security
- Non-root Execution: SystemMonitor runs with container user permissions
- Read-only Access: Only reads system files, no write access
- Network Isolation: Communicates only with Valkey service
Data Privacy
- No Sensitive Data: Only collects system resource metrics
- Local Processing: All calculations performed within container
- Encrypted Transport: Valkey connections should use TLS in production
Performance Tuning
Optimization Settings
Collection Intervals:
- Metrics: 5 seconds (configurable)
- Logs: 30 seconds (configurable)
Resource Limits:
- CPU: Minimal impact (< 0.1% typical)
- Memory: ~10-20MB per container
- Network: Minimal bandwidth usage
Scaling Considerations
- Container Count: Linear scaling with container count
- Valkey Load: Minimal impact on Valkey performance
- Network Overhead: Negligible for typical deployments
Support and Escalation
First-Level Support
- Check Container Status:
docker ps - Review Logs:
docker logs <container> - Verify Network: Test Valkey connectivity
- Check Metrics: Verify Valkey key updates
Escalation Path
- Development Team: For SystemMonitor code issues
- Infrastructure Team: For container/Docker issues
- Database Team: For Valkey connectivity problems
Emergency Procedures
SystemMonitor Down:
- Check container health
- Restart affected containers
- Verify Valkey connectivity
- Check for resource constraints
Metrics Not Updating:
- Verify SystemMonitor process running
- Check Valkey connectivity
- Review container logs
- Test manual metric collection
Quick Reference
Essential Commands
# Development Mode - Restart to pick up changes
docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml restart sirius-engine sirius-ui
# Production Mode - Rebuild from GitHub source
docker-compose build --no-cache sirius-postgres sirius-rabbitmq sirius-valkey sirius-engine sirius-ui
# Check SystemMonitor status
docker exec <container> ps aux | grep -E "system-monitor|go run main.go"
# View metrics in Valkey
docker exec sirius-valkey redis-cli get "system:metrics:<container_name>"
# Check container logs for startup mode
docker logs <container> | grep -i "system monitor\|development\|go run"
# Verify development environment
docker exec <container> env | grep GO_ENV
# Check for exec format errors
docker logs <container> | grep -i "exec format error"
Key Files
Source Code:
- SystemMonitor:
/minor-projects/app-system-monitor/main.go - GitHub Repo:
https://github.com/SiriusScan/app-system-monitor
Container Integration:
- Engine Startup:
/sirius-engine/start-enhanced.sh - UI Dev Startup:
/sirius-ui/start-dev.sh - UI Prod Startup:
/sirius-ui/start-prod.sh - Other Services:
/<service>/start-with-monitor.sh
Dockerfiles:
- Engine:
/sirius-engine/Dockerfile(multi-stage build from GitHub) - UI:
/sirius-ui/Dockerfile(multi-stage build from GitHub) - PostgreSQL:
/sirius-postgres/Dockerfile(multi-stage build from GitHub) - RabbitMQ:
/sirius-rabbitmq/Dockerfile(multi-stage build from GitHub) - Valkey:
/sirius-valkey/Dockerfile(multi-stage build from GitHub)
Monitoring Endpoints
- Valkey:
sirius-valkey:6379 - Metrics Key:
system:metrics:{container_name} - Logs Key:
system:logs:{container_name}:{timestamp}
Development Mode Indicators
Logs showing development mode:
Running system monitor with go run (development mode)
go: downloading github.com/SiriusScan/go-api...
System Monitor started with PID: 7
Logs showing production mode:
Running system monitor binary (production mode)
System monitor started with PID: 8
Common Issues Quick Fix
| Issue | Quick Fix |
|---|---|
| Exec format error | Rebuild with docker-compose build <service> |
| SystemMonitor not running | Check docker logs <container> for startup errors |
| Metrics not updating | Verify Valkey connection: docker exec <container> nc -zv sirius-valkey 6379 |
| Container crash loop | Check if scanner failure is bringing down other services |
| Development changes not appearing | Restart container: docker-compose restart <service> |
This documentation covers SystemMonitor v2.1+ with development mode support, CPU drift fixes, and multi-stage Docker builds. For older versions, refer to historical documentation or upgrade to the latest version.