可观性

可观察性允许根据系统生成的数据(例如日志、指标和跟踪)来测量系统的当前状态。

日志

Postgrest将基本请求信息记录到 stdout ,包括已验证的用户(如果可用)、请求IP地址和用户代理、请求的URL、HTTP响应状态和以字节为单位的响应正文大小(如果可用)。

日志级 设置为 info ,我们得到:

127.0.0.1 - user [26/Jul/2021:01:56:38 -0500] "GET /clients HTTP/1.1" 200 56 "" "curl/7.64.0"
127.0.0.1 - anonymous [26/Jul/2021:01:56:48 -0500] "GET /unexistent HTTP/1.1" 404 162 "" "curl/7.64.0"

有关服务器本身的诊断信息,Postgrest登录到 stderr :

06/May/2024:08:16:11 -0500: Starting PostgREST 12.1...
06/May/2024:08:16:11 -0500: Successfully connected to PostgreSQL 14.10 (Ubuntu 14.10-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, 64-bit
06/May/2024:08:16:11 -0500: Connection Pool initialized with a maximum size of 10 connections
06/May/2024:08:16:11 -0500: API server listening on port 3000
06/May/2024:08:16:11 -0500: Listening for database notifications on the "pgrst" channel
06/May/2024:08:16:11 -0500: Config reloaded
06/May/2024:08:16:11 -0500: Schema cache queried in 3.8 milliseconds
06/May/2024:08:16:11 -0500: Schema cache loaded 15 Relations, 8 Relationships, 8 Functions, 0 Domain Representations, 4 Media Type Handlers
06/May/2024:14:11:27 -0500: Received a config reload message on the "pgrst" channel
06/May/2024:14:11:27 -0500: Config reloaded

备注

收件箱基于 log-level 设置.看到 日志级 .

SQL查询收件箱

以记录 main SQL query 为请求执行,请将 日志查询main-query .它将根据当前记录 日志级 设置.例如,对于此配置:

log-level = "warn"
log-query = "main-query"

SQL查询只能登录 400 HTTP错误及以上。因此,如果用户在没有足够特权的情况下请求资源:

curl "localhost:3000/protected_table"

这将由Postgrest记录:

17/Feb/2025:17:28:15 -0500: WITH pgrst_source AS ( SELECT "public"."protected_table".* FROM "public"."protected_table"  )  SELECT null::bigint AS total_result_set, pg_catalog.count(_postgrest_t) AS page_total, coalesce(json_agg(_postgrest_t), '[]') AS body, nullif(current_setting('response.headers', true), '') AS response_headers, nullif(current_setting('response.status', true), '') AS response_status, '' AS response_inserted FROM ( SELECT * FROM pgrst_source ) _postgrest_t
127.0.0.1 - web_anon [17/Feb/2025:17:28:15 -0500] "GET /protected_table HTTP/1.1" 401 99 "" "curl/8.7.1"

数据库日志

此外,要查找所有SQL操作,您可以查看数据库日志。默认情况下,PostgreSQL不保留这些日志,因此您需要进行下面的配置更改。

发现 postgresql.conf 在您的PostgreSQL数据目录中(要找到它,请发出以下命令 show data_directory; )。找到散布在整个文件中的设置,并将它们更改为下列值,或者将此代码块追加到配置文件的末尾。

# send logs where the collector can access them
log_destination = "stderr"

# collect stderr output to log files
logging_collector = on

# save logs in pg_log/ under the pg data directory
log_directory = "pg_log"

# (optional) new log file per day
log_filename = "postgresql-%Y-%m-%d.log"

# log every kind of SQL statement
log_statement = "all"

重新启动数据库并实时查看日志文件,以了解如何将HTTP请求转换为SQL命令。

备注

在Docker上,您可以使用自定义 init.sh

#!/bin/sh
echo "log_statement = 'all'" >> /var/lib/postgresql/data/postgresql.conf

之后,您可以启动容器并使用以下命令检查日志 docker logs

docker run -v "$(pwd)/init.sh":"/docker-entrypoint-initdb.d/init.sh" -d postgres
docker logs -f <container-id>

度量

metrics 终点 管理服务器 端点提供指标 Prometheus text format .

curl "http://localhost:3001/metrics"

# HELP pgrst_schema_cache_query_time_seconds The query time in seconds of the last schema cache load
# TYPE pgrst_schema_cache_query_time_seconds gauge
pgrst_schema_cache_query_time_seconds 1.5937927e-2
# HELP pgrst_schema_cache_loads_total The total number of times the schema cache was loaded
# TYPE pgrst_schema_cache_loads_total counter
pgrst_schema_cache_loads_total 1.0
...

架构缓存收件箱

架构缓存 .

pgrst_schema_cache_query_time_seconds

Type

上次模式缓存加载的查询时间(秒)。

pgrst_schema_cache_loads_total

Type

计数器

Labels

status :成功|失败

加载架构缓存的总次数。

连接池收件箱

连接池 .

pgrst_db_pool_timeouts_total

Type

计数器

池连接超时的总数。

pgrst_db_pool_available

Type

池中的可用连接。

pgrst_db_pool_waiting

Type

等待获取池连接的请求

pgrst_db_pool_max

Type

最大池连接数。

迹线

服务器版本标题

调试问题时,验证正在运行的Postgrest版本非常重要。为此,您可以查看 Server 每个请求都会返回的HTTP响应标头。

HEAD /users HTTP/1.1

Server: postgrest/11.0.1

跟踪标头

您可以通过设置启用跟踪HTTP请求 服务器跟踪标头 。在请求中指定Set标头,服务器会将其包含在响应中。

server-trace-header = "X-Request-Id"
curl "http://localhost:3000/users" \
  -H "X-Request-Id: 123"
HTTP/1.1 200 OK
X-Request-Id: 123

代理状态标题

看到 代理状态标题 .

服务器计时头

您可以启用 Server-Timing 通过设置表头 启用服务器计时 在……上面。此标头传达请求-响应周期中不同阶段的指标。

curl "http://localhost:3000/users" -i
HTTP/1.1 200 OK

Server-Timing: jwt;dur=14.9, parse;dur=71.1, plan;dur=109.0, transaction;dur=353.2, response;dur=4.4
  • 所有的持续时间 (dur )以毫秒为单位。

  • 这个 jwt 舞台是指 基于JWT的用户模拟 已经完成了。此持续时间可通过以下方式缩短 JWT缓存

  • parse 舞台,舞台 URL语法 是被解析的。

  • plan 舞台,舞台 架构缓存 用于生成 主查询 这笔交易的。

  • 这个 transaction 阶段对应于数据库事务。看见 交易记录

  • 这个 response 阶段是计算响应状态和标头的地方。

备注

我们正在努力降低持续时间 parseplan Https://github.com/PostgREST/postgrest/issues/2816.上的阶段

内容长度标头

您可以在中验证响应正文大小(以字节为单位) Content-Length header .

curl -i 'localhost:3000/users'
HTTP/1.1 200 OK
Content-Length: 104

请注意,此标题不会返回 HEAD 出于优化目的的请求(请参阅 拿起头来 ).这符合 RFC 9110 .

体型也存在于 PostgREST logs .

执行计划

你可以拿到 EXPLAIN execution plan 通过添加请求的 Accept: application/vnd.pgrst.plan 标题。这可通过以下方式实现 数据库-计划已启用 (默认情况下为False)。

curl "http://localhost:3000/users?select=name&order=id" \
  -H "Accept: application/vnd.pgrst.plan"
Aggregate  (cost=73.65..73.68 rows=1 width=112)
  ->  Index Scan using users_pkey on users  (cost=0.15..60.90 rows=850 width=36)

该计划的输出是在 text 格式,但您可以通过使用 +json 后缀。

curl "http://localhost:3000/users?select=name&order=id" \
  -H "Accept: application/vnd.pgrst.plan+json"
[
  {
    "Plan": {
      "Node Type": "Aggregate",
      "Strategy": "Plain",
      "Partial Mode": "Simple",
      "Parallel Aware": false,
      "Async Capable": false,
      "Startup Cost": 73.65,
      "Total Cost": 73.68,
      "Plan Rows": 1,
      "Plan Width": 112,
      "Plans": [
        {
          "Node Type": "Index Scan",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Async Capable": false,
          "Scan Direction": "Forward",
          "Index Name": "users_pkey",
          "Relation Name": "users",
          "Alias": "users",
          "Startup Cost": 0.15,
          "Total Cost": 60.90,
          "Plan Rows": 850,
          "Plan Width": 36
        }
      ]
    }
  }
]

默认情况下,假设计划生成资源的JSON表示 (application/json ),但您可以获取 different representations that PostgREST supports 通过将它们添加到 for 参数。例如,要获得一个 text/xml ,您将使用 Accept: application/vnd.pgrst.plan; for="text/xml

其他可用参数包括 analyzeverbosesettingsbufferswal ,它们对应于 EXPLAIN command options 。要使用 analyzewal 参数,例如,您可以将它们添加为 Accept: application/vnd.pgrst.plan; options=analyze|wal

注意,与EXPLAIN命令类似,更改将在使用 analyze 选择。要避免这种情况,您可以使用 DB-TX-END 以及 Prefer: tx=rollback 标题。

确保执行计划的安全

建议仅激活 数据库-计划已启用 因为它揭示了内部数据库的详细信息。但是,如果选择在生产中使用它,则可以添加一个 数据库-请求前 以筛选可以使用此功能的请求。

例如,要仅允许来自IP地址的请求获取执行计划:

-- Assuming a proxy(Nginx, Cloudflare, etc) passes an "X-Forwarded-For" header(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)
create or replace function filter_plan_requests()
returns void as $$
declare
  headers   json := current_setting('request.headers', true)::json;
  client_ip text := coalesce(headers->>'x-forwarded-for', '');
  accept    text := coalesce(headers->>'accept', '');
begin
  if accept like 'application/vnd.pgrst.plan%' and client_ip != '144.96.121.73' then
    raise insufficient_privilege using
      message = 'Not allowed to use application/vnd.pgrst.plan';
  end if;
end; $$ language plpgsql;

-- set this function on your postgrest.conf
-- db-pre-request = filter_plan_requests