Files
Document_Translator/app/api/health.py
beabigegg 6eabdb2f07 16th_fix
2025-09-04 18:34:05 +08:00

224 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
系統健康檢查 API
Author: PANJIT IT Team
Created: 2024-01-28
Modified: 2024-01-28
"""
from datetime import datetime
from flask import Blueprint, jsonify
from app.utils.helpers import create_response
from app.utils.logger import get_logger
from app.models.job import TranslationJob
from app.utils.timezone import format_taiwan_time, now_taiwan
health_bp = Blueprint('health', __name__, url_prefix='/health')
logger = get_logger(__name__)
@health_bp.route('', methods=['GET'])
def health_check():
"""系統健康檢查"""
try:
status = {
'timestamp': format_taiwan_time(datetime.utcnow(), "%Y-%m-%d %H:%M:%S"),
'status': 'healthy',
'services': {}
}
# 資料庫檢查
try:
from app import db
from sqlalchemy import text
db.session.execute(text('SELECT 1'))
status['services']['database'] = {'status': 'healthy'}
except Exception as e:
status['services']['database'] = {
'status': 'unhealthy',
'error': str(e)
}
status['status'] = 'unhealthy'
# Redis 檢查
try:
import redis
from flask import current_app
redis_client = redis.from_url(current_app.config['REDIS_URL'])
redis_client.ping()
status['services']['redis'] = {'status': 'healthy'}
except Exception as e:
status['services']['redis'] = {
'status': 'unhealthy',
'error': str(e)
}
# Redis 暫時異常不影響整體狀態(如果沒有使用 Celery
# LDAP 檢查
try:
from app.utils.ldap_auth import LDAPAuthService
ldap_service = LDAPAuthService()
if ldap_service.test_connection():
status['services']['ldap'] = {'status': 'healthy'}
else:
status['services']['ldap'] = {'status': 'unhealthy', 'error': 'Connection failed'}
except Exception as e:
status['services']['ldap'] = {
'status': 'unhealthy',
'error': str(e)
}
# LDAP 異常會影響整體狀態
status['status'] = 'unhealthy'
# 檔案系統檢查
try:
from pathlib import Path
from flask import current_app
upload_folder = Path(current_app.config['UPLOAD_FOLDER'])
# 檢查上傳目錄是否可寫
test_file = upload_folder / 'health_check.tmp'
test_file.write_text('health_check')
test_file.unlink()
status['services']['filesystem'] = {'status': 'healthy'}
except Exception as e:
status['services']['filesystem'] = {
'status': 'unhealthy',
'error': str(e)
}
status['status'] = 'unhealthy'
# 檢查 Dify API如果配置了
try:
from flask import current_app
if current_app.config.get('DIFY_API_KEY') and current_app.config.get('DIFY_API_BASE_URL'):
# 這裡會在實作 Dify 服務時加入連線測試
status['services']['dify_api'] = {'status': 'not_tested'}
else:
status['services']['dify_api'] = {'status': 'not_configured'}
except Exception as e:
status['services']['dify_api'] = {
'status': 'error',
'error': str(e)
}
return jsonify(status), 200 if status['status'] == 'healthy' else 503
except Exception as e:
logger.error(f"Health check error: {str(e)}")
return jsonify({
'timestamp': format_taiwan_time(datetime.utcnow(), "%Y-%m-%d %H:%M:%S"),
'status': 'error',
'error': str(e)
}), 500
@health_bp.route('/metrics', methods=['GET'])
def get_metrics():
"""系統指標"""
try:
# 統計任務狀態
from app import db
from sqlalchemy import func
job_stats = db.session.query(
TranslationJob.status,
func.count(TranslationJob.id)
).group_by(TranslationJob.status).all()
job_counts = {status: count for status, count in job_stats}
# 系統指標
metrics_data = {
'timestamp': format_taiwan_time(datetime.utcnow(), "%Y-%m-%d %H:%M:%S"),
'jobs': {
'pending': job_counts.get('PENDING', 0),
'processing': job_counts.get('PROCESSING', 0),
'completed': job_counts.get('COMPLETED', 0),
'failed': job_counts.get('FAILED', 0),
'retry': job_counts.get('RETRY', 0),
'total': sum(job_counts.values())
}
}
# 添加最近24小時的統計
from datetime import timedelta
yesterday = datetime.utcnow() - timedelta(days=1)
recent_jobs = db.session.query(
TranslationJob.status,
func.count(TranslationJob.id)
).filter(
TranslationJob.created_at >= yesterday
).group_by(TranslationJob.status).all()
recent_counts = {status: count for status, count in recent_jobs}
metrics_data['recent_24h'] = {
'pending': recent_counts.get('PENDING', 0),
'processing': recent_counts.get('PROCESSING', 0),
'completed': recent_counts.get('COMPLETED', 0),
'failed': recent_counts.get('FAILED', 0),
'retry': recent_counts.get('RETRY', 0),
'total': sum(recent_counts.values())
}
return jsonify(create_response(
success=True,
data=metrics_data
))
except Exception as e:
logger.error(f"Get metrics error: {str(e)}")
return jsonify(create_response(
success=False,
error='SYSTEM_ERROR',
message='取得系統指標失敗'
)), 500
@health_bp.route('/version', methods=['GET'])
def get_version():
"""取得版本資訊"""
try:
version_info = {
'application': 'PANJIT Document Translator',
'version': '1.0.0',
'build_date': '2024-01-28',
'python_version': None,
'flask_version': None
}
# 取得 Python 版本
import sys
version_info['python_version'] = sys.version
# 取得 Flask 版本
import flask
version_info['flask_version'] = flask.__version__
return jsonify(create_response(
success=True,
data=version_info
))
except Exception as e:
logger.error(f"Get version error: {str(e)}")
return jsonify(create_response(
success=False,
error='SYSTEM_ERROR',
message='取得版本資訊失敗'
)), 500
@health_bp.route('/ping', methods=['GET'])
def ping():
"""簡單的 ping 檢查"""
return jsonify({
'status': 'ok',
'timestamp': format_taiwan_time(datetime.utcnow(), "%Y-%m-%d %H:%M:%S"),
'message': 'pong'
})