Files
mev-beta/orig/scripts/log-manager.sh
Administrator c54c569f30 refactor: move all remaining files to orig/ directory
Completed clean root directory structure:
- Root now contains only: .git, .env, docs/, orig/
- Moved all remaining files and directories to orig/:
  - Config files (.claude, .dockerignore, .drone.yml, etc.)
  - All .env variants (except active .env)
  - Git config (.gitconfig, .github, .gitignore, etc.)
  - Tool configs (.golangci.yml, .revive.toml, etc.)
  - Documentation (*.md files, @prompts)
  - Build files (Dockerfiles, Makefile, go.mod, go.sum)
  - Docker compose files
  - All source directories (scripts, tests, tools, etc.)
  - Runtime directories (logs, monitoring, reports)
  - Dependency files (node_modules, lib, cache)
  - Special files (--delete)

- Removed empty runtime directories (bin/, data/)

V2 structure is now clean:
- docs/planning/ - V2 planning documents
- orig/ - Complete V1 codebase preserved
- .env - Active environment config (not in git)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 10:53:05 +01:00

834 lines
30 KiB
Bash
Executable File

#!/bin/bash
# MEV Bot Production Log Manager
# Comprehensive log management with real-time monitoring, alerting, and analytics
set -euo pipefail
# Production Configuration
PROJECT_ROOT="/home/administrator/projects/mev-beta"
LOGS_DIR="$PROJECT_ROOT/logs"
ARCHIVE_DIR="$PROJECT_ROOT/logs/archives"
ANALYTICS_DIR="$PROJECT_ROOT/logs/analytics"
ALERTS_DIR="$PROJECT_ROOT/logs/alerts"
CONFIG_FILE="$PROJECT_ROOT/config/log-manager.conf"
# Default Configuration
DEFAULT_RETENTION_DAYS=30
DEFAULT_ARCHIVE_SIZE_LIMIT="10G"
DEFAULT_LOG_SIZE_LIMIT="1G"
DEFAULT_ERROR_THRESHOLD=100
DEFAULT_ALERT_EMAIL=""
DEFAULT_SLACK_WEBHOOK=""
DEFAULT_MONITORING_INTERVAL=60
# Colors and formatting
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
# Performance metrics
declare -A METRICS=(
["archives_created"]=0
["logs_rotated"]=0
["alerts_sent"]=0
["errors_detected"]=0
["corruption_found"]=0
["performance_issues"]=0
)
# Initialize configuration
init_config() {
if [[ ! -f "$CONFIG_FILE" ]]; then
mkdir -p "$(dirname "$CONFIG_FILE")"
cat > "$CONFIG_FILE" << EOF
# MEV Bot Log Manager Configuration
RETENTION_DAYS=${DEFAULT_RETENTION_DAYS}
ARCHIVE_SIZE_LIMIT=${DEFAULT_ARCHIVE_SIZE_LIMIT}
LOG_SIZE_LIMIT=${DEFAULT_LOG_SIZE_LIMIT}
ERROR_THRESHOLD=${DEFAULT_ERROR_THRESHOLD}
ALERT_EMAIL=${DEFAULT_ALERT_EMAIL}
SLACK_WEBHOOK=${DEFAULT_SLACK_WEBHOOK}
MONITORING_INTERVAL=${DEFAULT_MONITORING_INTERVAL}
AUTO_ROTATE=true
AUTO_ANALYZE=true
AUTO_ALERT=true
COMPRESS_LEVEL=9
HEALTH_CHECK_ENABLED=true
PERFORMANCE_TRACKING=true
EOF
log "Created default configuration: $CONFIG_FILE"
fi
source "$CONFIG_FILE"
}
# Logging functions with levels
log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] INFO:${NC} $1" | tee -a "$LOGS_DIR/log-manager.log"
}
warn() {
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARN:${NC} $1" | tee -a "$LOGS_DIR/log-manager.log"
}
error() {
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" | tee -a "$LOGS_DIR/log-manager.log"
((METRICS["errors_detected"]++))
}
success() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] SUCCESS:${NC} $1" | tee -a "$LOGS_DIR/log-manager.log"
}
debug() {
if [[ "${DEBUG:-false}" == "true" ]]; then
echo -e "${CYAN}[$(date +'%Y-%m-%d %H:%M:%S')] DEBUG:${NC} $1" | tee -a "$LOGS_DIR/log-manager.log"
fi
}
# Create directory structure
setup_directories() {
local dirs=("$ARCHIVE_DIR" "$ANALYTICS_DIR" "$ALERTS_DIR" "$LOGS_DIR/rotated" "$LOGS_DIR/health")
for dir in "${dirs[@]}"; do
if [[ ! -d "$dir" ]]; then
mkdir -p "$dir"
debug "Created directory: $dir"
fi
done
}
# Enhanced log rotation with size and time-based triggers
rotate_logs() {
log "Starting intelligent log rotation..."
local rotated_count=0
local timestamp=$(date +"%Y%m%d_%H%M%S")
# Find logs that need rotation
while IFS= read -r -d '' logfile; do
local filename=$(basename "$logfile")
local size=$(stat -c%s "$logfile" 2>/dev/null || echo 0)
local size_mb=$((size / 1024 / 1024))
# Check if rotation is needed (size > limit or age > 24h)
local needs_rotation=false
if [[ $size -gt $(numfmt --from=iec "${LOG_SIZE_LIMIT}") ]]; then
needs_rotation=true
debug "Log $filename needs rotation: size ${size_mb}MB exceeds limit"
fi
if [[ $(find "$logfile" -mtime +0 -print 2>/dev/null) ]]; then
needs_rotation=true
debug "Log $filename needs rotation: older than 24 hours"
fi
if [[ "$needs_rotation" == "true" ]]; then
local rotated_name="${filename%.log}_${timestamp}.log"
mv "$logfile" "$LOGS_DIR/rotated/$rotated_name"
gzip "$LOGS_DIR/rotated/$rotated_name"
touch "$logfile" # Create fresh log file
((rotated_count++))
log "Rotated $filename -> ${rotated_name}.gz (${size_mb}MB)"
fi
done < <(find "$LOGS_DIR" -maxdepth 1 -name "*.log" -type f -print0)
METRICS["logs_rotated"]=$rotated_count
success "Log rotation completed: $rotated_count files rotated"
}
# Real-time log analysis with pattern detection
analyze_logs() {
log "Starting comprehensive log analysis..."
local analysis_file="$ANALYTICS_DIR/analysis_$(date +%Y%m%d_%H%M%S).json"
local main_log="$LOGS_DIR/mev_bot.log"
if [[ ! -f "$main_log" ]]; then
warn "Main log file not found: $main_log"
return 1
fi
# Performance metrics extraction
local total_lines=$(wc -l < "$main_log")
local error_lines=$(grep -c "ERROR" "$main_log" || echo 0)
local warn_lines=$(grep -c "WARN" "$main_log" || echo 0)
local success_lines=$(grep -c "SUCCESS\|✅" "$main_log" || echo 0)
# MEV-specific metrics
local opportunities=$(grep -c "opportunity" "$main_log" || echo 0)
local rejections=$(grep -c "REJECTED" "$main_log" || echo 0)
local parsing_failures=$(grep -c "PARSING FAILED" "$main_log" || echo 0)
local direct_parsing=$(grep -c "DIRECT PARSING" "$main_log" || echo 0)
# Transaction processing metrics
local blocks_processed=$(grep -c "Block.*Processing.*transactions" "$main_log" || echo 0)
local dex_transactions=$(grep -c "DEX transactions" "$main_log" || echo 0)
# Error pattern analysis
local zero_address_issues=$(grep -c "zero.*address" "$main_log" || echo 0)
local connection_errors=$(grep -c "connection.*failed\|context.*canceled" "$main_log" || echo 0)
local timeout_errors=$(grep -c "timeout\|deadline exceeded" "$main_log" || echo 0)
# Performance trending (last 1000 lines for recent activity)
local recent_errors=$(tail -1000 "$main_log" | grep -c "ERROR" || echo 0)
local recent_success=$(tail -1000 "$main_log" | grep -c "SUCCESS" || echo 0)
# Calculate rates and health scores
local error_rate=$(echo "scale=2; $error_lines * 100 / $total_lines" | bc -l 2>/dev/null || echo 0)
local success_rate=$(echo "scale=2; $success_lines * 100 / $total_lines" | bc -l 2>/dev/null || echo 0)
local health_score=$(echo "scale=0; 100 - $error_rate" | bc -l 2>/dev/null || echo 100)
# Generate comprehensive analysis
cat > "$analysis_file" << EOF
{
"analysis_timestamp": "$(date -Iseconds)",
"log_file": "$main_log",
"system_info": {
"hostname": "$(hostname)",
"uptime": "$(uptime -p 2>/dev/null || echo 'unknown')",
"load_average": "$(uptime | awk -F'load average:' '{print $2}' | xargs)"
},
"log_statistics": {
"total_lines": $total_lines,
"file_size_mb": $(echo "scale=2; $(stat -c%s "$main_log") / 1024 / 1024" | bc -l),
"error_lines": $error_lines,
"warning_lines": $warn_lines,
"success_lines": $success_lines,
"error_rate_percent": $error_rate,
"success_rate_percent": $success_rate,
"health_score": $health_score
},
"mev_metrics": {
"opportunities_detected": $opportunities,
"events_rejected": $rejections,
"parsing_failures": $parsing_failures,
"direct_parsing_attempts": $direct_parsing,
"blocks_processed": $blocks_processed,
"dex_transactions": $dex_transactions
},
"error_patterns": {
"zero_address_issues": $zero_address_issues,
"connection_errors": $connection_errors,
"timeout_errors": $timeout_errors
},
"recent_activity": {
"recent_errors": $recent_errors,
"recent_success": $recent_success,
"recent_health_trend": "$([ -n "${recent_errors}" ] && [ "${recent_errors}" -lt 10 ] 2>/dev/null && echo good || echo concerning)"
},
"alerts_triggered": []
}
EOF
# Check for alert conditions
check_alert_conditions "$analysis_file"
success "Log analysis completed: $analysis_file"
echo -e "${BLUE}Health Score: $health_score/100${NC} | Error Rate: ${error_rate}% | Success Rate: ${success_rate}%"
}
# Alert system with multiple notification channels
check_alert_conditions() {
local analysis_file="$1"
local alerts_triggered=()
# Read analysis data
local error_rate=$(jq -r '.log_statistics.error_rate_percent' "$analysis_file" 2>/dev/null || echo 0)
local health_score=$(jq -r '.log_statistics.health_score' "$analysis_file" 2>/dev/null || echo 100)
local parsing_failures=$(jq -r '.mev_metrics.parsing_failures' "$analysis_file" 2>/dev/null || echo 0)
local zero_address_issues=$(jq -r '.error_patterns.zero_address_issues' "$analysis_file" 2>/dev/null || echo 0)
# Define alert conditions
if (( $(echo "$error_rate > 10" | bc -l) )); then
alerts_triggered+=("HIGH_ERROR_RATE:$error_rate%")
send_alert "High Error Rate" "Error rate is $error_rate%, exceeding 10% threshold"
fi
if (( $(echo "$health_score < 80" | bc -l) )); then
alerts_triggered+=("LOW_HEALTH_SCORE:$health_score")
send_alert "Low Health Score" "System health score is $health_score/100, below 80 threshold"
fi
if (( parsing_failures > 50 )); then
alerts_triggered+=("PARSING_FAILURES:$parsing_failures")
send_alert "High Parsing Failures" "$parsing_failures parsing failures detected"
fi
if (( zero_address_issues > 100 )); then
alerts_triggered+=("ZERO_ADDRESS_CORRUPTION:$zero_address_issues")
send_alert "Address Corruption" "$zero_address_issues zero address issues detected"
fi
# Update analysis file with alerts
if [[ ${#alerts_triggered[@]} -gt 0 ]]; then
local alerts_json=$(printf '%s\n' "${alerts_triggered[@]}" | jq -R . | jq -s .)
jq ".alerts_triggered = $alerts_json" "$analysis_file" > "${analysis_file}.tmp" && mv "${analysis_file}.tmp" "$analysis_file"
METRICS["alerts_sent"]=${#alerts_triggered[@]}
fi
}
# Multi-channel alert delivery
send_alert() {
local title="$1"
local message="$2"
local timestamp=$(date -Iseconds)
local alert_file="$ALERTS_DIR/alert_$(date +%Y%m%d_%H%M%S).json"
# Create alert record
cat > "$alert_file" << EOF
{
"timestamp": "$timestamp",
"title": "$title",
"message": "$message",
"hostname": "$(hostname)",
"severity": "warning",
"system_load": "$(uptime | awk -F'load average:' '{print $2}' | xargs)",
"disk_usage": "$(df -h $LOGS_DIR | tail -1 | awk '{print $5}')"
}
EOF
error "ALERT: $title - $message"
# Email notification
if [[ -n "${ALERT_EMAIL:-}" ]] && command -v mail >/dev/null 2>&1; then
echo "MEV Bot Alert: $title - $message ($(hostname) at $timestamp)" | mail -s "MEV Bot Alert: $title" "$ALERT_EMAIL"
fi
# Slack notification
if [[ -n "${SLACK_WEBHOOK:-}" ]] && command -v curl >/dev/null 2>&1; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"🚨 MEV Bot Alert: $title\n$message\nHost: $(hostname)\nTime: $timestamp\"}" \
"$SLACK_WEBHOOK" >/dev/null 2>&1 || true
fi
}
# Log corruption detection and health checks
health_check() {
log "Running comprehensive health checks..."
local health_report="$LOGS_DIR/health/health_$(date +%Y%m%d_%H%M%S).json"
local issues=()
# Check log file integrity
while IFS= read -r -d '' logfile; do
if [[ ! -r "$logfile" ]]; then
issues+=("UNREADABLE_LOG:$(basename "$logfile")")
continue
fi
# Check for truncated logs
if [[ $(tail -c 1 "$logfile" | wc -l) -eq 0 ]]; then
issues+=("TRUNCATED_LOG:$(basename "$logfile")")
fi
# Check for corruption patterns
if grep -q "\x00" "$logfile" 2>/dev/null; then
issues+=("NULL_BYTES:$(basename "$logfile")")
((METRICS["corruption_found"]++))
fi
# Check for encoding issues
if ! file "$logfile" | grep -q "text"; then
issues+=("ENCODING_ISSUE:$(basename "$logfile")")
fi
done < <(find "$LOGS_DIR" -maxdepth 1 -name "*.log" -type f -print0)
# Check disk space
local disk_usage=$(df "$LOGS_DIR" | tail -1 | awk '{print $5}' | sed 's/%//')
if (( disk_usage > 90 )); then
issues+=("HIGH_DISK_USAGE:${disk_usage}%")
send_alert "High Disk Usage" "Log directory is ${disk_usage}% full"
fi
# Check archive integrity
while IFS= read -r -d '' archive; do
if ! tar -tzf "$archive" >/dev/null 2>&1; then
issues+=("CORRUPTED_ARCHIVE:$(basename "$archive")")
((METRICS["corruption_found"]++))
fi
done < <(find "$ARCHIVE_DIR" -name "*.tar.gz" -type f -print0 2>/dev/null)
# Generate health report
local health_status="healthy"
if [[ ${#issues[@]} -gt 0 ]]; then
health_status="issues_detected"
fi
cat > "$health_report" << EOF
{
"timestamp": "$(date -Iseconds)",
"status": "$health_status",
"issues_count": ${#issues[@]},
"issues": $(printf '%s\n' "${issues[@]}" | jq -R . | jq -s . 2>/dev/null || echo '[]'),
"disk_usage_percent": $disk_usage,
"log_files_count": $(find "$LOGS_DIR" -maxdepth 1 -name "*.log" -type f | wc -l),
"archive_files_count": $(find "$ARCHIVE_DIR" -name "*.tar.gz" -type f 2>/dev/null | wc -l),
"total_log_size_mb": $(du -sm "$LOGS_DIR" | cut -f1),
"system_load": "$(uptime | awk -F'load average:' '{print $2}' | xargs)"
}
EOF
if [[ ${#issues[@]} -eq 0 ]]; then
success "Health check passed: No issues detected"
else
warn "Health check found ${#issues[@]} issues: ${issues[*]}"
fi
echo "$health_report"
}
# Performance monitoring with trending
monitor_performance() {
log "Monitoring system performance..."
local perf_file="$ANALYTICS_DIR/performance_$(date +%Y%m%d_%H%M%S).json"
# System metrics
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//')
local memory_usage=$(free | grep Mem | awk '{printf("%.1f", $3/$2 * 100.0)}')
local load_avg=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
# MEV bot specific metrics
local mev_processes=$(pgrep -f mev-bot | wc -l)
local mev_memory=0
if [[ $mev_processes -gt 0 ]]; then
mev_memory=$(pgrep -f mev-bot | xargs ps -o pid,rss --no-headers | awk '{sum+=$2} END {print sum/1024}' 2>/dev/null || echo 0)
fi
# Log processing rate
local log_lines_per_min=0
if [[ -f "$LOGS_DIR/mev_bot.log" ]]; then
log_lines_per_min=$(tail -100 "$LOGS_DIR/mev_bot.log" | grep "$(date '+%Y/%m/%d %H:%M')" | wc -l || echo 0)
fi
cat > "$perf_file" << EOF
{
"timestamp": "$(date -Iseconds)",
"system_metrics": {
"cpu_usage_percent": $cpu_usage,
"memory_usage_percent": $memory_usage,
"load_average": $load_avg,
"uptime_seconds": $(awk '{print int($1)}' /proc/uptime)
},
"mev_bot_metrics": {
"process_count": $mev_processes,
"memory_usage_mb": $mev_memory,
"log_rate_lines_per_min": $log_lines_per_min
},
"log_metrics": {
"total_log_size_mb": $(du -sm "$LOGS_DIR" | cut -f1),
"archive_size_mb": $(du -sm "$ARCHIVE_DIR" 2>/dev/null | cut -f1 || echo 0),
"active_log_files": $(find "$LOGS_DIR" -maxdepth 1 -name "*.log" -type f | wc -l)
}
}
EOF
# Check for performance issues
if (( $(echo "$cpu_usage > 80" | bc -l) )); then
((METRICS["performance_issues"]++))
send_alert "High CPU Usage" "CPU usage is ${cpu_usage}%"
fi
if (( $(echo "$memory_usage > 85" | bc -l) )); then
((METRICS["performance_issues"]++))
send_alert "High Memory Usage" "Memory usage is ${memory_usage}%"
fi
debug "Performance monitoring completed: $perf_file"
}
# Advanced archiving with compression optimization
advanced_archive() {
log "Starting advanced archive process..."
local timestamp=$(date +"%Y%m%d_%H%M%S")
local archive_name="mev_logs_${timestamp}"
local temp_dir="$ARCHIVE_DIR/.tmp_$archive_name"
mkdir -p "$temp_dir"
# Copy logs with metadata preservation
find "$LOGS_DIR" -maxdepth 1 -name "*.log" -type f -exec cp -p {} "$temp_dir/" \;
# Copy rotated logs
if [[ -d "$LOGS_DIR/rotated" ]]; then
cp -r "$LOGS_DIR/rotated" "$temp_dir/"
fi
# Copy analytics and health data
if [[ -d "$ANALYTICS_DIR" ]]; then
cp -r "$ANALYTICS_DIR" "$temp_dir/"
fi
if [[ -d "$ALERTS_DIR" ]]; then
cp -r "$ALERTS_DIR" "$temp_dir/"
fi
# Generate comprehensive metadata
cat > "$temp_dir/archive_metadata.json" << EOF
{
"archive_info": {
"timestamp": "$(date -Iseconds)",
"archive_name": "$archive_name",
"created_by": "$(whoami)",
"hostname": "$(hostname)",
"mev_bot_version": "$(git rev-parse HEAD 2>/dev/null || echo 'unknown')",
"git_branch": "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')",
"compression_level": ${COMPRESS_LEVEL:-9}
},
"system_snapshot": {
"os": "$(uname -s)",
"kernel": "$(uname -r)",
"architecture": "$(uname -m)",
"uptime": "$(uptime -p 2>/dev/null || echo 'unknown')",
"load_average": "$(uptime | awk -F'load average:' '{print $2}' | xargs)",
"memory_total_gb": $(echo "scale=2; $(grep MemTotal /proc/meminfo | awk '{print $2}') / 1024 / 1024" | bc -l),
"disk_space_logs": "$(df -h $LOGS_DIR | tail -1 | awk '{print $4}')"
},
"content_summary": {
"total_files": $(find "$temp_dir" -type f | wc -l),
"total_size_bytes": $(find "$temp_dir" -type f -exec stat -c%s {} + | awk '{sum+=$1} END {print sum+0}'),
"log_files": $(find "$temp_dir" -name "*.log" | wc -l),
"compressed_files": $(find "$temp_dir" -name "*.gz" | wc -l)
},
"metrics": $(echo "${METRICS[@]}" | tr ' ' '\n' | awk -F= '{print "\"" $1 "\":" $2}' | paste -sd, | sed 's/^/{/' | sed 's/$/}/')
}
EOF
# Create optimized archive
cd "$ARCHIVE_DIR"
tar -cf "${archive_name}.tar.gz" --use-compress-program="gzip -${COMPRESS_LEVEL:-9}" -C "$(dirname "$temp_dir")" "$(basename "$temp_dir")"
# Verify archive integrity
if tar -tzf "${archive_name}.tar.gz" >/dev/null 2>&1; then
local archive_size=$(stat -c%s "${archive_name}.tar.gz" | numfmt --to=iec)
success "Archive created successfully: ${archive_name}.tar.gz ($archive_size)"
# Update symlink
ln -sf "${archive_name}.tar.gz" "latest_archive.tar.gz"
# Cleanup temp directory
rm -rf "$temp_dir"
((METRICS["archives_created"]++))
else
error "Archive verification failed: ${archive_name}.tar.gz"
rm -f "${archive_name}.tar.gz"
return 1
fi
}
# Cleanup with advanced retention policies
intelligent_cleanup() {
log "Starting intelligent cleanup with retention policies..."
local deleted_archives=0
local deleted_size=0
# Archive retention by age
while IFS= read -r -d '' archive; do
local size=$(stat -c%s "$archive")
rm "$archive"
((deleted_archives++))
deleted_size=$((deleted_size + size))
debug "Deleted old archive: $(basename "$archive")"
done < <(find "$ARCHIVE_DIR" -name "mev_logs_*.tar.gz" -mtime +${RETENTION_DAYS} -print0 2>/dev/null)
# Size-based cleanup if total exceeds limit
local total_size=$(du -sb "$ARCHIVE_DIR" 2>/dev/null | cut -f1 || echo 0)
local size_limit=$(numfmt --from=iec "${ARCHIVE_SIZE_LIMIT}")
if [[ $total_size -gt $size_limit ]]; then
warn "Archive directory exceeds size limit, cleaning oldest archives..."
while [[ $total_size -gt $size_limit ]] && [[ $(find "$ARCHIVE_DIR" -name "mev_logs_*.tar.gz" | wc -l) -gt 1 ]]; do
local oldest=$(find "$ARCHIVE_DIR" -name "mev_logs_*.tar.gz" -printf '%T+ %p\n' | sort | head -1 | cut -d' ' -f2)
if [[ -f "$oldest" ]]; then
local size=$(stat -c%s "$oldest")
rm "$oldest"
((deleted_archives++))
deleted_size=$((deleted_size + size))
total_size=$((total_size - size))
debug "Deleted for size limit: $(basename "$oldest")"
fi
done
fi
# Cleanup analytics and alerts older than retention period
find "$ANALYTICS_DIR" -name "*.json" -mtime +${RETENTION_DAYS} -delete 2>/dev/null || true
find "$ALERTS_DIR" -name "*.json" -mtime +${RETENTION_DAYS} -delete 2>/dev/null || true
find "$LOGS_DIR/health" -name "*.json" -mtime +${RETENTION_DAYS} -delete 2>/dev/null || true
if [[ $deleted_archives -gt 0 ]]; then
local deleted_size_human=$(echo $deleted_size | numfmt --to=iec)
success "Cleanup completed: $deleted_archives archives deleted ($deleted_size_human freed)"
else
log "Cleanup completed: No files needed deletion"
fi
}
# Real-time monitoring daemon
start_monitoring() {
log "Starting real-time monitoring daemon..."
local monitor_pid_file="$LOGS_DIR/.monitor.pid"
if [[ -f "$monitor_pid_file" ]] && kill -0 $(cat "$monitor_pid_file") 2>/dev/null; then
warn "Monitoring daemon already running (PID: $(cat "$monitor_pid_file"))"
return 1
fi
# Background monitoring loop
(
echo $$ > "$monitor_pid_file"
while true; do
sleep "${MONITORING_INTERVAL}"
# Quick health check
if [[ "${HEALTH_CHECK_ENABLED}" == "true" ]]; then
health_check >/dev/null 2>&1
fi
# Performance monitoring
if [[ "${PERFORMANCE_TRACKING}" == "true" ]]; then
monitor_performance >/dev/null 2>&1
fi
# Auto-rotation check
if [[ "${AUTO_ROTATE}" == "true" ]]; then
local needs_rotation=$(find "$LOGS_DIR" -maxdepth 1 -name "*.log" -size +${LOG_SIZE_LIMIT} | wc -l)
if [[ $needs_rotation -gt 0 ]]; then
rotate_logs >/dev/null 2>&1
fi
fi
# Auto-analysis
if [[ "${AUTO_ANALYZE}" == "true" ]]; then
analyze_logs >/dev/null 2>&1
fi
done
) &
local daemon_pid=$!
echo "$daemon_pid" > "$monitor_pid_file"
success "Monitoring daemon started (PID: $daemon_pid, interval: ${MONITORING_INTERVAL}s)"
}
# Stop monitoring daemon
stop_monitoring() {
local monitor_pid_file="$LOGS_DIR/.monitor.pid"
if [[ -f "$monitor_pid_file" ]]; then
local pid=$(cat "$monitor_pid_file")
if kill -0 "$pid" 2>/dev/null; then
kill "$pid"
rm "$monitor_pid_file"
success "Monitoring daemon stopped (PID: $pid)"
else
warn "Monitoring daemon not running (stale PID file)"
rm "$monitor_pid_file"
fi
else
warn "Monitoring daemon not running"
fi
}
# Dashboard generation
generate_dashboard() {
log "Generating operational dashboard..."
local dashboard_file="$ANALYTICS_DIR/dashboard_$(date +%Y%m%d_%H%M%S).html"
local latest_analysis=$(find "$ANALYTICS_DIR" -name "analysis_*.json" -type f | sort | tail -1)
local latest_health=$(find "$LOGS_DIR/health" -name "health_*.json" -type f | sort | tail -1)
local latest_performance=$(find "$ANALYTICS_DIR" -name "performance_*.json" -type f | sort | tail -1)
cat > "$dashboard_file" << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MEV Bot Operations Dashboard</title>
<style>
body { font-family: 'Segoe UI', Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }
.dashboard { max-width: 1200px; margin: 0 auto; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 10px; margin-bottom: 20px; }
.metrics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 20px; }
.metric-card { background: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.metric-value { font-size: 2em; font-weight: bold; margin: 10px 0; }
.metric-label { color: #666; font-size: 0.9em; }
.status-good { color: #28a745; }
.status-warning { color: #ffc107; }
.status-error { color: #dc3545; }
.chart-container { background: white; border-radius: 10px; padding: 20px; margin-bottom: 20px; }
.log-preview { background: #1e1e1e; color: #fff; padding: 15px; border-radius: 5px; font-family: 'Courier New', monospace; font-size: 0.8em; max-height: 300px; overflow-y: auto; }
.timestamp { color: #888; font-size: 0.8em; }
</style>
</head>
<body>
<div class="dashboard">
<div class="header">
<h1>MEV Bot Operations Dashboard</h1>
<p class="timestamp">Generated: $(date)</p>
</div>
EOF
# Add metrics if analysis file exists
if [[ -f "$latest_analysis" ]]; then
local health_score=$(jq -r '.log_statistics.health_score' "$latest_analysis" 2>/dev/null || echo 0)
local error_rate=$(jq -r '.log_statistics.error_rate_percent' "$latest_analysis" 2>/dev/null || echo 0)
local opportunities=$(jq -r '.mev_metrics.opportunities_detected' "$latest_analysis" 2>/dev/null || echo 0)
cat >> "$dashboard_file" << EOF
<div class="metrics-grid">
<div class="metric-card">
<div class="metric-label">System Health Score</div>
<div class="metric-value status-$([ $(echo "$health_score > 80" | bc -l) -eq 1 ] && echo 'good' || echo 'warning')">${health_score}/100</div>
</div>
<div class="metric-card">
<div class="metric-label">Error Rate</div>
<div class="metric-value status-$([ $(echo "$error_rate < 5" | bc -l) -eq 1 ] && echo 'good' || echo 'warning')">${error_rate}%</div>
</div>
<div class="metric-card">
<div class="metric-label">MEV Opportunities</div>
<div class="metric-value status-good">${opportunities}</div>
</div>
</div>
EOF
fi
# Add recent log entries
cat >> "$dashboard_file" << EOF
<div class="chart-container">
<h3>Recent Log Activity</h3>
<div class="log-preview">$(tail -20 "$LOGS_DIR/mev_bot.log" 2>/dev/null | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' || echo 'No recent log activity')</div>
</div>
</div>
</body>
</html>
EOF
success "Dashboard generated: $dashboard_file"
echo "$dashboard_file"
}
# Main command dispatcher
main() {
case "${1:-help}" in
"init")
setup_directories
init_config
success "Log manager initialized"
;;
"rotate")
init_config
setup_directories
rotate_logs
;;
"analyze")
init_config
setup_directories
analyze_logs
;;
"archive")
init_config
setup_directories
advanced_archive
;;
"health")
init_config
setup_directories
health_check
;;
"monitor")
init_config
setup_directories
monitor_performance
;;
"cleanup")
init_config
setup_directories
intelligent_cleanup
;;
"start-daemon")
init_config
setup_directories
start_monitoring
;;
"stop-daemon")
stop_monitoring
;;
"dashboard")
init_config
setup_directories
generate_dashboard
;;
"full")
init_config
setup_directories
rotate_logs
analyze_logs
health_check
monitor_performance
advanced_archive
intelligent_cleanup
generate_dashboard
;;
"status")
init_config
echo -e "${BOLD}MEV Bot Log Manager Status${NC}"
echo "Configuration: $CONFIG_FILE"
echo "Monitoring: $([ -f "$LOGS_DIR/.monitor.pid" ] && echo "Running (PID: $(cat "$LOGS_DIR/.monitor.pid"))" || echo "Stopped")"
echo "Archives: $(find "$ARCHIVE_DIR" -name "*.tar.gz" 2>/dev/null | wc -l) files"
echo "Total archive size: $(du -sh "$ARCHIVE_DIR" 2>/dev/null | cut -f1 || echo "0")"
echo "Log directory size: $(du -sh "$LOGS_DIR" | cut -f1)"
;;
*)
cat << EOF
MEV Bot Production Log Manager
USAGE:
$0 <command> [options]
COMMANDS:
init Initialize log manager with directories and config
rotate Rotate large log files
analyze Perform comprehensive log analysis
archive Create compressed archive with metadata
health Run health checks and corruption detection
monitor Generate performance monitoring report
cleanup Clean old archives based on retention policy
start-daemon Start real-time monitoring daemon
stop-daemon Stop monitoring daemon
dashboard Generate HTML operations dashboard
full Run complete log management cycle
status Show current system status
EXAMPLES:
$0 init # First-time setup
$0 full # Complete log management cycle
$0 start-daemon # Start background monitoring
$0 dashboard # Generate operations dashboard
CONFIGURATION:
Edit $CONFIG_FILE to customize behavior
MONITORING:
The daemon provides real-time monitoring with configurable intervals,
automatic rotation, health checks, and alerting via email/Slack.
EOF
;;
esac
}
# Initialize and run
cd "$PROJECT_ROOT" 2>/dev/null || { error "Invalid project root: $PROJECT_ROOT"; exit 1; }
main "$@"