How to Interpret and Explore the Postgres Logs
为 API 日志 制作了一本免费指南
通过日志调试和监控 Postgres #
🌐 Debugging and monitoring Postgres with logs
日志可以让你了解 Postgres 的操作情况。它们有助于满足合规要求、发现可疑活动以及排查问题。
🌐 Logs provide insights into Postgres operations. They help meet compliance requirements, detect suspicious activity, and troubleshoot problems.
目录 #
🌐 Table of contents
- 查询日志
postgres_logs表结构
- 筛选日志
- 日常事件
- 按时间段
- 按错误严重性
- 按查询
- 按 API/角色
- 通过 Supabase 仪表板查询
- 查找错误的完整示例
- 合规与安全的日志记录
- 查看日志设置
- 更改日志设置
- 严重程度
- 配置已记录的查询
- 函数内的日志记录
- 常见问题
- 其他资源
查询日志 #
🌐 Querying logs
探索和筛选日志最实用的方法是通过 日志浏览器。
🌐 The most practical way to explore and filter logs is through the Logs Explorer.
它使用 BigQuery SQL 语法的一个子集,并且会预解析查询以进行优化。这带来了三个主要限制:
🌐 It uses a subset of BigQuery SQL syntax and pre-parses queries for optimization. This imposes three primary limitations:
- 不允许子查询或
WITH语句 - 列名不能用
*通配符 - 没有
ILIKE语句
虽然有很多过滤日志的策略,比如 like 和 in 语句,但一个叫做 regexp_contains 的辅助函数提供了最大的灵活性和控制力。
🌐 Although there are many strategies to filter logs, such as like and in statements, a helper function called regexp_contains provides the most flexibility and control.
postgres_logs 表包含 Postgres 事件。
🌐 The postgres_logs table contains Postgres events.
postgres_logs#
🌐 postgres_logs table structure
这个表格有3个基本列:
🌐 The table contains 3 fundamental columns:
| 列 | 描述 |
|---|---|
| event_message | 日志信息 |
| timestamp | 事件记录时间 |
| parsed metadata | 关于事件的元数据 |
解析后的元数据列是一个包含事件相关信息的数组。要访问这些信息,必须将其展开。这可以使用 cross join 来完成。
🌐 The parsed metadata column is an array that contains relevant information about events. To access the information, it must be unnested. This is done with a cross join.
展开嵌套示例
1select2 event_message,3 parsed.<column name>4from5 postgres_logs6-- Unpack data stored in the 'metadata' field7cross join unnest(metadata) AS metadata8-- After unpacking the 'metadata' field, extract the 'parsed' field from it9cross join unnest(parsed) AS parsed;解析的元数据字段 #
🌐 Parsed metadata fields
查询信息 [#query-information]
🌐 Query information
| 字段 | 描述 | 示例 |
|---|---|---|
| parsed.query | 执行的 SQL 查询 | SELECT * FROM table; |
| parsed.command_tag | 标识命令类型的标签(例如 SELECT) | SELECT、INSERT、UPDATE… |
| parsed.internal_query | 用于辅助主查询的内部查询。实时任务中经常使用 | select to_jsonb() |
建议使用场景:
- 识别慢查询
- 识别失败的查询
错误/警告信息 [#errorwarning-information]
🌐 Error/Warning information
| 字段 | 描述 | 示例 |
|---|---|---|
| parsed.error_severity | 事件严重性 | LOG、WARNING、ERROR... |
| parsed.detail | 根据 Postgres 对事件的解释 | "键 (fk_table)=(553585367) 已存在。" |
| parsed.sql_state_code | 对应 Postgres 错误表的错误代码 | 42501 |
| parsed.hint | 关于如何解决错误的提示 | "没有符合给定名称和参数类型的函数。你可能需要添加显式类型转换。" |
| parsed.context | 提供错误可能发生位置的相关信息 | "PL/pgSQL 函数 public.find_text(public.vector,integer) 第 3 行的 IF 语句" |
建议使用场景:
- 按错误严重性或 SQL 代码筛选
- 获取关于错误事件的提示、细节和上下文
连接/身份信息 [#connectionidentification-information]
🌐 Connection/Identification information
| 字段 | 描述 | 示例 |
|---|---|---|
| parsed.session_id | 会话ID | 12345 |
| parsed.session_start_time | 会话开始时间 | 2024-05-08 15:30:00 |
| parsed.connection_from | 连接IP | 192.165.1.100 |
| parsed.user_name | 连接数据库用户的名称 | postgres |
| parsed.application_name | 应用名称 | Supavisor, PostgREST |
| parsed.database_name | 数据库名称 | postgres |
| parsed.process_id | 进程ID,通常用来识别扩展工作器 | 1234 |
| parsed.backend_type | 判断事件是来自内部(例如 pg_net、timescale 或 pg_cron 等后台工作进程)还是来自客户端 (client backend) | client backend |
建议使用场景:
- 按服务器/API 识别事件
- 按IP筛选连接
- 识别与特定数据库的连接
- 按会话过滤连接以进行调试
- 识别扩展事件
筛选日志 #
🌐 Filtering logs
不包括日常事件 #
🌐 Excluding routine events
在正常时期,大多数 Postgres 日志都是日常事件,比如连接授权和检查点。要查看默认记录的事件类型,你可以查看这个指南。
🌐 Most Postgres logs during normal periods are routine events, such as connection authorizations and checkpoints. To see the default types of events that are logged, you can check this guide.
在查看日志中异常行为时,通常策略是先过滤掉预期值。可以通过在你的查询中添加以下过滤器来实现:
🌐 When exploring the logs for atypical behavior, it's often strategic to filter out expected values. This can be done by adding the following filter to your queries:
1...query2where3 -- Excluding routine events related to cron, PgBouncer, checkpoints, and successful connections4 not regexp_contains(event_message, '^cron|PgBouncer|checkpoint|connection received|authenticated|authorized');按时间框 #
🌐 By timeframe
调查某个特定时期的问题:
🌐 To investigate issues around a specific period:
1-- filtering by time period2...query3where4 timestamp between '2024-05-06 04:44:00' and '2024-05-06 04:45:00'按错误严重性 #
🌐 By error severity
这个过滤器会找到所有错误、致命错误和崩溃:
🌐 This filter finds all errors, fatals, and panics:
| 严重性 | 用法 |
|---|---|
| 错误 | 报告导致当前命令中止的错误。 |
| 致命 | 报告导致当前会话中止的错误。 |
| 紧急 | 报告导致所有数据库会话中止的错误。 |
1-- find error events2... query3where4 parsed.error_severity in ('ERROR', 'FATAL', 'PANIC')失败事件包括一个可以在 Postgres 文档 中查阅的 sql_state_code
🌐 Failure events include an sql_state_code that can be referenced in the Postgres Docs
通过查询 #
🌐 By query
注意:除非配置了 pg_audit,否则只会记录失败的查询
1-- find queries executed by the Dashboard2...query3where4 regexp_contains(parsed.query, '(?i)select . <some table>')查询可以使用复杂的语法,所以通常通过引用的数据库对象来隔离是很有帮助的,比如 functions、tables 和 columns。由于查询结构可能很复杂,建议使用 正则 来查找匹配项。一些常见的正则模式有:
🌐 Queries can use complex syntax, so it is often helpful to isolate by referenced database objects, such as functions, tables, and columns. Because query structures can be complex, it is advised to use regex to find matches. Some common regex patterns are:
(?i):忽略大小写.:wildcard^:查找字符串开头的值|:或运算符
按 API/角色 #
🌐 By APIs/roles
所有失败的查询,包括来自 PostgREST、Auth 和外部库(例如 Prisma)的查询,都会记录带有有用错误信息的日志以便调试。
🌐 All failed queries, including those from PostgREST, Auth, and external libraries (e.g., Prisma) are logged with helpful error messages for debugging.
服务器/角色对应 #
🌐 Server/Role mapping
API 服务器已经分配了用于连接数据库的数据库角色:
🌐 API servers have assigned database roles for connecting to the database:
| 角色 | API/工具 |
|---|---|
supabase_admin | Supabase 用于配置项目和监控 |
authenticator | PostgREST |
supabase_auth_admin | 认证 |
supabase_storage_admin | 存储 |
supabase_realtime_admin | 实时 |
supabase_replication_admin | 同步只读副本 |
postgres | Supabase 仪表板和外部工具(例如 Prisma、SQLAlchemy、PSQL...) |
| 自定义角色 | 外部工具(例如 Prisma、SQLAlchemy、PSQL...) |
按 parsed.user_name 角色筛选,只获取特定角色的日志:
🌐 Filter by the parsed.user_name role to only retrieve logs made by specific roles:
1-- find events based on role/server2... query3where4 -- find events from the relevant role5 parsed.user_name = '<ROLE>'6...通过仪表板查询 #
🌐 By Dashboard queries
来自 Supabase 仪表板的查询是以 postgres 角色执行的,并包含注释 -- source: dashboard。在调试时,如果想隔离或排除仪表板的请求,你可以通过这个注释来过滤。
🌐 Queries from the Supabase Dashboard are executed under the postgres role and include the comment -- source: dashboard. To isolate or exclude Dashboard requests during debugging, you can filter by this comment.
1-- find queries executed by the Dashboard2...query3where4 regexp_contains(parsed.query, '-- source: dashboard')查找错误的完整示例 #
🌐 Full example for finding errors
1select2 cast(postgres_logs.timestamp as datetime) as timestamp,3 event_message,4 parsed.error_severity,5 parsed.user_name,6 parsed.query,7 parsed.detail,8 parsed.hint,9 parsed.sql_state_code,10 parsed.backend_type11from12 postgres_logs13 cross join unnest(metadata) as metadata14 cross join unnest(metadata.parsed) as parsed15where16 regexp_contains(parsed.error_severity, 'ERROR|FATAL|PANIC')17 and parsed.user_name = 'postgres'18 and regexp_contains(event_message, 'duration|operator')19 and not regexp_contains(parsed.query, '<key words>')20 and postgres_logs.timestamp between '2024-04-15 10:50:00' and '2024-04-15 10:50:27'21order by timestamp desc22limit 100;出于合规和安全的日志记录 #
🌐 Logging for compliance and security
自定义对象和角色活动日志 #
🌐 Customized object and role activity logging
⚠️ 注意:这特别适用于使用
postgres角色或 自定义角色 与他们的数据库交互的人。使用数据库 REST API 的人应该参考 数据库 API 日志指南。
在记录谁访问了什么时,基于数据库角色和对象的日志记录是确保活动踪迹可靠的最可靠方式。
🌐 When recording what is accessed and by whom, logging based on database roles and objects is the most reliable way to ensure a proper trail of activity.
你可以使用 pg_audit 扩展,根据特定角色对特定数据库对象,选择性地记录相关查询,而不仅仅是错误。
🌐 You can use the pg_audit extension to selectively log relevant queries, not only errors, by certain roles, against specific database objects.
在使用这个扩展时,你应该注意不要记录所有的数据库事件,只记录绝对必要的。过度记录会给数据库带来压力,还会产生大量日志噪音,让筛选相关事件变得困难。
🌐 You should take care when using the extension to not log all database events, but only what is absolutely necessary. Over-logging can strain the database and create log noise that makes it difficult to filter for relevant events.
按 pg_audit 过滤:
1... query2where3 -- all pg_audit recorded events start with 'AUDIT'4 regexp_contains(event_message, '^AUDIT')5 and6 -- Finding queries executed from the relevant role (e.g., 'API_role')7 parsed.user_name = 'API_role'按IP筛选 #
🌐 Filtering by IP
如果你是从已知的、有限范围的IP地址连接,应该启用网络限制。
在处理动态地址(例如无服务器或边缘环境的地址)时,监控 IP 会变得棘手。当依赖某些连接池工具时,这个问题会更加突出,比如 Prisma Accelerate、Supavisor 或 Cloudflare 的 Hyperdrive,因为它们记录的是连接池的 IP,而不是实际的来源。
🌐 Monitoring IPs becomes tricky when dealing with dynamic addressing, such as those from serverless or edge environments. This challenge amplifies when relying on certain poolers, such as Prisma Accelerate, Supavisor, or Cloudflare's Hyperdrive, as they record the pooler's IP, not the true origin.
当持续依赖拥有静态IP地址的服务器的直接数据库连接时,IP跟踪是最有效的:
🌐 IP tracking is most effective when consistently relying on direct database connections from servers with static IP addresses:
1-- filter by IP2select3 event_message,4 connection_from as ip,5 count(connection_from) as ip_count6from7 postgres_logs8 cross join unnest(metadata) as metadata9 cross join unnest(parsed) as parsed10where11 regexp_contains(user_name, '<ROLE>')12 and regexp_contains(backend_type, 'client backend') -- only search for connections from outside the database (excludes cron jobs)13 and regexp_contains(event_message, '^connection authenticated') -- only view successful authentication events14group by connection_from, event_message15order by ip_count desc16limit 100;查看日志设置 #
🌐 Reviewing log settings
pg_settings 表描述了系统和日志配置。
🌐 The pg_settings table describes system and logging configurations.
1-- view system variables2select * from pg_settings;影响日志的设置分为以下类别:
| 类别 | 描述 |
|---|---|
Reporting and Logging / What to Log | 指定值得记录的系统事件。 |
Reporting and Logging / When to Log | 指定日志记录的某些条件或规则 |
Customized Options | 配置扩展和加载的模块,包括那些增强日志功能的,如 auto_explain 和 pg_audit。 |
🌐 The settings that affect logs are categorized under:
| Category | Description |
|---|---|
Reporting and Logging / What to Log | Specifies system events worth logging. |
Reporting and Logging / When to Log | Specifies certain conditions or rules for logging |
Customized Options | Configures extensions and loaded modules, including those enhancing logging like auto_explain and pg_audit. |
要查看你数据库的所有日志设置,可以执行以下 SQL:
🌐 To view all log settings for your database, you can execute the following SQL:
1-- view all log related settings2select *3from pg_settings4where5 (6 category like 'Reporting and Logging / What to Log'7 or category like 'Reporting and Logging / When to Log'8 or category = 'Customized Options'9 )10 and name like '%log%';更改日志设置 #
🌐 Changing log settings
警告:宽松的设置可能会导致过度记录,影响数据库性能,同时在日志中产生噪音。
严重程度 #
🌐 Severity levels
log_min_messages 变量决定了什么程度的问题会被记录。这里是来自 Postgres 文档 的严重性阈值。
🌐 The log_min_messages variable determines what is severe enough to log. Here are the severity thresholds from the Postgres docs.
| 严重性 | 用途 |
|---|---|
| DEBUG1 .. DEBUG5 | 提供开发者使用的逐步更详细的信息。 |
| INFO | 提供用户隐式请求的信息,例如 VACUUM VERBOSE 的输出。 |
| NOTICE | 提供可能对用户有帮助的信息,例如长标识符被截断的通知。 |
| WARNING | 提供可能出现问题的警告,例如在事务块外执行 COMMIT。 |
| ERROR | 报告导致当前命令中止的错误。 |
| LOG | 报告管理员关心的信息,例如检查点活动。 |
| FATAL | 报告导致当前会话中止的错误。 |
| PANIC | 报告导致所有数据库会话中止的错误。 |
在大多数情况下,默认设置就足够了。不过,如果你必须调整设置,可以用下面的查询进行:
🌐 In most cases, the default is adequate. However, if you must adjust the setting, you can do so with the following query:
1alter role postgres set log_min_messages = '<NEW VALUE>';23-- view new setting4show log_min_messages; -- default WARNING配置已记录的查询 #
🌐 Configuring queries logged
默认情况下,只有失败的查询会被记录。PGAudit 扩展 扩展了 Postgres 内置的日志功能。它可以用来有选择地跟踪你数据库中的所有查询,方法是:
🌐 By default, only failed queries are logged. The PGAudit extension extends Postgres's built-in logging abilities. It can be used to selectively track all queries in your database by:
- role
- session
- 数据库对象
- 整个数据库
在数据库函数中记录日志 #
🌐 Logging within database functions
要跟踪或调试函数,可以按照函数调试指南来配置日志
🌐 To track or debug functions, logging can be configured by following the function debugging guide
常见问题 #
🌐 Frequently Asked Questions
如何合并不同的日志表 #
🌐 How to join different log tables
不,日志表彼此独立,不共享任何用于关联的主键/外键关系。
🌐 No, log tables are independent from each other and do not share any primary/foreign key relations for joining.
如何下载日志 #
🌐 How to download logs
目前,下载日志的方式是通过日志仪表板以 CSV 格式下载
🌐 At the moment, the way to download logs is through the Log Dashboard as a CSV
记录了什么? #
🌐 What is logged?
要查看默认记录的事件类型,你可以查看这个指南。
🌐 To see the default types of events that are logged, you can check this guide.
其他资源: #
🌐 Other resources: