bifitnex-trading/check_errors.py
kroutony 24c3f033d2 Add check_errors.py cron job for API error monitoring
- New check_errors.py: scans last 1 hour of logs, sends Slack @channel only on errors
- Add to system crontab (every 5 min)
- Update setup.sh to include check_errors.py in crontab setup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:34:52 +00:00

69 lines
1.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""Check API errors in the last hour and send Slack alert if any found."""
import os
import sys
from datetime import datetime, timedelta
sys.path.insert(0, os.path.dirname(__file__))
import slack_notifier
LOG_FILES = [
"trading.log",
"sync_cost_basis.log",
"cron.log",
]
LOOKBACK_MINUTES = 60
def collect_recent_errors() -> list[str]:
since = datetime.now() - timedelta(minutes=LOOKBACK_MINUTES)
since_str = since.strftime("%Y-%m-%d %H:%M")
errors = []
for logfile in LOG_FILES:
path = os.path.join(os.path.dirname(__file__), logfile)
if not os.path.exists(path):
continue
with open(path) as f:
for line in f:
if "[ERROR]" not in line:
continue
# Only compare lines that start with a timestamp
if not line[:4].isdigit():
continue
if line[:16] >= since_str:
errors.append(line.rstrip())
return errors
def main():
errors = collect_recent_errors()
if not errors:
return
# Deduplicate and limit
unique = list(dict.fromkeys(errors))
display = unique[:20]
remaining = len(unique) - len(display)
lines = [
"<!channel>",
f"⚠️ *API 錯誤警報* (最近 {LOOKBACK_MINUTES} 分鐘,共 {len(unique)} 筆)",
"",
]
for e in display:
lines.append(f"• `{e[:200]}`")
if remaining > 0:
lines.append(f"\n...另有 {remaining} 筆錯誤")
slack_notifier._send({"text": "\n".join(lines)})
if __name__ == "__main__":
main()