可观性
可观察性允许根据系统生成的数据(例如日志、指标和跟踪)来测量系统的当前状态。
日志
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 |
|
加载架构缓存的总次数。
连接池收件箱
与 连接池 .
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语法 是被解析的。这个
transaction
阶段对应于数据库事务。看见 交易记录 。这个
response
阶段是计算响应状态和标头的地方。
备注
我们正在努力降低持续时间 parse
和 plan
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
。
其他可用参数包括 analyze
, verbose
, settings
, buffers
和 wal
,它们对应于 EXPLAIN command options 。要使用 analyze
和 wal
参数,例如,您可以将它们添加为 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