目标
REST 访问日志天然带端点名,吵闹的客户端一次 sort 就现形;而没有操作名的 GraphQL 只会给你一整面 POST /graphql 的墙。指纹化解决了这个问题:为每个请求记录操作名与规范化查询文本的哈希,一天之内你就能拿到“谁在真实使用 API、每种形状有多贵”的排行榜。
步骤要点
- 在 Apollo Server 插件的 willSendResponse 里输出操作名(匿名则记 anonymous)、查询文本哈希前 12 位与嵌套深度到结构化日志。
- 用 jq 聚合 name+hash 出现次数并降序排列,找出调用量最大的操作,逼近榜首的匿名哈希就是没署名的大户。
- 再按深度排序:列表字段上 12 层嵌套立刻显形,解释了单请求成本离群的原因。
- 给服务端加 depthLimit(8) 校验规则,超深匿名查询被明确拒绝,第三方被迫注册具名且经评审的操作。
- 持续观察排行榜变化,把新增的高频操作逐步迁入持久化查询注册表。
排错提示
匿名查询占大头时,对一方客户端在 CI 里强制操作命名,对第三方启用持久化查询只发哈希;深度高但成本低说明分支只返回标量,应结合字段级成本权重再拒绝;同一逻辑查询哈希漂移是空白与注释造成的,需先用 graphql print 规范化再哈希或改用操作名加变量签名。
适用边界
指纹看到的是查询文本而非执行成本,看似便宜的查询配上传入的大变量值依然昂贵;持久化查询需要注册表工具链,并给客户端增加一个发布步骤。
代码示例
# Rank operations by volume
grep '"op"' access.log | jq -r '.name + " " + .hash' \
| sort | uniq -c | sort -rn | head -15