mcpField
C
clickhouse-logs-queries

clickhouse-logs-queries

github.com/supabase数据与数据库114.3k90 次安装今天更新
代码仓库

关于 clickhouse-logs-queries

clickhouse-logs-queries 是用于查询和迁移 Supabase 日志的技能,面向使用 Logs Explorer 或 ClickHouse 查询日志的开发者。它说明统一 logs 表、来源筛选、属性映射及 BigQuery 到 ClickHouse 的转换方式。

主要功能

  1. 01查询统一的 ClickHouse logs 表
  2. 02按服务来源筛选日志
  3. 03读取 log_attributes 字段
  4. 04将 BigQuery 查询转换为 ClickHouse
  5. 05提供查询示例与实践规范

适用场景

  1. 01编写或审查 Supabase 日志查询
  2. 02在日志中筛选特定服务和字段
  3. 03将旧 BigQuery 查询迁移至 ClickHouse

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/supabase/supabase --skill clickhouse-logs-queries

安装后在 Claude Code 中输入/clickhouse-logs-queries确认已加载。

附带文件references/codebase-integration.mdreferences/bigquery-migration.md

详细介绍

查询 Supabase 日志(ClickHouse)

Supabase 日志都存储在单个 ClickHouse logs 表中,由 logs.all.otel 分析端点提供服务。堆栈各部分的每一行日志在此表中都对应一行,并通过 source 列标记。这取代了旧的 BigQuery 模式:每个服务各有一张表,字段则通过 cross join unnest(metadata) 获取。

有两类工作会用到此技能,它们共用同一套 SQL 模型:

  1. 编写或审查日志查询(在 Logs Explorer 中,或在其他需要原始 ClickHouse 日志查询的地方)。请从本文档开始。
  2. 在 Studio 代码库中接入日志查询(品牌分析 SQL、端点选择器、OTEL 查询构建器)。请阅读 references/codebase-integration.md。

如果要转换现有的 BigQuery 日志查询,请阅读 references/bigquery-migration.md,查看完整的转换表。

日志表

每行包含少量真实列。每个服务特有的信息都存储在 log_attributes 中。

列类型说明
idString唯一的日志标识符。
timestampDateTime64 (UTC)日志生成时间。直接对其排序或比较。
event_messageString原始日志行。
severity_textString日志级别(如果来源设置了该值)。
sourceString日志所属的服务。始终按此列筛选。
log_attributesMap(String, String)按来源组织的结构化字段,以带点的路径作为键。

timestamp 的格式类似 2026-06-22T09:34:06.215000(ISO 8601 格式,精度为微秒, 末尾没有 Z)。在 Logs Explorer 中,系统会自动应用所选时间范围,因此通常无需手动编写 timestamp 筛选条件。

一个格式规范的最简查询。开头添加注释以命名查询,按 source 筛选,并始终设置 limit:

-- recent edge requests
select timestamp, event_message
from logs
where source = 'edge_logs'
order by timestamp desc
limit 100;

来源

source 用于选择服务。常见的来源包括:

  • edge_logs — API 网关请求和响应
  • postgres_logs — 数据库语句和错误(也包含 pg_cron 日志)
  • auth_logs — 身份验证和授权活动
  • function_edge_logs — Edge Function 请求和响应
  • function_logs — Edge Function 内部的 console 输出
  • storage_logs — 对象上传和检索活动
  • realtime_logs — Realtime 客户端连接
  • postgrest_logs、supavisor_logs、pgbouncer_logs — 主要包含 id、timestamp、event_message

Logs Explorer 中的 字段参考 抽屉会列出每个来源及其实际设置的字段。无法确定某个键时,请从真实数据中查找,而不是猜测(见下文)。

从 log_attributes 读取字段

log_attributes 将字符串键映射到字符串值。使用方括号访问字段。无需使用展开连接:

select
  log_attributes['request.method'] as method,
  log_attributes['request.path'] as path,
  log_attributes['response.status_code'] as status
from logs
where source = 'edge_logs'

键保留了 BigQuery 通过嵌套结构表示的点分路径,只是省略了 metadata 根节点:BigQuery 的 metadata.request.method 对应 log_attributes['request.method']。保留完整前缀——request.cf.country 对应 log_attributes['request.cf.country'],而不是 log_attributes['cf.country']。

各来源的常见键:

  • edge_logs:request.method、request.path、request.search、response.status_code、identifier
  • postgres_logs:parsed.error_severity、parsed.detail、parsed.hint、parsed.query、identifier
  • auth_logs:level、status、path、msg、error
  • function_edge_logs:response.status_code、request.method、request.pathname、function_id、execution_id、execution_time_ms
  • function_logs:event_type、function_id、execution_id、level
数值字段是字符串

映射值始终是字符串。要比较或聚合数值字段,请用 toInt32OrZero 包裹它;对于缺失或非数值的值,该函数会返回 0,因此不会因部分数据而报错:

select count() as server_errors
from logs
where source = 'edge_logs'
  and toInt32OrZero(log_attributes['response.status_code']) between 500 and 599
查找来源设置的键

从最近的行中读取 mapKeys,不要猜测键名:

select arrayJoin(mapKeys(log_attributes)) as key, count() as n
from logs
where source = 'postgres_logs'
group by key
order by n desc
limit 100;

arrayJoin(mapKeys(...)) 会将映射键展开为每个键对应一行,以便按频率排序。(Studio 代码库正是这样实现字段参考抽屉,并为 AI 改写提供真实键名。)

ClickHouse 与 BigQuery 函数对照

以下替换最容易让人踩坑:

需求BigQueryClickHouse
统计行数count(*)count()
正则匹配regexp_contains(x, 'p')match(x, 'p')
子串匹配x like '%p%'x ilike '%p%'(不区分大小写)或 like
数值转换cast(x as int64)toInt32OrZero(x)
读取时间戳cast(timestamp as datetime)timestamp(直接使用该列)
映射键不适用(使用 unnest)mapKeys(log_attributes)

logs.all.otel 分析端点(以及基于它的 Logs Explorer)会拒绝 count(*) 和 select *——请使用 count(),并列出所需的列。(原始 ClickHouse 支持这两种写法;这是日志查询接口的限制。)

最佳实践

遵循这些做法可以确保查询正确且开销低。日志表数据量很大;无界扫描会读取远超所需的数据。

  • 每条查询都以说明性注释开头(例如 -- errors since last deploy)。这会在日志和审查中标记该查询,也便于区分文件中的多条查询。
  • 始终包含 LIMIT。 即使在迭代聚合查询时也要包含。
  • 始终使用 from logs where source = '...' 查询。 不存在按服务划分的表(没有 edge_logs、postgres_logs 等表)——只有一个 logs 表,而 source 用于限定服务范围。必须按 source 筛选,这不只是优化手段。
  • 缩小时间范围。 时间窗口越短,结果返回越快。
  • 先筛选实际列(source、timestamp),再访问 log_attributes。
  • 按 timestamp desc 排序,优先查看最新日志。
  • 使用 count(),不要使用 count(*) 或 select *。

示例

按状态码统计请求:

select
  toInt32OrZero(log_attributes['response.status_code']) as status,
  count() as count
from logs
where source = 'edge_logs'
group by status
order by count desc
limit 50

Auth 错误:

select timestamp, event_message, log_attributes['msg'] as message
from logs
where source = 'auth_logs'
  and log_attributes['level'] in ('error', 'fatal')
order by timestamp desc
limit 100

搜索原始消息:

select timestamp, event_message
from logs
where source = 'postgres_logs'
  and event_message ilike '%deadlock%'
order by timestamp desc
limit 100

按严重级别分组的 Postgres 错误(将 unnest 转换为 map 的规范示例):

select log_attributes['parsed.error_severity'] as severity, count() as count
from logs
where source = 'postgres_logs'
  and log_attributes['parsed.error_severity'] in ('ERROR', 'FATAL', 'PANIC')
group by severity
order by count desc
limit 100

当用户粘贴 BigQuery 查询时

请转换查询,而不是直接运行。机械转换步骤(将每服务的表替换为 from logs where source = ...,移除所有 cross join unnest(...),将 unnest 别名列改写为 log_attributes['...'] 查询,并替换上述函数)已在 references/bigquery-migration.md 中通过完整的转换前后示例说明。Logs Explorer 还内置了 Rewrite to ClickHouse 操作,可借助 AI 完成转换;对于在仪表板中进行的一次性转换,请引导用户使用此功能。

评论

支持 Markdown