kp-023
监控、日志与告警
前置知识
本文基于模型知识整理。
一句话定义
采集系统的可观测性 = 结构化日志(出了什么)+ 指标水位(系统健康吗)+ 告警(坏了快喊人),其中「数据量骤降告警」是爬虫独有的生命线。
为什么重要
爬虫是长跑型系统:站点改版、接口失效、限流升级都会让它「安静地失效」——进程还在跑,数据却是空的。没有监控的任务最贵的一次故障是:两周后才有人发现数据早就没了。
前置知识
kp-018(有工程化任务可观测)。
核心概念
- 核心指标:请求成功率、429/403 率、QPS、每小时入库条数、解析失败率、关键字段空值率。
- 结构化日志:JSON Lines 格式,每行带
ts/level/url/status/duration/err,可被机器检索。 - 心跳:任务周期性上报「活着 + 本窗口产出 N 条」。
- 假成功检测:HTTP 200 但数据为空/字段全空 —— 爬虫最高频的真实故障。
原理与机制
指标采集与告警的最小实现(进程内计数 + 阈值判断):
import json, time, logging
metrics = {"ok": 0, "http_err": 0, "parse_empty": 0}
def log_event(level, **kw):
rec = {"ts": time.strftime("%Y-%m-%d %H:%M:%S"), "level": level, **kw}
print(json.dumps(rec, ensure_ascii=False)) # JSONL → 文件/日志平台
def heartbeat():
total = metrics["ok"] + metrics["http_err"] + metrics["parse_empty"]
log_event("INFO", event="heartbeat", **metrics, total=total)
rate = metrics["ok"] / total if total else 0
if total >= 100 and rate < 0.8: # 成功率阈值 80%
log_event("CRITICAL", event="alert", reason="low_success_rate", rate=round(rate, 3))
if total >= 100 and metrics["parse_empty"] / total > 0.3: # 空数据水位
log_event("CRITICAL", event="alert", reason="empty_data_spike") # 疑似改版!
告警阈值设计(经验基线,按任务校准):
成功率 < 80% (连续两个心跳窗口) → 告警
入库速率 < 历史 50% 且持续 1h → 告警(站点改版/接口失效高概率)
429 率 > 10% → 自动降速并告警( kp-017 联动 )
关键字段空值率 > 30% → 告警(解析器失效或页面结构变化)
「数据量水位」比「进程存活」更重要:进程活着但抓不到东西,是爬虫监控区别于普通服务的核心点。
实例或案例
某商品价格监控连续运行三个月无告警;某日站点前端改版把价格 class 改名,监控在 1 小时后触发 empty_data_spike 告警,当日修复。若无此告警,价格断档两周将直接污染 kp-027 的月度均价分析。
常见误区
- 误区一:
print当日志。 无时间戳、无结构、翻文件靠肉眼;JSONL + 级别是最低标准。 - 误区二:只监控「进程在不在」。 爬虫的病多数是「活着但白跑」;入库速率与空值率才是生命体征。
- 误区三:告警无分级。 单条失败重试即可恢复的事件不该吵人;告警必须绑定「需要人介入」的语义,否则狼来了效应让真告警被忽略。
自测题
- 爬虫监控区别于普通服务监控的关键指标是什么?
答:每小时入库条数与关键字段空值率——检测「进程活着但数据断了」的假成功。
- 为什么必须做假成功检测?
答:站点对异常访问常返回 200+空内容,状态码层面看不出故障;需用内容/字段水位兜底。
- 结构化日志相比 print 的两大收益?
答:可机器检索统计(算成功率/延迟分布);字段统一便于接日志平台与告警规则。
与其他知识点的关系
kp-016 的拦截升级会首先反映在 429/403 率上;kp-025 的质量指标依赖本篇日志数据;kp-033 把监控列为项目工作流的验收项。
延伸阅读
Python logging 官方文档(Formatter/Handler);本库 kp-033(监控在工作流中的位置)。