跳转到主要内容

/api/health

主要健康检查端点。在单个管道调用中检查所有 Redis 支持的数据键和种子新鲜度元数据。 身份验证: 紧凑健康检查(?compact=1)对正常运行时间和关键字监控器公开。详细健康检查(不带 compact=1/api/health)和运维历史视图(?history=1)需要有效的运维/企业 API 密钥,因为它们会暴露规范的 Redis 键名、记录数和新鲜度阈值。浏览器来源仍须通过 api/_cors.js 中的 CORS 允许列表;无 Origin 头的请求(如服务器端监控器)仅在紧凑健康检查时被允许,除非包含运维密钥。健康响应从不缓存(Cache-Control: private, no-store, max-age=0CDN-Cache-Control: no-store)。 HTTP 方法: GET

查询参数

参数取值说明
compact1省略每个键的详细信息;仅返回有问题的键

响应状态码

HTTP 状态总体状态含义
200HEALTHY所有检查正常,无警告
200WARNING某些键过期或按需键为空,但无严重故障
200DEGRADED关键键为空,但 ≤3% 的所有探测键
200UNHEALTHY关键键为空,>3% 的所有探测键
401-无有效运维/企业 API 密钥时请求详细健康检查或历史记录
503REDIS_DOWN无法连接到 Redis —— 这是唯一返回非 200 状态码的状态
总体健康判定位于 JSON 的 status 字段中,而非 HTTP 状态码。除 REDIS_DOWN 外的每种状态都返回 200,这样警告级别的种子抖动不会触发 HTTP 状态监控器的抖动(参见 PR #2699)。REDIS_DOWN 返回 503,因为当 Redis 不可达时,端点无法评估任何内容,所以普通的 HTTP 探测必须看到失败。

响应体

{
  "status": "HEALTHY | WARNING | DEGRADED | UNHEALTHY | REDIS_DOWN",
  "summary": {
    "total": 194,
    "ok": 180,
    "warn": 5,
    "onDemandWarn": 9,
    "staleContent": 0,
    "crit": 0
  },
  "checkedAt": "2026-03-11T14:00:00.000Z",
  "checks": {
    "earthquakes": {
      "status": "OK",
      "records": 142,
      "seedAgeMin": 8,
      "maxStaleMin": 30
    }
  }
}
summary 字段:total 是每个探测键的一个条目(目前约 194 个,并随面板增加而增长)。warn 不包括按需为空的键 —— 这些键作为 onDemandWarn 单独显示,因此它们不会将总体判定推向 WARNINGstaleContentwarn 的一个子集(种子器新鲜但上游订阅源停止推进)。只有 critEMPTY/EMPTY_DATA)会驱动 DEGRADED/UNHEALTHY 使用 ?compact=1 时,checks 对象会被 problems 替换,仅包含非 OK 的键。

键分类

键被分为三个层级,决定告警严重程度:
层级为空时的严重程度说明
BootstrapCRIT启动时所需的种子数据。为空表示仪表板缺少关键数据
StandaloneCRIT(种子填充)/ WARN(按需)由种子循环或 RPC 处理器填充。按需键在首次请求之前预期为空
On-demandWARN由 RPC 调用懒加载填充。如果尚未有人请求数据,则为空是正常的

每个键的状态

状态严重程度含义
OK绿色数据存在,种子新鲜
OK_CASCADE绿色键为空但级联组中的同级键有数据(例如,战区态势后备链)
STALE_SEED警告数据存在但 seed-meta 年龄超过 maxStaleMin
STALE_CONTENT警告种子器新鲜但上游内容停止推进(冻结的订阅源);计入 summary.staleContent
COVERAGE_PARTIAL警告记录数低于该键声明的 minRecordCount(例如 10/13 个咽喉点或 139/174 个 PortWatch 港口活动国家)
SEED_ERROR警告seed-meta 报告上次种子运行的 status: "error"
REDIS_PARTIAL警告该键的 STRLEN/GET 上出现单个每命令 Redis 错误(非完全中断)
EMPTY_ON_DEMAND警告按需键尚无数据(在首次请求之前为预期情况);计入 summary.onDemandWarn
EMPTY严重Bootstrap 或种子填充的独立键无数据
EMPTY_DATA严重键存在但包含零条记录(且 0 对它来说不是有效状态)

级联组

某些键使用后备链。如果任何同级键有数据,空的同类键报告 OK_CASCADE
  • 战区态势: theaterPostureLive -> theaterPosture(过期)-> theaterPostureBackup
  • 军事航班: militaryFlights -> militaryFlightsStale
  • 流离失所: displacement(当前 UTC 年)-> displacementPrev(上一年,覆盖新年种子运行之前的 1 月 1 日窗口)
riskScores 有意比原始订阅源心跳更严格。其 recordCount 是实时信号密度覆盖:CII 刷新期间存在的与评分相关的 Tier-1 冲突、新闻和网络信号系列的数量。 冲突系列可由 ACLED 路径或 UCDP 事件订阅源满足,与 CII v8 评分器匹配。当这些订阅源可达但安静时,riskScores 仍可报告 COVERAGE_PARTIAL;底层订阅源的新鲜度由订阅源特定健康条目跟踪,这些订阅源在这些条目中发布种子元数据。 portwatchPortActivity 也使用 minRecordCount。低于 174 个国家的新鲜 seed-meta:supply_chain:portwatch-ports 记录会报告 COVERAGE_PARTIAL 而非 OK;部分运行仍可刷新按国家的 PortWatch 缓存条目,但规范国家列表和健康的 seed-meta 信号在完整 174 国覆盖恢复之前不会推进。

过期阈值(maxStaleMin)

SEED_META 中的部分阈值:
领域最大过期时间(分钟)说明
市场报价、加密货币、行业、地震、洞察30高频中继循环 / 关键事件数据
军事航班30近实时跟踪
预测、航班延误(FAA)90Polymarket / 机场快照
动乱12045 分钟 cron,2 小时宽限期
网络威胁240APT 数据更新频率较低
野火360FIRMS NRT 在数小时内累积
气候异常5403 小时 cron,3 倍节奏
BIS 扩展、World Bank、IMF2160-100800机构数据,每周/每月/每年
这些仅供参考;api/health.js 中的 SEED_META 是事实来源,每个条目都记录了其自身节奏的依据。

示例请求

# Full health check (requires an operator API key)
curl -s https://api.worldmonitor.app/api/health \
  -H "X-WorldMonitor-Key: $WORLDMONITOR_API_KEY" | jq .

# Compact (problems only)
curl -s "https://api.worldmonitor.app/api/health?compact=1" | jq .

# UptimeRobot / monitoring: check HTTP status code
curl -o /dev/null -s -w "%{http_code}" "https://api.worldmonitor.app/api/health?compact=1"
# Returns 503 only when Redis is unreachable (REDIS_DOWN); 200 for every other
# state — the verdict (HEALTHY/WARNING/DEGRADED/UNHEALTHY) is in the body's `status`.

/api/seed-health

用于种子循环新鲜度的专用端点。仅检查 seed-meta:* 键,不获取实际数据负载。 身份验证: 需要有效的 API 密钥或允许的来源。 HTTP 方法: GET

响应状态码

HTTP 状态总体状态含义
200healthy所有种子循环按时报告
200warning某些种子过期(年龄 > 2 倍间隔)或低于声明的覆盖率下限
200degraded某些种子完全缺失
401-无效或缺失的 API 密钥
503-Redis 不可用

响应体

{
  "overall": "healthy | warning | degraded",
  "checkedAt": 1710158400000,
  "seeds": {
    "seismology:earthquakes": {
      "status": "ok",
      "fetchedAt": 1710158100000,
      "recordCount": 142,
      "sourceVersion": null,
      "ageMinutes": 5,
      "stale": false
    },
    "market:stocks": {
      "status": "stale",
      "fetchedAt": 1710150000000,
      "recordCount": 85,
      "sourceVersion": null,
      "ageMinutes": 140,
      "stale": true
    },
    "supply_chain:portwatch-ports": {
      "status": "coverage_partial",
      "fetchedAt": 1710158100000,
      "recordCount": 139,
      "minRecordCount": 174,
      "sourceVersion": null,
      "ageMinutes": 5,
      "stale": true
    }
  }
}

过期逻辑

当种子的年龄超过配置间隔的 2 倍时,即被视为过期。这考虑了 cron/中继计时的正常抖动。具有显式 minRecordCount 的种子还会报告 coverage_partialstale: true,直到满足其覆盖率下限。
领域间隔(分钟)过期阈值(分钟)
预测、军事航班816
市场报价、地震、动乱1530
ETF 资金流、稳定币、咽喉点3060
服务状态、支出、野火60120
航运费率、卫星90-120180-240
GPS 干扰、流离失所360720
伊朗事件、UCDP210-5040420-10080

示例请求

curl -s https://api.worldmonitor.app/api/seed-health \
  -H "Origin: https://worldmonitor.app" | jq .

与监控工具的集成

UptimeRobot

使用 /api/health?compact=1 作为公开监控器 URL。HTTP 状态码仅区分 Redis 完全中断与其他所有情况:
  • 503 = REDIS_DOWN(Redis 不可达 —— 真正的硬中断)
  • 200 = 其他所有状态,包括 DEGRADEDUNHEALTHY
因此,仅基于 HTTP 状态的监控器能捕获完全的后端中断,但不能捕获降级/不健康的数据。对于这些情况,请添加关键字监控器。 将关键字监控器指向 https://api.worldmonitor.app/api/health?compact=1,并在紧凑令牌 "status":"HEALTHY"(冒号后无空格)从响应体中缺失时告警。紧凑模式序列化时不带缩进,因此无论格式如何,此确切令牌都是稳定的。
/api/health URL 现在是运维视图,无 API 密钥时返回 401。公开监控应始终使用 ?compact=1

自定义告警

解析 JSON 响应以构建细粒度告警:
# 对任何关键键告警
STATUS=$(curl -s "https://api.worldmonitor.app/api/health?compact=1")
CRIT=$(echo "$STATUS" | jq '.summary.crit')
if [ "$CRIT" -gt 0 ]; then
  echo "CRITICAL: $CRIT data keys empty"
  echo "$STATUS" | jq '.problems'
fi

端点之间的差异

方面/api/health/api/seed-health
范围数据键 + 种子元数据仅种子元数据
身份验证无(公开)API 密钥或允许的来源
获取的数据完整 Redis 值(用于计数记录)seed-meta:*
HTTP 503REDIS_DOWN(DEGRADED/UNHEALTHY 返回 200)否(除非 Redis 宕机,否则始终为 200)
最适合正常运行时间监控、仪表板健康状态调试种子循环问题
响应大小较大(约 194 个键及记录计数)较小(仅 seed-meta 领域)