Skip to content
Observability

检测检查

使用这些检查来识别值得调查的证据。一个发现并不能确定原因。代理提示也使用这些相同的检查。

🌐 Use these checks to identify evidence worth investigating. A finding does not establish a cause. The agent prompts use these same checks.

在运行检查之前 #

🌐 Before running checks

  • 识别项目和数据库实例。使用项目范围的 Supabase MCP 和 read_only=true。
  • 使用 query_logs 运行 ClickHouse SQL;通过工具的输入模式提供明确的 UTC 时间范围。使用 execute_sql 运行 Postgres SQL。在 Explorer 中,选择 Run SQL,然后分别查询源 Logs 或 Database。
  • 记录观测时间、窗口、阈值和已保存的基线。以下默认值是初始警报策略,不是 Supabase 服务保证。运行前记录运算符的覆盖操作。
  • 工具失败、缺少权限或必填字段、不完整的窗口以及不可用的历史记录都会导致受影响的检查无法评估。继续独立检查。仅凭零记录事件不能证明服务健康。

每次检查都会返回 发现、正常(已完成,未触发阈值)或 无法评估(缺少输入)。即使一次正常运行没有发送通知,也要保留这个结果。

🌐 Each check returns finding, clear (completed, no threshold crossed), or unable to assess with the missing input. Preserve this result even when a clear run sends no notification.

健康 #

🌐 Health

测量 API 和认证服务器错误 #

🌐 Measure API and Auth server errors

输入: 最近完整的 UTC 小时及其前一个完整小时,分别查询。分别评估每个来源;API 网关和认证事件是不同的观察项,不是要加在一起的唯一请求。

select source,
count() as events,
countIf(status between 100 and 599) as responses,
countIf(status between 500 and 599) as server_errors,
countIf(status in (401, 403)) as access_failures,
countIf(status is null or status < 100 or status > 599) as unknown_status
from (
select source,
toInt32OrNull(if(source = 'edge_logs',
log_attributes['response.status_code'], log_attributes['status'])) as status
from logs
where source in ('edge_logs', 'auth_logs')
)
group by source
order by source
limit 2;

信号: 根据来源计算 100 * server_errors / responses。报告至少 20 个服务器错误,错误率至少为 1%,并且至少为之前错误率的两倍。当之前的错误率为零时,请使用错误数量和 1% 的条件。两个时间窗口都需要至少 100 个响应,否则无法进行比较评估。

费率只使用有效状态。unknown_status 报告要单独列出;没有有效状态会导致检查无法评估。没有响应状态的认证事件不是成功的请求。缺失的源行需要进行抓取/流量检查,而不是假设为零错误率。

🌐 Rates use valid statuses only. Report unknown_status separately; no valid statuses makes the check unable to assess. Auth events without response statuses are not successful requests. A missing source row requires a capture/traffic check, not an assumed zero error rate.

下一步: 缩小到来源和时间。最多收集五个带有时间戳和状态的事件 ID,然后按照 API 错误排查 操作。隐藏路径和消息。修复后,在相似的时间窗口重新运行。

检查连接压力 #

🌐 Check connection pressure

输入: 一个当前的 Postgres 快照,具有读取所有会话的权限。

select
count(*) filter (where backend_type = 'client backend') as client_connections,
count(*) filter (where backend_type = 'client backend' and state = 'active') as active_connections,
current_setting('max_connections')::int as max_connections
from pg_stat_activity;

**信号:**在 max_connections 的 80% 时报告客户端连接。这是一个实例级的压力指标。保留的插槽、角色限制和池化器限制可能会更早约束客户端;这并不衡量应用可用的插槽。

接下来: 检查连接管理和角色数量。在工作负载或连接池变化后重新运行。

安全 #

🌐 Security

查看顾问的发现 #

🌐 Review advisor findings

操作: 使用工具的项目范围调用 get_advisors 和 type: "security"。报告 WARN 和 ERROR 的结果,包括 lint 名称、受影响对象和文档链接。保持 INFO 作为上下文,默认不发出警告。

接下来: 按照检查文档操作,并在提出更改之前验证预期的访问模型。修复后重新运行顾问。没有发现问题并不意味着项目是安全的。其他执行路径请参见 顾问。

衡量身份验证和授权失败 #

🌐 Measure authentication and authorization failures

输入/操作: 对最近完整的 UTC 天和前一个完整的 UTC 天运行 status-count 查询,每次请求最多 24 小时。分别评估每个来源。

信号: 计算 100 * access_failures / responses。在两个窗口中应用至少 100 个回复的健康最小值。报告至少 20 次失败,失败率至少为 1%,并且至少为前一次失败率的两倍。当前一次失败率为零时,使用计数和 1% 的条件。应用相同的未知状态和缺失来源规则。

接下来: 按状态和已清理的路径分组失败,而不是按用户、邮箱或 IP 分组。调查客户端流程和认证错误代码。峰值只是一个复查信号,而不是攻击的证据。对比类似时间窗口进行验证。

表现 #

🌐 Performance

查找长时间运行的会话和阻塞 #

🌐 Find long-running sessions and blockers

输入: 当前的 Postgres 快照,具有读取所有会话的权限。这无法重建在预定运行之间结束的会话。

select pid, usename as role, state,
now() - query_start as query_age,
now() - xact_start as transaction_age,
wait_event_type, wait_event,
pg_blocking_pids(pid) as blocking_pids
from pg_stat_activity
where datname = current_database()
and pid <> pg_backend_pid()
and (
(state = 'active' and now() - query_start > interval '30 seconds')
or (state like 'idle in transaction%' and now() - xact_start > interval '30 seconds')
or cardinality(pg_blocking_pids(pid)) > 0
)
order by query_start
limit 20;

信号: 每一行都需要审查。非空的 blocking_pids 表示有阻塞;仅仅是长查询或等待事件并不表示阻塞。查询存在时间并不等于锁等待时间。返回二十行可能表示被截断。

下一步: 使用数据库检查查看PID,并确定事务的目的和影响。不要仅因为时间长就建议取消。重新运行以验证是否解决。

比较查询执行时间 #

🌐 Compare query execution time

输入: 已启用 pg_stat_statements、查询标识可见性,以及三个间隔一小时保存的快照。它们定义了前一小时和当前小时。

select
now() as observed_at,
s.dbid,
s.userid,
s.queryid,
s.toplevel,
s.calls,
s.total_exec_time,
i.stats_reset,
i.dealloc,
to_jsonb(s) ->> 'stats_since' as statement_stats_since
from
pg_stat_statements as s
cross join pg_stat_statements_info as i
where s.dbid = (select oid from pg_database where datname = current_database())
order by s.total_exec_time desc
limit 100;

信号: 在同一项目实例中匹配 (dbid, userid, queryid, toplevel)。对于每个时间间隔,计算以毫秒为单位的 delta(total_exec_time) / delta(calls)。报告当前平均值至少为 100 毫秒,并且是前一个平均值的两倍,每个时间间隔至少有 20 次调用。

比较所有快照中存在的行,其中重置/启动标记保持不变且计数器没有减少。在升级、重置或更改为 dealloc(条目驱逐)之后,丢弃比较。如果 statement_stats_since 不可用,需要确认没有发生每条语句的重置。缺少历史或重置来源意味着无法评估;开始收集快照。前 100 行只是样本,并非完整查询覆盖。不要重置统计数据来收集基线。参见 Postgres 统计语义。

🌐 Compare rows present in all snapshots with unchanged reset/start markers and counters that have not decreased. Discard comparisons after an upgrade, reset, or change to dealloc (entry eviction). If statement_stats_since is unavailable, require confirmation that no per-statement reset occurred. Missing history or reset provenance means unable to assess; start collecting snapshots. The top 100 rows are a sample, not full query coverage. Do not reset statistics to collect a baseline. See Postgres statistics semantics.

下一步: 检查语句及其查询计划。保留一个对比窗口以验证任何变化。

查看性能顾问 #

🌐 Review performance advisors

用 type: "performance" 调用 get_advisors。应用安全严重性策略:报告 WARN 和 ERROR;保留 INFO 作为上下文。按照返回的文档操作,验证与工作负载的相关性,并在修复后重新运行。

🌐 Call get_advisors with type: "performance". Apply the Security severity policy: report WARN and ERROR; retain INFO as context. Follow the returned documentation, verify relevance to the workload, and rerun after a fix.

检查缓存未命中 #

🌐 Inspect cache misses

这个可选诊断是累积的,而不是每小时提醒或物理磁盘读取的测量:

🌐 This optional diagnostic is cumulative, not an hourly alert or a measurement of physical disk reads:

select
sum(heap_blks_hit) as heap_hits,
sum(heap_blks_read) as heap_reads,
round(
100.0 * sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0),
2
) as heap_hit_percent
from pg_statio_user_tables;

在发出警报之前,先使用特定工作负载的基线。空比率表示没有观察到访问。操作系统缓存可能会处理 Postgres 缓冲区未命中的情况。参见 缓存检查。

🌐 Use a workload-specific baseline before alerting. A null ratio means no observed accesses. The operating system cache may serve a Postgres buffer miss. See cache inspection.

容量 #

🌐 Capacity [#usage]

收集尺寸和连接测量 #

🌐 Collect size and connection measurements

输入/操作: 每天在相同的 UTC 时间读取相同的数据库实例。将数值和时间戳保存在授权的持久化支撑状态中,或使用授权的历史指标来源。不要在项目中创建监控表。

select
now() as observed_at,
current_database() as database_name,
pg_database_size(current_database()) as database_bytes;
select
now() as observed_at,
schemaname,
relname as table_name,
pg_total_relation_size(relid) as total_bytes
from pg_catalog.pg_statio_user_tables
order by total_bytes desc
limit 20;
select now() as observed_at, usename as role, state, count(*) as connections
from pg_stat_activity
where datname = current_database() and backend_type = 'client backend'
group by role, state
order by connections desc
limit 100;

解释: 大小是以字节为单位,连接数是快照计数,表总数包括索引。未出现在前20名的关系不一定缩小了。快照不能确定峰值连接需求;请使用 Metrics API 获取时间序列数据。

预测资源限制 #

🌐 Forecast a resource limit

输入: 至少七个每天的同一指标和范围的测量值,以及同单位的已确认限制。记录限制的来源和获取时间。数据库大小不是总磁盘使用量:磁盘预测需要已使用字节和磁盘容量。切勿将表字节数或请求次数与不相关的计划限制相比。

信号: 当增长为正时,计算:

growth_per_day = (latest_value - earliest_value) / elapsed_days
days_remaining = (confirmed_limit - latest_value) / growth_per_day

当当前值已经达到确认的限制时,就报告,不管历史情况如何。否则,报告最多14天以外的支持预测,并标记为线性估计。缺少历史数据、限制未知、范围变化或测量不连续都会导致预测无法评估。平稳或下降的数值无法支持耗尽日期。

🌐 Report when the current value already meets the confirmed limit, regardless of history. Otherwise, report a supported projection at most 14 days away, labeled as a linear estimate. Missing history, unknown limits, changed scope, or discontinuous measurements make the forecast unable to assess. Flat or falling values do not support an exhaustion date.

下一步: 将度量、单位、历史、限制来源和计算带到 计算和磁盘指南。在容量变化后再次测量,并更新存储的限制。

比较请求量 #

🌐 Compare request volume

对两个独立的完整 UTC 天运行健康查询。比较 API Gateway events;报告至少 1,000 个事件,并且是前一次数量的两倍。如果前一次数量为零,则报告观察到的新流量,而不显示增长百分比。应用缺失来源的规则。请求增长是工作负载上下文,而不是容量限制或计费总量。

🌐 Run the Health query for two separate complete UTC days. Compare API Gateway events; report at least 1,000 events and twice the preceding count. If the preceding count is zero, report new observed traffic without a growth percentage. Apply the missing-source rules. Request growth is workload context, not a capacity limit or billing total.

把检测变成诊断 #

🌐 Turn a detection into a diagnosis

报告检查、结果、项目、观察时间、窗口或快照、阈值、测量值和单位,以及证据标识符。包括一个调查链接和一个验证步骤。将观察与假设分开;不要编造原因或修复 SQL。使用故障排除指南来调查证据。

🌐 Report the check, outcome, project, observation time, window or snapshot, threshold, measured values and units, and an evidence identifier. Include one investigation link and a verification step. Separate observations from hypotheses; do not invent a cause or remediation SQL. Use the troubleshooting guides to investigate the evidence.