pg-logstats is a PostgreSQL log investigation CLI. It reads supported
PostgreSQL stderr logs, groups related statements into query families, ranks the
most useful findings, and prints follow-up SQL for live PostgreSQL inspection.
top query-families: rank query families in one log window by total runtime.slow-queries diff: compare a target log window against a baseline window.suggest-sql: printpg_stat_statementsandpg_stat_activityfollow-up SQL for a finding from JSON output.
Supported input is PostgreSQL stderr logs using this prefix shape:
2024-01-15 10:00:00.000 UTC [2001] app@appdb api: LOG: statement: SELECT * FROM users WHERE id = 1;
2024-01-15 10:00:00.020 UTC [2001] app@appdb api: LOG: duration: 20.000 ms
That corresponds to a PostgreSQL log_line_prefix similar to:
%m [%p] %u@%d %a:
Amazon RDS for PostgreSQL logs are also supported when they use the RDS prefix shape documented for pgBadger:
%t:%r:%u@%d:[%p]:
pg-logstats auto-detects local stderr and RDS-style logs by default. Use
--input-format rds when you want JSON evidence to mark the source kind as
AwsRds or when you want to reject non-RDS prefixes.
cargo install pg-logstats
pg-logstats top query-families tests/fixtures/cli/sample_stderr.log
pg-logstats --input-format rds top query-families tests/fixtures/cli/aws_rds.log
pg-logstats top query-families \
--rds-instance my-db \
--since 2h \
--output-format json
pg-logstats top query-families \
--output-format json \
--outfile findings.json \
tests/fixtures/cli/sample_stderr.log
pg-logstats slow-queries diff \
--baseline tests/fixtures/cli/diff_baseline.log \
--target tests/fixtures/cli/diff_target.log
pg-logstats suggest-sql --findings-file findings.json --rank 1Global flags such as --input-format, --output-format, --outfile,
--outdir, and --quiet can be placed before or after the workflow command.
For Amazon RDS PostgreSQL instances that publish PostgreSQL logs to CloudWatch
Logs, pg-logstats can read a bounded time window through the optional AWS SDK
integration.
Build with the optional feature:
cargo install pg-logstats --features aws-sdkThen run:
pg-logstats top query-families \
--rds-instance my-db \
--since 2h \
--output-format json--rds-instance my-db resolves to:
/aws/rds/instance/my-db/postgresql
You can also pass the log group explicitly:
pg-logstats top query-families \
--cloudwatch-log-group /aws/rds/instance/my-db/postgresql \
--since 2026-05-03T10:00:00Z \
--until 2026-05-03T11:00:00ZCloudWatch input uses the AWS SDK's normal credential and region provider chain.
Use --aws-profile, --aws-region, --cloudwatch-filter-pattern, and
--cloudwatch-max-pages to control the request. Relative --since values
support m, h, and d.
From crates.io:
cargo install pg-logstats
pg-logstats --versionFrom a local checkout:
git clone https://github.com/vrajat/pg-logstats.git
cd pg-logstats
cargo install --path .
pg-logstats --versionFrom source without installing:
cargo run -- top query-families tests/fixtures/cli/sample_stderr.logRank normalized query families in one log window:
pg-logstats top query-families tests/fixtures/cli/sample_stderr.logAnalyze every .log or .txt file in a directory:
pg-logstats top query-families --log-dir tests/fixtures/cliLimit the number of emitted findings:
pg-logstats top query-families --limit 5 tests/fixtures/cli/sample_stderr.logWrite JSON findings for shell or agent workflows:
pg-logstats top query-families \
--output-format json \
--outfile findings.json \
tests/fixtures/cli/sample_stderr.logCompare a target log window with a baseline log window:
pg-logstats slow-queries diff \
--baseline tests/fixtures/cli/diff_baseline.log \
--target tests/fixtures/cli/diff_target.logApply eligibility thresholds:
pg-logstats slow-queries diff \
--baseline tests/fixtures/cli/diff_baseline.log \
--target tests/fixtures/cli/diff_target.log \
--min-target-count 2 \
--min-target-total-ms 100 \
--min-p95-delta-ms 10Generate follow-up SQL for a finding selected by rank:
pg-logstats suggest-sql --findings-file findings.json --rank 1Or select by exact finding id:
pg-logstats suggest-sql \
--findings-file findings.json \
--finding-id 'query_family:queryid=|db=appdb|user=app|app=api|sql=SELECT * FROM users WHERE id = ?'JSON output is centered on findings:
pg-logstats top query-families \
--output-format json \
tests/fixtures/cli/sample_stderr.log | jq '.findings[0]'Useful fields include:
schema_versionmetadata.analysis_timestampmetadata.tool_versionmetadata.total_log_entriesfindings[].finding_idfindings[].kindfindings[].rankfindings[].titlefindings[].reasonfindings[].reason_codesfindings[].scorefindings[].confidencefindings[].query_family.normalized_sqlfindings[].query_family.databasefindings[].query_family.userfindings[].query_family.application_namefindings[].metrics.execution_countfindings[].metrics.total_duration_msfindings[].metrics.max_duration_msfindings[].next_sql
For diff findings, each finding also includes baseline, target, and delta
duration summaries.
tests/fixtures/cli contains the checked-in fixture logs used by the commands above.
make fmt
make checkRun a smoke command during local development:
cargo run -- top query-families tests/fixtures/cli/sample_stderr.logIf no findings are emitted, first check the log prefix. The current parser expects the supported stderr prefix shown above and statement/duration lines that can be correlated by process id and order.
Use --sample-size <N> with top query-families or slow-queries diff when you
want a quick pass over the first N lines of each file.
This project is licensed under the MIT License. See LICENSE.