Supabase 日志查询迁到统一 logs 表:这套 ClickHouse SQL 可以直接抄
Supabase 的日志查询换了一套查询面之后,最难受的不是”要改”,而是”改完返回空,也不知道是没数据还是写错了”。这篇把能直接复制的查询和验收办法放在一处。
以下写法取自 Supabase 官方的日志查询文档与 Management API 示例。
先记住三条会咬人的规则
第一,来源字段是 source,不是 source_name。 7 月 23 日那份迁移公告的示例代码写的是 WHERE source_name = 'edge_logs',但官方现行文档里的示例与实际查询面用的是 source。照抄公告不会报错,只会静默返回空结果——你会以为那天没有日志。
第二,log_attributes 里的值全是字符串。 想比较数字必须先转:
toInt32OrZero(log_attributes['response.status_code']) between 500 and 599
toInt32OrZero 会把缺失值和非数字值都变成 0,所以别把这个 0 当成真实的响应码或耗时。取字段时保留完整的点分路径,不要自己拆层。
第三,select * 和 count(*) 会被拒绝。 查询面要求列出具体字段,聚合要用 count()。同时必须给一个带边界的时间范围,API 单次窗口不超过 24 小时。
四条可以直接抄的查询
1. 最近的 API 网关 5xx
select timestamp, id,
toInt32OrZero(log_attributes['response.status_code']) as status,
log_attributes['request.path'] as path
from logs
where source = 'edge_logs'
and toInt32OrZero(log_attributes['response.status_code']) between 500 and 599
order by timestamp desc
limit 100;
2. 连接失败类错误
select timestamp, id, event_message
from logs
where source = 'postgres_logs'
and event_message ilike '%connection%'
and match(event_message, '(?i)failed|refused|timeout')
order by timestamp desc
limit 100;
3. 不知道有哪些字段可用时,先把 key 摸出来
select arrayJoin(mapKeys(log_attributes)) as key, count() as events
from logs
where source = 'postgres_logs'
group by key
order by events desc
limit 100;
这条应该在迁移任何一条旧查询之前先跑一遍,比你猜字段名快。
4. 走 Management API
把上面的 SQL 存成 logs.sql:
curl --get "https://api.supabase.com/v1/projects/$PROJECT_REF/analytics/endpoints/logs" \
--header "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
--data-urlencode "[email protected]" \
--data-urlencode "iso_timestamp_start=$START" \
--data-urlencode "iso_timestamp_end=$END"
$START 与 $END 用 UTC 时间戳,跨度不超过 24 小时。不带 sql 参数时,这个端点只返回 API Gateway 的事件——如果你发现查出来全是网关日志,先确认自己传了 sql。
迁移自查清单
- 端点路径从
analytics/endpoints/logs.all改成analytics/endpoints/logs - 源表(如
FROM edge_logs)改成FROM logs+WHERE source = '...' - 所有
CROSS JOIN unnest(metadata)的逐层展开,换成log_attributes['a.b.c'] - 数值比较外面套
toInt32OrZero() - 去掉
select *和count(*) - 脚本里显式传
iso_timestamp_start/iso_timestamp_end,别指望服务端替你兜 - 用 MCP 的,把
mcp-server-supabase升到 v0.10.0,并改用query_logs(execute_sql是查 Postgres 的,不查 ClickHouse 日志) - Supabase CLI 查不了 ClickHouse 日志,只能用上面的 Management API
验收标准:怎么证明自己迁对了
别用”跑通了”当验收。三条硬标准:
- 非空校验:同一个时间窗、同一个源,新查询返回的行数不为 0。是 0 就先怀疑字段名,不要下”那段时间没日志”的结论。
- 对照校验:挑一个已知会出现的事件(比如你手动打一次 404),新查询必须能在 5 分钟内查到它。查不到说明
source或log_attributes的路径写错了。 - 计数校验:把旧查询在还能用的时候跑一次记下行数,迁移后同一窗口的行数应在同一量级。差一个数量级基本就是
source写成了source_name或者漏了时间范围。
三条都过才算迁完。只过第一条,是最容易自欺的那种”好了”。
什么情况别折腾
- 你只在 Dashboard 的 Logs Explorer 里看日志——那不受影响,什么都不用改。
- 你的日志消费全靠第三方可观测平台接的 Postgres 或 webhook,没直接调
logs.all——同样不用改。 - 你的脚本一年跑不了两次、坏了有人肉眼看——那就等它真报错了再改,别为它排期。
参考:https://supabase.com/docs/guides/observability/advanced-log-filtering