#!/bin/bash
################################################################################
# 系统日志检测模块
# 功能: 检测内核错误、磁盘错误、服务崩溃、系统资源耗尽等日志问题
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################

# 获取脚本所在目录并加载依赖
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="${LIB_DIR:-/tmp/check_modules}"

# 加载配置文件和通用函数库
if [ -f "$LIB_DIR/lib/config.sh" ]; then
    source "$LIB_DIR/lib/config.sh"
else
    echo "ERROR: 配置文件不存在: $LIB_DIR/lib/config.sh"
    exit 1
fi

if [ -f "$LIB_DIR/lib/common.sh" ]; then
    source "$LIB_DIR/lib/common.sh"
else
    echo "ERROR: 通用函数库不存在: $LIB_DIR/lib/common.sh"
    exit 1
fi

# ==================== 检测函数 ====================

# 检测内核错误
check_kernel_errors() {
    local kernel_errors=0

    if command -v dmesg &>/dev/null; then
        kernel_errors=$(dmesg 2>/dev/null | grep -iE "error|fail|timeout" | grep -v "ACPI" | wc -l || echo "0")
    fi

    output_result "KERNEL_ERRORS_24H" "${kernel_errors:-0}"

    if [ "$kernel_errors" -gt 100 ]; then
        output_result "KERNEL_ERRORS_LEVEL" "严重"
    elif [ "$kernel_errors" -gt 10 ]; then
        output_result "KERNEL_ERRORS_LEVEL" "警告"
    else
        output_result "KERNEL_ERRORS_LEVEL" "正常"
    fi
}

# 检测磁盘错误
check_disk_errors() {
    local disk_errors=0

    if command -v dmesg &>/dev/null; then
        disk_errors=$(dmesg 2>/dev/null | grep -ciE "I/O error|disk error|ata error|sd.*error|nvme.*error|filesystem error" || echo "0")
    fi

    output_result "DISK_ERRORS_24H" "${disk_errors:-0}"

    if [ "$disk_errors" -gt 10 ]; then
        output_result "DISK_ERRORS_LEVEL" "严重"
    elif [ "$disk_errors" -gt 0 ]; then
        output_result "DISK_ERRORS_LEVEL" "警告"
    else
        output_result "DISK_ERRORS_LEVEL" "正常"
    fi
}

# 检测内核panic/oops
check_kernel_panic() {
    local panic_count=0
    local oops_count=0

    if command -v dmesg &>/dev/null; then
        panic_count=$(dmesg 2>/dev/null | grep -ci "kernel panic" || echo "0")
        oops_count=$(dmesg 2>/dev/null | grep -ci "kernel oops\|BUG:" || echo "0")
    fi

    output_result "KERNEL_PANIC_COUNT" "$panic_count"
    output_result "KERNEL_OOPS_COUNT" "$oops_count"

    if [ "$panic_count" -gt 0 ]; then
        output_result "KERNEL_STABILITY_LEVEL" "严重"
    elif [ "$oops_count" -gt 5 ]; then
        output_result "KERNEL_STABILITY_LEVEL" "警告"
    else
        output_result "KERNEL_STABILITY_LEVEL" "正常"
    fi
}

# 检测服务崩溃重启记录
check_service_crashes() {
    local crash_count=0
    local crashed_services=""

    if command -v docker &>/dev/null; then
        local restarted_containers
        restarted_containers=$(docker ps -a --format "{{.Names}}: {{.RestartCount}}" 2>/dev/null | grep -v ": 0$" | grep -v ": $")

        if [ -n "$restarted_containers" ]; then
            crash_count=$(echo "$restarted_containers" | wc -l)
            crashed_services=$(echo "$restarted_containers" | tr '\n' ',' | sed 's/,$//')
        fi
    fi

    output_result "SERVICE_CRASH_COUNT" "$crash_count"

    if [ -n "$crashed_services" ]; then
        output_result "CRASHED_SERVICES" "$crashed_services"
    fi

    if [ "$crash_count" -gt 5 ]; then
        output_result "SERVICE_STABILITY_LEVEL" "严重"
    elif [ "$crash_count" -gt 0 ]; then
        output_result "SERVICE_STABILITY_LEVEL" "警告"
    else
        output_result "SERVICE_STABILITY_LEVEL" "正常"
    fi
}

# 检测systemd服务失败列表
check_systemd_failures() {
    if ! command -v systemctl &>/dev/null; then
        return
    fi

    local failed_services
    failed_services=$(systemctl list-units --state=failed --no-legend 2>/dev/null | awk '{print $1}' | tr '\n' ',' | sed 's/,$//')

    if [ -n "$failed_services" ]; then
        local failed_count
        failed_count=$(echo "$failed_services" | tr ',' '\n' | wc -l)
        output_result "SYSTEMD_FAILED_COUNT" "$failed_count"
        output_result "SYSTEMD_FAILED_SERVICES" "$failed_services"
        output_result "SYSTEMD_FAILED_LEVEL" "严重"
    else
        output_result "SYSTEMD_FAILED_COUNT" "0"
        output_result "SYSTEMD_FAILED_LEVEL" "正常"
    fi
}

# 检测OOM Killer记录
check_oom_killer() {
    local oom_count=0

    if command -v dmesg &>/dev/null; then
        oom_count=$(dmesg 2>/dev/null | grep -ci "out of memory" || echo "0")
    fi

    output_result "OOM_KILLER_COUNT" "$oom_count"

    if [ "$oom_count" -gt 0 ]; then
        output_result "OOM_LEVEL" "严重"
    else
        output_result "OOM_LEVEL" "正常"
    fi
}

# 检测日志文件大小
check_log_file_sizes() {
    local large_logs=""

    for log_file in /var/log/messages /var/log/syslog /var/log/kern.log; do
        if [ -f "$log_file" ]; then
            local log_size
            log_size=$(du -m "$log_file" 2>/dev/null | awk '{print $1}')
            if [ "$log_size" -gt 500 ]; then
                local log_name
                log_name=$(basename "$log_file")
                large_logs="${large_logs}${log_name}:${log_size}MB,"
            fi
        fi
    done

    large_logs=$(echo "$large_logs" | sed 's/,$//')

    if [ -n "$large_logs" ]; then
        output_result "LARGE_LOG_FILES" "$large_logs"
        output_result "LARGE_LOG_FILES_LEVEL" "警告"
    else
        output_result "LARGE_LOG_FILES" "无"
        output_result "LARGE_LOG_FILES_LEVEL" "正常"
    fi
}

# 检测/var/log/messages
check_messages_log() {
    local messages_file="/var/log/messages"

    if [ ! -f "$messages_file" ]; then
        if [ -f "/var/log/syslog" ]; then
            messages_file="/var/log/syslog"
        else
            return
        fi
    fi

    local error_count warn_count
    error_count=$(grep -c "ERROR" "$messages_file" 2>/dev/null || echo "0")
    warn_count=$(grep -c "WARN" "$messages_file" 2>/dev/null || echo "0")

    output_result "MESSAGES_ERRORS_COUNT" "$error_count"
    output_result "MESSAGES_WARNS_COUNT" "$warn_count"

    local log_size
    log_size=$(du -h "$messages_file" 2>/dev/null | awk '{print $1}')
    output_result "MESSAGES_LOG_SIZE" "$log_size"
}

# ==================== 主检测流程 ====================
main() {
    log_info "开始系统日志检测..."

    set +e

    check_kernel_errors 2>/dev/null || true
    check_disk_errors 2>/dev/null || true
    check_kernel_panic 2>/dev/null || true
    check_service_crashes 2>/dev/null || true
    check_systemd_failures 2>/dev/null || true
    check_oom_killer 2>/dev/null || true
    check_log_file_sizes 2>/dev/null || true
    check_messages_log 2>/dev/null || true

    log_info "系统日志检测完成"
}

main