#!/usr/bin/env bash # monitor_rate_limits.sh # Checks OpenClaw usage log for recent rate_limit / 429 entries and acts. # Use user-local paths to avoid sudo permissions MONITOR_DIR=/home/alex/clawd/monitor LOG=${MONITOR_DIR}/usage.log COUNT_FILE=${MONITOR_DIR}/openclaw_rate_limit_count THRESHOLD=2 WINDOW_MIN=10 DISCORD_USER=231473537649475588 mkdir -p "$MONITOR_DIR" : > "${MONITOR_DIR}/monitor_last" || true # Primary source: existing local DB/collected metrics (preferred) # Fallback: global /var/log/openclaw/usage.log if present SRC_LOG=/var/log/openclaw/usage.log # Helper to send Discord alert via OpenClaw CLI (if available) send_discord_alert(){ local msg="$1" # Try OpenClaw message send (best effort) if command -v openclaw >/dev/null 2>&1; then openclaw message send --channel discord --to "$DISCORD_USER" --message "$msg" >/dev/null 2>&1 || true fi } # Look for rate_limit/429 in collected metrics DB first FOUND=0 if command -v sqlite3 >/dev/null 2>&1 && [ -f ~/clawd/data/usage.db ]; then lines=$(sqlite3 ~/clawd/data/usage.db "SELECT value,extra FROM metrics WHERE key LIKE '%logs%' ORDER BY ts DESC LIMIT 5;" 2>/dev/null || true) if echo "$lines" | grep -E "rate_limit|429" >/dev/null 2>&1; then FOUND=1 fi fi # If not found in DB, search the system log (fallback) if [ $FOUND -eq 0 ] && [ -f "$SRC_LOG" ]; then if grep -E "rate_limit|429" "$SRC_LOG" --binary-files=without-match >/dev/null 2>&1; then FOUND=1 RECENTS=$(grep -E "rate_limit|429" "$SRC_LOG" | tail -n 50) fi fi # Also check local monitor log for quick indicators if [ $FOUND -eq 0 ] && [ -f "$LOG" ]; then if grep -E "rate_limit|429" "$LOG" >/dev/null 2>&1; then FOUND=1 RECENTS=$(grep -E "rate_limit|429" "$LOG" | tail -n 50) fi fi # If still not found, try journalctl for openclaw unit if [ $FOUND -eq 0 ] && command -v journalctl >/dev/null 2>&1; then RECENTS=$(journalctl -u openclaw --no-pager --since "${WINDOW_MIN} minutes ago" | grep -E "rate_limit|429" || true) if [ -n "$RECENTS" ]; then FOUND=1 fi fi if [ $FOUND -eq 1 ]; then prev=0 [ -f "$COUNT_FILE" ] && prev=$(cat "$COUNT_FILE" 2>/dev/null || echo 0) cur=$((prev+1)) echo "$cur" > "$COUNT_FILE" echo "$(date -Iseconds) Detected rate_limit/429 entries (count=$cur)." >> "$LOG" echo "$RECENTS" >> "$LOG" # provider-specific detection alert_msg="⚠️ Rate limit hit - switching to fallback" if echo "$RECENTS" | grep -qi "anthropic"; then alert_msg="⚠️ Anthropic rate limit hit - switching to fallback" elif echo "$RECENTS" | grep -Ei "gemini|google" >/dev/null 2>&1; then alert_msg="⚠️ Gemini rate limit hit" elif echo "$RECENTS" | grep -qi "openrouter"; then alert_msg="⚠️ OpenRouter rate limit hit" elif echo "$RECENTS" | grep -Ei "copilot|github-copilot" >/dev/null 2>&1; then alert_msg="⚠️ Copilot rate limit hit" fi if [ "$cur" -ge "$THRESHOLD" ]; then echo "Threshold reached: restarting OpenClaw gateway and logging alert." >> "$LOG" if command -v openclaw >/dev/null 2>&1; then openclaw gateway restart || echo "gateway restart failed" >> "$LOG" fi echo "$(date -Iseconds) ALERT: $alert_msg" >> "$LOG" send_discord_alert "$alert_msg" # reset counter echo "0" > "$COUNT_FILE" fi else echo "No recent rate_limit/429 entries found." >> "$LOG" echo "0" > "$COUNT_FILE" fi