163 lines
5.8 KiB
Python
163 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
生產環境監控腳本
|
|
監控系統效能、Redis狀態、資料庫連接等
|
|
"""
|
|
import time
|
|
import requests
|
|
import redis
|
|
import json
|
|
from datetime import datetime
|
|
import argparse
|
|
import sys
|
|
|
|
def check_app_health():
|
|
"""檢查應用程式健康狀態"""
|
|
try:
|
|
response = requests.get('http://localhost:12010/', timeout=10)
|
|
return {
|
|
'status': 'healthy' if response.status_code == 200 else 'unhealthy',
|
|
'status_code': response.status_code,
|
|
'response_time': response.elapsed.total_seconds()
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'status': 'unhealthy',
|
|
'error': str(e),
|
|
'response_time': None
|
|
}
|
|
|
|
def check_redis_health():
|
|
"""檢查 Redis 健康狀態"""
|
|
try:
|
|
r = redis.from_url('redis://localhost:6379/0')
|
|
r.ping()
|
|
info = r.info()
|
|
return {
|
|
'status': 'healthy',
|
|
'used_memory': info.get('used_memory_human'),
|
|
'connected_clients': info.get('connected_clients'),
|
|
'total_commands_processed': info.get('total_commands_processed'),
|
|
'keyspace_hits': info.get('keyspace_hits'),
|
|
'keyspace_misses': info.get('keyspace_misses')
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'status': 'unhealthy',
|
|
'error': str(e)
|
|
}
|
|
|
|
def check_onlyoffice_health():
|
|
"""檢查 OnlyOffice 健康狀態"""
|
|
try:
|
|
response = requests.get('http://localhost:12011/healthcheck', timeout=10)
|
|
return {
|
|
'status': 'healthy' if response.status_code == 200 else 'unhealthy',
|
|
'status_code': response.status_code,
|
|
'response_time': response.elapsed.total_seconds()
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'status': 'unhealthy',
|
|
'error': str(e),
|
|
'response_time': None
|
|
}
|
|
|
|
def get_docker_stats():
|
|
"""獲取 Docker 容器統計資訊"""
|
|
import subprocess
|
|
try:
|
|
result = subprocess.run(['docker', 'stats', '--no-stream', '--format',
|
|
'table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}'],
|
|
capture_output=True, text=True, timeout=10)
|
|
if result.returncode == 0:
|
|
return result.stdout
|
|
else:
|
|
return f"Error: {result.stderr}"
|
|
except Exception as e:
|
|
return f"Error getting docker stats: {str(e)}"
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='暫時規範系統監控工具')
|
|
parser.add_argument('--json', action='store_true', help='以JSON格式輸出')
|
|
parser.add_argument('--watch', '-w', type=int, metavar='SECONDS',
|
|
help='持續監控,指定刷新間隔秒數')
|
|
args = parser.parse_args()
|
|
|
|
def run_checks():
|
|
timestamp = datetime.now().isoformat()
|
|
|
|
# 執行各項健康檢查
|
|
app_health = check_app_health()
|
|
redis_health = check_redis_health()
|
|
onlyoffice_health = check_onlyoffice_health()
|
|
|
|
results = {
|
|
'timestamp': timestamp,
|
|
'app': app_health,
|
|
'redis': redis_health,
|
|
'onlyoffice': onlyoffice_health
|
|
}
|
|
|
|
if args.json:
|
|
print(json.dumps(results, indent=2, ensure_ascii=False))
|
|
else:
|
|
# 格式化輸出
|
|
print(f"\n🕒 監控時間: {timestamp}")
|
|
print("=" * 60)
|
|
|
|
# 應用程式狀態
|
|
status_icon = "✅" if app_health['status'] == 'healthy' else "❌"
|
|
print(f"{status_icon} 應用程式: {app_health['status']}")
|
|
if app_health.get('response_time'):
|
|
print(f" 響應時間: {app_health['response_time']:.3f}s")
|
|
if app_health.get('error'):
|
|
print(f" 錯誤: {app_health['error']}")
|
|
|
|
# Redis 狀態
|
|
status_icon = "✅" if redis_health['status'] == 'healthy' else "❌"
|
|
print(f"{status_icon} Redis: {redis_health['status']}")
|
|
if redis_health['status'] == 'healthy':
|
|
print(f" 記憶體使用: {redis_health['used_memory']}")
|
|
print(f" 連接數: {redis_health['connected_clients']}")
|
|
if redis_health['keyspace_hits'] and redis_health['keyspace_misses']:
|
|
hit_rate = redis_health['keyspace_hits'] / (redis_health['keyspace_hits'] + redis_health['keyspace_misses']) * 100
|
|
print(f" 快取命中率: {hit_rate:.2f}%")
|
|
elif redis_health.get('error'):
|
|
print(f" 錯誤: {redis_health['error']}")
|
|
|
|
# OnlyOffice 狀態
|
|
status_icon = "✅" if onlyoffice_health['status'] == 'healthy' else "❌"
|
|
print(f"{status_icon} OnlyOffice: {onlyoffice_health['status']}")
|
|
if onlyoffice_health.get('response_time'):
|
|
print(f" 響應時間: {onlyoffice_health['response_time']:.3f}s")
|
|
if onlyoffice_health.get('error'):
|
|
print(f" 錯誤: {onlyoffice_health['error']}")
|
|
|
|
# Docker 統計
|
|
print("\n📊 容器資源使用:")
|
|
print(get_docker_stats())
|
|
|
|
return results
|
|
|
|
try:
|
|
if args.watch:
|
|
while True:
|
|
try:
|
|
if not args.json:
|
|
print("\033[H\033[J") # 清空終端
|
|
run_checks()
|
|
if args.json:
|
|
print() # JSON輸出間的分隔
|
|
time.sleep(args.watch)
|
|
except KeyboardInterrupt:
|
|
print("\n👋 監控已停止")
|
|
sys.exit(0)
|
|
else:
|
|
run_checks()
|
|
except Exception as e:
|
|
print(f"❌ 監控執行錯誤: {str(e)}")
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
main() |