Files
foxhunt/scripts/health-check.sh
jgrusewski 2da5bafc0e refactor: rename tli→fxt, delete legacy scripts/RunPod/deploy artifacts
- Rename tli/ directory to fxt/, update package + binary name to "fxt"
- Replace all `use tli::` → `use fxt::` across 52 Rust files
- Update build.rs proto paths (tli/proto → fxt/proto) in 6 services
- Update Dockerfiles, CI workflows, deploy.sh for new paths
- Delete ~170 legacy shell scripts (kept 15 essential ones)
- Delete RunPod Python client (runpod/), tests (tests/runpod/)
- Delete foxhunt-deploy crate (RunPod-only deployment tool)
- Delete terraform/runpod/ (moved to Scaleway)
- Delete ML Python hyperopt scripts (replaced by Rust Argmin PSO)
- Delete .gitlab-ci.yml (using GitHub + Gitea)
- Remove foxhunt-deploy from workspace members

504 files changed, -74,355 lines of legacy code removed.
Workspace compiles clean (0 errors, 0 warnings).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:32:21 +01:00

436 lines
13 KiB
Bash
Executable File

#!/bin/bash
#============================================================================
# FOXHUNT HFT TRADING SYSTEM - COMPREHENSIVE HEALTH CHECK
#============================================================================
# Validates system health, performance metrics, and service connectivity
#
# Usage: ./health-check.sh [OPTIONS]
#
# Options:
# --detailed Show detailed health information
# --performance Include performance metrics
# --json Output results in JSON format
# --continuous Run continuous monitoring (Ctrl+C to stop)
# --help Show this help message
#============================================================================
set -euo pipefail
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOCKER_COMPOSE_FILE="docker-compose.production.yml"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Health check results
declare -A health_results
declare -A performance_metrics
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[✓]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[⚠]${NC} $1"
}
log_error() {
echo -e "${RED}[✗]${NC} $1"
}
# Show help
show_help() {
cat << EOF
Foxhunt HFT Trading System - Health Check
Usage: $0 [OPTIONS]
OPTIONS:
--detailed Show detailed health information
--performance Include performance metrics
--json Output results in JSON format
--continuous Run continuous monitoring (Ctrl+C to stop)
--help Show this help message
EXAMPLES:
$0 # Basic health check
$0 --detailed # Detailed health check
$0 --performance # Include performance metrics
$0 --continuous # Continuous monitoring
EOF
}
# Check if service is running
check_service_status() {
local service_name="$1"
local container_name="foxhunt-${service_name}-prod"
if docker ps --format "table {{.Names}}" | grep -q "$container_name"; then
health_results["${service_name}_status"]="running"
return 0
else
health_results["${service_name}_status"]="stopped"
return 1
fi
}
# Check service health endpoint
check_service_health() {
local service_name="$1"
local health_url="$2"
local timeout="${3:-5}"
if curl -sf --max-time "$timeout" "$health_url" &>/dev/null; then
health_results["${service_name}_health"]="healthy"
return 0
else
health_results["${service_name}_health"]="unhealthy"
return 1
fi
}
# Get service performance metrics
get_service_metrics() {
local service_name="$1"
local metrics_url="$2"
local response
if response=$(curl -sf --max-time 5 "$metrics_url" 2>/dev/null); then
# Extract key metrics (simplified for demo)
local cpu_usage=$(echo "$response" | grep "cpu_usage" | awk '{print $2}' || echo "0")
local memory_usage=$(echo "$response" | grep "memory_usage" | awk '{print $2}' || echo "0")
local request_rate=$(echo "$response" | grep "request_rate" | awk '{print $2}' || echo "0")
performance_metrics["${service_name}_cpu"]="$cpu_usage"
performance_metrics["${service_name}_memory"]="$memory_usage"
performance_metrics["${service_name}_requests"]="$request_rate"
fi
}
# Check database connectivity
check_database() {
local db_type="$1"
local connection_string="$2"
case "$db_type" in
"postgresql")
if docker exec foxhunt-postgres-prod pg_isready &>/dev/null; then
health_results["postgresql_health"]="healthy"
log_success "PostgreSQL is accessible"
else
health_results["postgresql_health"]="unhealthy"
log_error "PostgreSQL is not accessible"
fi
;;
"redis")
if docker exec foxhunt-redis-prod redis-cli ping | grep -q PONG; then
health_results["redis_health"]="healthy"
log_success "Redis is accessible"
else
health_results["redis_health"]="unhealthy"
log_error "Redis is not accessible"
fi
;;
"influxdb")
if check_service_health "influxdb" "http://localhost:8086/ping" 3; then
log_success "InfluxDB is accessible"
else
log_error "InfluxDB is not accessible"
fi
;;
esac
}
# Check critical trading metrics
check_trading_metrics() {
log_info "Checking critical trading metrics..."
# Check if trading service is responsive
if check_service_health "trading" "http://localhost:8080/health"; then
log_success "Trading service is healthy"
# Check latency metrics
local latency_response
if latency_response=$(curl -sf "http://localhost:8080/metrics" 2>/dev/null); then
local avg_latency=$(echo "$latency_response" | grep "order_latency" | awk '{print $2}' || echo "unknown")
if [[ "$avg_latency" != "unknown" && "$avg_latency" != "" ]]; then
if (( $(echo "$avg_latency < 10" | bc -l) )); then
log_success "Order latency is acceptable: ${avg_latency}ms"
health_results["trading_latency"]="good"
else
log_warning "Order latency is high: ${avg_latency}ms"
health_results["trading_latency"]="high"
fi
fi
fi
else
log_error "Trading service is not healthy"
fi
}
# Check system resources
check_system_resources() {
log_info "Checking system resources..."
# Memory usage
local memory_info
memory_info=$(free -m | awk 'NR==2{printf "%.1f", $3*100/$2}')
if (( $(echo "$memory_info > 90" | bc -l) )); then
log_warning "High memory usage: ${memory_info}%"
health_results["memory_usage"]="high"
else
log_success "Memory usage is acceptable: ${memory_info}%"
health_results["memory_usage"]="normal"
fi
# Disk usage
local disk_usage
disk_usage=$(df / | awk 'NR==2{print $5}' | sed 's/%//')
if [[ "$disk_usage" -gt 85 ]]; then
log_warning "High disk usage: ${disk_usage}%"
health_results["disk_usage"]="high"
else
log_success "Disk usage is acceptable: ${disk_usage}%"
health_results["disk_usage"]="normal"
fi
# CPU load
local cpu_load
cpu_load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
local cpu_cores=$(nproc)
if (( $(echo "$cpu_load > $cpu_cores * 0.8" | bc -l) )); then
log_warning "High CPU load: $cpu_load (cores: $cpu_cores)"
health_results["cpu_load"]="high"
else
log_success "CPU load is acceptable: $cpu_load (cores: $cpu_cores)"
health_results["cpu_load"]="normal"
fi
}
# Check network connectivity
check_network() {
log_info "Checking network connectivity..."
# Test internal service communication
local services=("trading:8080" "ml-training:8082" "backtesting:8083" "fxt:8081")
for service in "${services[@]}"; do
local service_name=$(echo "$service" | cut -d':' -f1)
local service_port=$(echo "$service" | cut -d':' -f2)
if nc -z localhost "$service_port" 2>/dev/null; then
log_success "$service_name service is reachable on port $service_port"
else
log_error "$service_name service is not reachable on port $service_port"
fi
done
}
# Comprehensive health check
run_health_check() {
local detailed="$1"
local include_performance="$2"
log_info "Starting comprehensive health check..."
# Check core services
local services=("trading" "ml-training" "backtesting" "fxt")
for service in "${services[@]}"; do
if check_service_status "$service"; then
log_success "$service service is running"
else
log_error "$service service is not running"
fi
done
# Check infrastructure services
check_database "postgresql" ""
check_database "redis" ""
check_database "influxdb" ""
# Check Vault
if check_service_health "vault" "http://localhost:8200/v1/sys/health" 5; then
log_success "Vault is accessible"
else
log_error "Vault is not accessible"
fi
# Check monitoring services
if check_service_health "prometheus" "http://localhost:9090/-/healthy"; then
log_success "Prometheus is healthy"
else
log_error "Prometheus is not healthy"
fi
if check_service_health "grafana" "http://localhost:3000/api/health"; then
log_success "Grafana is healthy"
else
log_error "Grafana is not healthy"
fi
# Check trading-specific metrics
check_trading_metrics
# Check system resources
if [[ "$detailed" == true ]]; then
check_system_resources
check_network
fi
# Get performance metrics
if [[ "$include_performance" == true ]]; then
log_info "Collecting performance metrics..."
get_service_metrics "trading" "http://localhost:8080/metrics"
get_service_metrics "ml-training" "http://localhost:8082/metrics"
fi
}
# Output results in JSON format
output_json() {
echo "{"
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
echo " \"health_check\": {"
local first=true
for key in "${!health_results[@]}"; do
if [[ "$first" == false ]]; then
echo ","
fi
echo " \"$key\": \"${health_results[$key]}\""
first=false
done
if [[ ${#performance_metrics[@]} -gt 0 ]]; then
echo " },"
echo " \"performance_metrics\": {"
first=true
for key in "${!performance_metrics[@]}"; do
if [[ "$first" == false ]]; then
echo ","
fi
echo " \"$key\": \"${performance_metrics[$key]}\""
first=false
done
fi
echo " }"
echo "}"
}
# Display summary
show_summary() {
local total_checks=0
local passed_checks=0
for result in "${health_results[@]}"; do
((total_checks++))
if [[ "$result" == "running" || "$result" == "healthy" || "$result" == "good" || "$result" == "normal" ]]; then
((passed_checks++))
fi
done
echo ""
echo "==============================================="
echo "HEALTH CHECK SUMMARY"
echo "==============================================="
echo "Total checks: $total_checks"
echo "Passed: $passed_checks"
echo "Failed: $((total_checks - passed_checks))"
if [[ $passed_checks -eq $total_checks ]]; then
log_success "All health checks passed! System is operating normally."
elif [[ $passed_checks -gt $((total_checks / 2)) ]]; then
log_warning "Some health checks failed. System is partially operational."
else
log_error "Multiple health checks failed. System requires attention."
fi
}
# Continuous monitoring
continuous_monitoring() {
local detailed="$1"
local include_performance="$2"
log_info "Starting continuous monitoring (Press Ctrl+C to stop)..."
while true; do
clear
echo "Foxhunt HFT Health Check - $(date)"
echo "========================================"
# Reset results
health_results=()
performance_metrics=()
run_health_check "$detailed" "$include_performance"
show_summary
sleep 30
done
}
# Main function
main() {
local detailed=false
local include_performance=false
local json_output=false
local continuous=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--detailed)
detailed=true
shift
;;
--performance)
include_performance=true
shift
;;
--json)
json_output=true
shift
;;
--continuous)
continuous=true
shift
;;
--help)
show_help
exit 0
;;
*)
log_error "Unknown option: $1"
show_help
exit 1
;;
esac
done
if [[ "$continuous" == true ]]; then
continuous_monitoring "$detailed" "$include_performance"
else
run_health_check "$detailed" "$include_performance"
if [[ "$json_output" == true ]]; then
output_json
else
show_summary
fi
fi
}
# Run main function
main "$@"