Hook Overview
Executor Hooks
The executor hooks work together to capture metrics for optimizable queries (SELECT, INSERT, UPDATE, DELETE, MERGE).ExecutorStart_hook
Called: Before the executor begins processing a query. What pg_stat_ch does:- Skips parallel workers (to avoid double-counting)
- Records if this is a top-level query (nesting_level == 0)
- Captures the query start timestamp
- Initializes CPU time baseline via
getrusage() - Enables instrumentation to collect buffer/timing stats
ExecutorRun_hook
Called: When the executor actually runs the query plan. What pg_stat_ch does:- Increments
nesting_levelto track nested queries - Calls the actual executor
- Decrements
nesting_levelin PG_FINALLY (even on error)
ExecutorEnd_hook.
ExecutorFinish_hook
Called: After execution completes but before cleanup (handles AFTER triggers). What pg_stat_ch does: Same as ExecutorRun - tracks nesting level only.ExecutorEnd_hook
Called: After query execution is complete, during cleanup. What pg_stat_ch does:- Finalizes instrumentation (
InstrEndLoop) - Computes CPU time delta from
getrusage() - Extracts all metrics from
QueryDesc - Builds a
PschEventand enqueues it to shared memory
Metrics Captured from QueryDesc
TheQueryDesc structure provides access to all query execution information:
From query_desc->totaltime (Instrumentation)
From query_desc->estate (Executor State)
From query_desc->plannedstmt
ProcessUtility_hook
Called: For utility (non-optimizable) statements like DDL. What pg_stat_ch captures:- CREATE/ALTER/DROP (tables, indexes, etc.)
- COPY
- VACUUM, ANALYZE
- GRANT, REVOKE
- SET, SHOW
- Transaction control (BEGIN, COMMIT, ROLLBACK)
- EXECUTE (prepared statement execution - counted via executor hooks)
- PREPARE (preparation only, not execution)
- DEALLOCATE
emit_log_hook
Called: When PostgreSQL emits a log message (before sending to log destination). What pg_stat_ch captures: Messages at the configured minimum level and above (default: WARNING). The minimum level is controlled by thepg_stat_ch.log_min_elevel GUC parameter.
See the events schema reference for the complete list of error levels and their numeric values.
ErrorData fields captured:
Example SQLSTATE codes:
42P01- Undefined table23505- Unique violation42601- Syntax error40001- Serialization failure
disable_error_capture = true before calling PschEnqueueEvent() to prevent recursive calls if enqueueing itself triggers an error.
Hook Chaining
PostgreSQL hooks use a chaining pattern - each extension saves the previous hook value and calls it. This ensures pg_stat_ch works alongside other extensions likepg_stat_statements, auto_explain, etc.
Nesting Level Tracking
Queries can be nested (e.g., triggers, functions calling queries). pg_stat_ch tracks nesting level to:- Identify top-level queries - Only top-level queries start CPU time tracking
- Avoid double-counting - Nested queries are captured separately
top_level flag in events indicates whether the query was top-level.
Parallel Worker Handling
Parallel workers execute portions of a query plan. pg_stat_ch:- Skips parallel workers via
IsParallelWorker()check - Captures aggregate stats from the leader backend
- Reports worker counts (PG18+) via
es_parallel_workers_*

