PostgreSQLXVI · Observability, Logging and AlertingObservability
Production logging configuration
What you'll learn
- Configure a log_line_prefix that supports correlation
- Choose what to log by what question it answers
- Manage log volume and rotation deliberately
- Know which settings require a restart
Prerequisites
Verified against PostgreSQL 18.x · PostgreSQL (comparison targets) 17.11, 16.15 · PostgreSQL (support calendar) 18, 17, 16, 15, 14 supported · pgBackRest 2.59.1 · PgBouncer 1.25.2 · Patroni 4.1.5 · Ubuntu (host baseline) 26.04 LTS · 2026-08-27
Every other instrument in this part shows you the present. The log is the only one that shows you last Tuesday at 03:14.
The prefix
Everything starts here, because a log line without context cannot be joined to anything.
log_line_prefix = '%m [%p] %q%u@%d/%a '
| Escape | Is | Why |
|---|---|---|
%m | Timestamp with milliseconds | Correlating with anything else |
%p | Process id | Joins to pg_stat_activity.pid and to the OS |
%q | Stop here for background processes | Keeps background lines clean |
%u | User | Who |
%d | Database | Where |
%a | Application name | Which service — if the app sets it |
$ tail /tmp/sb.log2026-08-27 23:13:19.892 UTC [637] postgres@postgres/psql LOG: statement: CREATE ROLE demo_user ...%p is the one that matters most. Lesson XVI-06 shows that
pg_stat_activity.pid is the operating system pid, so a log line
carrying %p can be joined to a running backend and to ps, top and
/proc.
Add %h (client host) if you need to trace connections back to
machines, and %x (transaction id) when investigating locking.
What to log
Always:
log_min_duration_statement = '1s' # the slow query log
log_checkpoints = on # on by default since 15
log_autovacuum_min_duration = '1s' # vacuum that took real time
log_lock_waits = on # anything waiting past deadlock_timeout
log_temp_files = 0 # every spill to disk; lesson XI-05
log_connections = on
log_disconnections = on
Each answers a question you will have during an incident:
log_min_duration_statement— which queries were slow?log_lock_waits— what was blocking? Part IX’s whole subject.log_temp_files— waswork_memtoo small? Lesson XI-05 measured spilling.log_checkpoints— was a write stall a checkpoint? Lesson XII-04.log_connections/log_disconnections— was it a connection storm?
Destination and rotation
logging_collector = on # RESTART REQUIRED
log_destination = 'stderr' # or 'jsonlog', or 'csvlog', or several
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = '1d'
log_rotation_size = '100MB'
log_truncate_on_rotation = off
logging_collector requires a restart, and it is what makes
PostgreSQL manage its own files. Without it, output goes to whatever
started the postmaster — journald under systemd, docker logs in a
container — which is fine if that is deliberate and surprising if it is
not.
jsonlog, added in PostgreSQL 15, emits one JSON object per event. If a
collector consumes your logs, it is easier to parse correctly than
stderr — no ambiguity about where a multi-line statement ends.
What to take from this
log_line_prefix = '%m [%p] %q%u@%d/%a '.%pis what joins the log topg_stat_activityand to the OS.- Check what your prefix actually is; distributions differ.
- Log slow statements, checkpoints, slow autovacuum, lock waits, temp files, connections.
log_min_duration_statementis a threshold. Use sampling rather than lowering it globally.logging_collectorrequires a restart and prevents interleaved lines.- The collector can become a bottleneck that backends block on. Do not log everything.
Cross-course references
- Linux for Production Sysadmins — Part VIII (Logging and journald) covers rotation and the filesystem the logs land on, which is a disk-full cause in its own right.
- Observability for Production Sysadmins — Part XXXI (Logging foundations) and Part XXXVI (Log shipping) cover getting these lines off the host, and Part XL (Log retention) covers how long to keep them.
Quiz
Knowledge check · 6 questions
Q1. Which log_line_prefix escape makes a log line joinable to a running backend and to operating system tools?
Q2. Queries on a busy cluster slow down after log_statement is set to all, with no change visible in pg_stat_statements' per-query timings. What is happening?
Q3. A log occasionally contains lines from two backends spliced together. logging_collector is off. Why?
Q4. Which logging settings answer a question you will actually have during an incident? Select all that apply.
Q5. logging_collector can be enabled with a reload, since it only changes where log output is directed.
Q6. Why is log_min_duration_statement preferable to log_statement = 'all', and what does sampling add?
Passing score: 75%. Answers are checked in this browser.