运维

监控与告警

/healthz 与 /metrics、Prometheus 抓取、告警条件与 Webhook 负载格式、日志。

/healthz

GET /healthz 返回 200 与纯文本 ok,不需要认证。它只表示进程在运行、HTTP 服务能响应,不检查数据库、渠道或任务队列。适合做进程存活检查与外部可用性探测;渠道是否健康看指标与告警。

/healthz 与 /metrics 自身的请求不计入 HTTP 指标。

/metrics

GET /metrics 以 Prometheus 文本格式输出指标,与业务共用同一个端口。

访问控制:只有客户端地址落在 IMGYOUNG_METRICS_ALLOW 内的请求才放行(变量未设置时为回环与私网段),其余返回 403;把变量设为空串(或只有空白)则对谁都不开放。客户端地址按反向代理与 HTTPS里的规则解析。指标里有路由模板、渠道名与用量,不应对公网开放:

  • 公网入口(反代)一律不转发 /metrics,deploy/ 里的 Caddy 与 Nginx 示例都对它返回 404;
  • 让 Prometheus 从内网直接访问 ImgYoung 的监听地址;
  • IMGYOUNG_TRUSTED_PROXIES 要配对。配错时经反代的请求都显得来自反代自身,反代地址又在放行网段内的话,转发了 /metrics 的反代会把指标暴露给所有人。

指标清单

全部业务指标以 imgyoung_ 为前缀:

指标类型标签含义
imgyoung_http_requests_totalcountermethod、route、statusHTTP 请求数。route 是路由模板(如 /i/{id}),不是原始路径
imgyoung_http_request_duration_secondshistogrammethod、routeHTTP 请求处理时延(秒)
imgyoung_upload_duration_secondshistogramoutcome上传管道耗时(秒)。ok 成功;rejected 输入或配额不合规;failed 基础设施失败
imgyoung_channel_puts_totalcounterchannel、result向渠道写对象的次数,含上传时的同步写入与异步补齐;result 为 ok / error
imgyoung_channel_storage_bytesgaugechannel渠道逻辑用量(字节),按已就绪副本的图片大小求和;每隔「用量上报间隔」刷新
imgyoung_channels_totalgauge已装载的渠道数,含不健康的,不含清理中和装载失败的
imgyoung_channels_healthy_totalgauge当前健康的渠道数
imgyoung_variant_lookups_totalcounterresult衍生图缓存查找次数;result 为 hit / miss
imgyoung_queue_jobs_waitinggauge任务队列里等待执行的任务数(可认领、已排程与待重试);抓取时查询,查询失败为 NaN
imgyoung_queue_jobs_runninggauge任务队列里正在执行的任务数;同上

此外还有 Prometheus Go 客户端自带的 go_*(运行时)与 process_*(进程)指标。

Prometheus 抓取配置

prometheus.yml
scrape_configs:
  - job_name: imgyoung
    static_configs:
      - targets: ["10.0.0.5:8721"]   # ImgYoung 的内网地址与端口

Prometheus 不在默认放行的私网段内时,把它的地址加进 IMGYOUNG_METRICS_ALLOW(连同仍需要的默认网段一起写,设置后会整体替换默认值)。

几条常用的告警表达式:

PromQL
# 有渠道不健康
imgyoung_channels_healthy_total < imgyoung_channels_total

# 渠道写入持续出错
sum by (channel) (rate(imgyoung_channel_puts_total{result="error"}[10m])) > 0

# 上传因基础设施失败
sum(rate(imgyoung_upload_duration_seconds_count{outcome="failed"}[10m])) > 0

# 任务队列积压
imgyoung_queue_jobs_waiting > 1000

告警

告警由评估循环产生:启动时评估一次,之后每隔「健康检查间隔」(health_check_seconds,出厂 60 秒)评估一次。每轮按现状判断哪些条件成立,与未恢复的告警对账——新成立的开启,不再成立的自动恢复。同一类型、同一对象至多有一条未恢复的告警;条件持续成立期间,详情会随每轮评估更新。

类型界面名称对象成立条件
channel_unhealthy渠道不健康渠道名在役渠道最近一次健康探测失败,或渠道装载失败;详情为失败原因
replication_failed副本补齐失败渠道名该渠道上有补齐失败的副本;详情含份数。渠道恢复健康后失败的副本会被重试
channel_quota_exceeded渠道用量超阈值渠道名设置了「渠道用量告警阈值」且该渠道用量超过它
drain_failed渠道排空失败渠道名「删除并清理」渠道时,删除渠道上的图片副本或本服务写的系统对象(含元数据库快照)第一次失败即开启,详情为失败原因(任务自身超时或停机中断不算)。排空会按退避一直自动重试,渠道清空后自动移除,告警随之恢复;凭证已失效或存储桶已不存在时,在「存储渠道」页对该渠道「直接移除」,远端对象保留
backup_failed备份失败空最近一次元数据库备份失败:没有健康渠道、生成快照失败,或有渠道没写成。详情为失败原因,部分渠道没写成时形如 快照 imgyoung-20261016-083000.123.db 有 1/3 个渠道未写成: 渠道 "r2-main": 上传快照: …,写成的渠道保留这份快照

backup_failed 依据的是本进程内最近一次备份的结果,进程重启后在下一次备份失败之前不会再出现。

在哪里看:后台「总览」页的「告警」卡片列出当前未恢复的告警,点「历史记录」进入「设置 → 告警历史」,那里分页列出包括已恢复在内的全部告警。告警的开启与恢复也会写入日志(告警开启、告警恢复)。

Webhook

在「设置 → 运行配置 → 告警与审计 → 告警 Webhook 地址」填入一个 http / https 地址后,每条告警在开启与恢复时各 POST 一次 JSON(Content-Type: application/json):

开启
{
  "kind": "channel_unhealthy",
  "target": "r2-main",
  "message": "连接超时",
  "status": "open",
  "opened_at": "2026-10-15 08:30:00"
}
恢复
{
  "kind": "channel_unhealthy",
  "target": "r2-main",
  "message": "连接超时",
  "status": "resolved",
  "opened_at": "2026-10-15 08:30:00",
  "resolved_at": "2026-10-15 09:05:00"
}
字段说明
kind告警类型,取值见上表
target告警对象(渠道名);backup_failed 为空串
message最近一次评估得到的描述(中文)
statusopen(开启)或 resolved(恢复)
opened_at开启时刻,UTC,格式 YYYY-MM-DD HH:MM:SS
resolved_at恢复时刻,同上格式;只在 resolved 时出现

投递规则:

  • 接收方返回 2xx 即视为成功;连接失败、超时(10 秒)或非 2xx 都会在下一轮评估时重试,直到成功;
  • 同一条告警总是先投递开启、再投递恢复;
  • 请求不带签名或认证头,需要校验来源时把密钥放进 URL(如查询参数),并使用 https;
  • 告警开启时没有配置 Webhook 的,该次转折直接记为已投递,之后再配置也不会补发;
  • 负载格式是固定的。要推送到即时通讯工具,需要一个转换格式的中转服务。

日志

  • 日志写到标准错误,格式是 Go log/slog 的文本格式:每行以 time=、level=、msg= 开头,后接 key=value 形式的字段,消息为中文。级别固定为 INFO 及以上,没有调整级别的配置项。
  • 查看:systemd 用 journalctl -u imgyoung,Docker 用 docker logs imgyoung,Compose 用 docker compose logs imgyoung。
  • 凭证不进日志:渠道配置参数不出现在任何日志与错误信息里,Cloudflare API Token 只在内存中以明文存在,配置修改的审计记录也只写 (已配置) 或 (空);上传 Token 与会话只存哈希。唯一会打印的密码是首次启动(或重置密码后)播种的出厂密码,它本就是公开值。

排障时值得留意的几行:

日志含义
ImgYoung 已启动启动完成,附版本、提交、实际监听地址与数据目录
已生成主密钥文件,请立即备份……数据目录里是全新的数据库、又没有主密钥,本次启动新生成了 master.key。不是首次部署时出现它,多半是数据目录指错了或数据卷没挂上
启动失败,err 含 主密钥与数据库不符 或 找不到主密钥数据库记有主密钥指纹,而当前主密钥与它不符,或 IMGYOUNG_MASTER_KEY 未设置且 master.key 不存在。换回原来的主密钥再启动
CDN purge 已启用(Cloudflare) / CDN purge 未启用……启动时 CDN 缓存清除的配置状态
渠道装载失败,本渠道跳过,健康检查时重试渠道配置解不开或驱动构造失败;渠道列表显示为不健康,原因以 装载失败: 开头,每轮健康检查重试装载
告警开启 / 告警恢复告警状态变化
元数据库快照已备份一份快照写进了一个渠道,每个渠道一行,字段 channel、key、bytes
启动备份未完成 / 定时备份未完成这一轮备份失败,err 与 backup_failed 告警的详情相同
渠道对账完成每日对账 GC 的结果,字段 objects、bytes、foreign(库里没有记录,键名不是本服务格式或早于渠道绑定时刻的对象,只计数不回收)、orphans_deleted、phantoms_requeued,见备份与恢复
渠道已清理完毕并删除「删除并清理」的渠道清完并删除了记录,字段 objects(删除的图片副本数)、system_objects(删除的系统对象数,含元数据库快照与深探测残留)
收到停机请求,优雅停机后由进程管理器拉起后台触发了从快照恢复
已用暂存快照换入元数据库,原库留存快照已换入,附原库留存路径
换入快照后已把渠道绑定时刻重置为当前时刻,快照之后写入渠道的对象不会被对账回收换入快照后的收尾,字段 channels 为重置的渠道数,见备份与恢复

本页目录