diff --git a/app/__init__.py b/app/__init__.py index 04a1a23..eab2e5d 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -2,6 +2,7 @@ import logging import os from flask import Flask, redirect, url_for from flask_migrate import Migrate +from zoneinfo import ZoneInfo from app.config import DevelopmentConfig, ProductionConfig from app.extensions import db, login_manager, scheduler @@ -97,6 +98,22 @@ def register_template_filters(app: Flask) -> None: return expr + @app.template_filter("to_cst") + def to_cst(dt, fmt: str = "%Y-%m-%d %H:%M:%S"): + """ + 将 UTC 时间转换为中国标准时间字符串,如果值为空则返回空字符串。 + """ + if not dt: + return "" + try: + tz = ZoneInfo(app.config.get("SCHEDULER_TIMEZONE", "Asia/Shanghai")) + # 如果是 naive datetime,认为是 UTC + if dt.tzinfo is None: + dt = dt.replace(tzinfo=ZoneInfo("UTC")) + return dt.astimezone(tz).strftime(fmt) + except Exception: + return str(dt) + def init_scheduler(app: Flask) -> None: """ diff --git a/app/services/api_executor.py b/app/services/api_executor.py index 9c62b5b..9de43a5 100644 --- a/app/services/api_executor.py +++ b/app/services/api_executor.py @@ -26,8 +26,7 @@ def _parse_json_field(raw: Optional[str]) -> Optional[Dict[str, Any]]: def execute_api(api_config: ApiConfig) -> None: """ - Execute an API call based on ApiConfig, apply retry logic, and persist ApiCallLog. - Only the final attempt is logged to avoid noise. + 根据配置调用 API,带重试,并将每次尝试都记录为日志(保留历史)。 """ request_time = datetime.utcnow() headers = _parse_json_field(api_config.headers) or {} @@ -42,13 +41,14 @@ def execute_api(api_config: ApiConfig) -> None: delay = max(api_config.retry_interval_seconds, 1) timeout = max(api_config.timeout_seconds, 1) attempt = 0 - last_response: Optional[Response] = None + total_attempts = retries + 1 last_error: Optional[str] = None - start_ts = time.time() - while attempt <= retries: + while attempt < total_attempts: + last_response: Optional[Response] = None + start_ts = time.time() + attempt += 1 try: - attempt += 1 last_response = requests.request( method=api_config.http_method, url=api_config.url, @@ -60,35 +60,38 @@ def execute_api(api_config: ApiConfig) -> None: ) if 200 <= last_response.status_code < 300: last_error = None - break - last_error = f"Non-2xx status: {last_response.status_code}" + else: + body_snippet = (last_response.text or "")[:200] + last_error = f"Non-2xx status: {last_response.status_code}, body: {body_snippet}" except requests.RequestException as exc: - last_response = None last_error = str(exc) - if attempt <= retries: + + duration_ms = int((time.time() - start_ts) * 1000) + success = last_error is None + + log_entry = ApiCallLog( + api_id=api_config.id, + request_time=request_time, + response_time=datetime.utcnow(), + success=success, + http_status_code=last_response.status_code if last_response else None, + error_message=(f"[第{attempt}次尝试/{total_attempts}] {last_error}" if last_error else None), + response_body=(last_response.text[:2000] if last_response and last_response.text else None), + duration_ms=duration_ms, + ) + db.session.add(log_entry) + try: + db.session.commit() + except Exception: + logger.exception("Failed to persist ApiCallLog for api_id=%s", api_config.id) + db.session.rollback() + + if success: + break + if attempt < total_attempts: time.sleep(delay) - duration_ms = int((time.time() - start_ts) * 1000) - success = last_error is None - - log_entry = ApiCallLog( - api_id=api_config.id, - request_time=request_time, - response_time=datetime.utcnow(), - success=success, - http_status_code=last_response.status_code if last_response else None, - error_message=last_error, - response_body=(last_response.text[:2000] if last_response and last_response.text else None), - duration_ms=duration_ms, - ) - db.session.add(log_entry) - try: - db.session.commit() - except Exception: - logger.exception("Failed to persist ApiCallLog for api_id=%s", api_config.id) - db.session.rollback() - - if not success: + if last_error: logger.warning("API call failed for api_id=%s error=%s", api_config.id, last_error) diff --git a/app/templates/apis/list.html b/app/templates/apis/list.html index cf3ae2d..2cf045f 100644 --- a/app/templates/apis/list.html +++ b/app/templates/apis/list.html @@ -50,6 +50,9 @@ 编辑 +
+ +