#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" LOGS_DIR="${ROOT_DIR}/logs" OLDER_THAN_DAYS="${OLDER_THAN_DAYS:-1}" WARN_TOTAL_MB="${WARN_TOTAL_MB:-300}" WARN_CANDIDATE_FILES="${WARN_CANDIDATE_FILES:-500}" # Keep in sync with archive-logs.sh patterns. PATTERN_PATHS=( "logs/e2e-automation/run_*.log" "logs/e2e-automation/report_*.md" "logs/prd-review/review_*.md" "logs/prd-review/claude_apply_*.md" "logs/prd-review/execution_report_*.md" "logs/prd-review/optimization_report_*.md" ) log() { echo "[logs-health] $*"; } to_mb() { local bytes="$1" awk -v b="${bytes}" 'BEGIN { printf "%.2f", b / 1024 / 1024 }' } if [[ ! -d "${LOGS_DIR}" ]]; then log "logs directory not found, skip." exit 0 fi cutoff_epoch="$(date -d "${OLDER_THAN_DAYS} days ago" +%s)" total_bytes="$(du -sb "${LOGS_DIR}" | awk '{print $1}')" total_mb="$(to_mb "${total_bytes}")" candidate_files=0 shopt -s nullglob for pattern in "${PATTERN_PATHS[@]}"; do for abs in "${ROOT_DIR}"/${pattern}; do [[ -f "${abs}" ]] || continue mtime_epoch="$(stat -c %Y "${abs}")" if [[ "${mtime_epoch}" -lt "${cutoff_epoch}" ]]; then candidate_files=$((candidate_files + 1)) fi done done shopt -u nullglob log "total_size_mb=${total_mb} (threshold=${WARN_TOTAL_MB})" log "archive_candidates_older_than_${OLDER_THAN_DAYS}d=${candidate_files} (threshold=${WARN_CANDIDATE_FILES})" if awk -v a="${total_mb}" -v b="${WARN_TOTAL_MB}" 'BEGIN { exit !(a > b) }'; then log "WARN: logs directory is large. Consider: npm run logs:archive:apply" fi if [[ "${candidate_files}" -gt "${WARN_CANDIDATE_FILES}" ]]; then log "WARN: many archive candidates detected. Consider archiving historical logs." fi log "top 5 largest log files:" find "${LOGS_DIR}" -type f -printf '%s %p\n' | sort -nr | sed -n '1,5p' | awk ' { mb = $1 / 1024 / 1024 $1 = "" sub(/^ /, "", $0) printf " - %.2f MB %s\n", mb, $0 } ' exit 0