# queries run once per cluster (via the 'postgres' database)

- name: "settings"
  help: "PostgreSQL settings"
  scope: cluster
  labels:
    - "settings"
  values:
    - "max_connections"
    - "autovacuum_freeze_max_age"
    - "superuser_reserved_connections"
    - "max_wal_senders"
    - "max_prepared_transactions"
  query: >-
          SELECT
          current_setting('max_connections')::float AS max_connections,
          current_setting('autovacuum_freeze_max_age')::float AS autovacuum_freeze_max_age,
          current_setting('superuser_reserved_connections')::float AS superuser_reserved_connections,
          current_setting('max_wal_senders')::float AS max_wal_senders,
          current_setting('max_prepared_transactions')::float AS max_prepared_transactions

- name: "pg_locks"
  help: "locks held"
  scope: cluster
  labels:
    - "datname"
    - "mode"
  values:
    - "count"
  query: >-
            SELECT datname, t.mode, count(l.mode) FROM pg_database d CROSS JOIN
            (VALUES ('AccessShareLock'), ('RowShareLock'), ('RowExclusiveLock'), ('ShareUpdateExclusiveLock'), ('ShareLock'), ('ShareRowExclusiveLock'), ('ExclusiveLock'), ('AccessExclusiveLock')) t(mode)
            LEFT JOIN pg_locks l ON d.oid = l.database AND t.mode = l.mode AND l.pid <> pg_backend_pid()
            WHERE datname !~ '^template(0|1)$' GROUP BY 1, 2

- name: "pg_stat_database"
  help: "database statistics"
  scope: cluster
  min_version: 9.2
  type: "counter"
  labels:
    - "datname"
  values:
    - "numbackends"
    - "xact_commit"
    - "xact_rollback"
    - "blks_read"
    - "blks_hit"
    - "tup_returned"
    - "tup_fetched"
    - "tup_inserted"
    - "tup_updated"
    - "tup_deleted"
    - "conflicts"
    - "temp_files"
    - "temp_bytes"
    - "deadlocks"
    - "blk_read_time"
    - "blk_write_time"
    - "freeze_age"
    - "dbsize"
  query: >-
          SELECT
          s.datname::text,
          numbackends::float,
          xact_commit::float,
          xact_rollback::float,
          blks_read::float,
          blks_hit::float,
          tup_returned::float,
          tup_fetched::float,
          tup_inserted::float,
          tup_updated::float,
          tup_deleted::float,
          conflicts::float,
          temp_files::float,
          temp_bytes::float,
          deadlocks::float,
          blk_read_time,
          blk_write_time,
          age(d.datfrozenxid) AS freeze_age,
          pg_database_size(s.datname)::float AS dbsize
          FROM pg_stat_database s
          LEFT JOIN pg_database d ON d.datname = s.datname
          WHERE NOT s.datname ~ '^template(0|1)$'

- name: "pg_stat_statements"
  help: "statement statistics"
  scope: cluster
  min_version: 9.2
  max_version: 12
  labels:
    - "usename"
    - "datname"
    - "queryid"
    - "query"
  values:
    - "calls"
    - "total_time"
    - "rows"
    - "shared_blks_hit"
    - "shared_blks_read"
    - "shared_blks_dirtied"
    - "shared_blks_written"
    - "local_blks_hit"
    - "local_blks_read"
    - "local_blks_dirtied"
    - "local_blks_written"
    - "temp_blks_read"
    - "temp_blks_written"
  query: >-
          WITH w_pg_stat_statements AS ( SELECT * FROM pg_stat_statements)
          (SELECT
          usename::text,
          datname::text,
          queryid::text,
          substr(regexp_replace(query, E'[\\n\\r]+', ' ', 'g' ), 1, 1024) AS query,
          calls,
          total_time,
          rows,
          shared_blks_hit,
          shared_blks_read,
          shared_blks_dirtied,
          shared_blks_written,
          local_blks_hit,
          local_blks_read,
          local_blks_dirtied,
          local_blks_written,
          temp_blks_read,
          temp_blks_written
          FROM w_pg_stat_statements pss JOIN pg_database pd ON pss.dbid = pd.oid
          JOIN pg_user pu ON pss.userid = pu.usesysid
          ORDER BY pss.total_time DESC
          LIMIT 25)
          UNION
          (SELECT
          usename::text,
          datname::text,
          queryid::text,
          substr(regexp_replace(query, E'[\\n\\r]+', ' ', 'g' ), 1, 1024) AS query,
          calls,
          total_time,
          rows,
          shared_blks_hit,
          shared_blks_read,
          shared_blks_dirtied,
          shared_blks_written,
          local_blks_hit,
          local_blks_read,
          local_blks_dirtied,
          local_blks_written,
          temp_blks_read,
          temp_blks_written
          FROM w_pg_stat_statements pss2 JOIN pg_database pd2 ON pss2.dbid = pd2.oid
          JOIN pg_user pu2 ON pss2.userid = pu2.usesysid
          ORDER BY calls DESC
          LIMIT 25)

- name: "pg_stat_statements"
  help: "statement statistics"
  scope: cluster
  min_version: 13
  labels:
    - "usename"
    - "datname"
    - "queryid"
    - "query"
  values:
    - "calls"
    - "total_time"
    - "total_plan_time"
    - "total_exec_time"
    - "rows"
    - "shared_blks_hit"
    - "shared_blks_read"
    - "shared_blks_dirtied"
    - "shared_blks_written"
    - "local_blks_hit"
    - "local_blks_read"
    - "local_blks_dirtied"
    - "local_blks_written"
    - "temp_blks_read"
    - "temp_blks_written"
  query: >-
          WITH w_pg_stat_statements AS ( SELECT * FROM pg_stat_statements)
          (SELECT
          usename::text,
          datname::text,
          queryid::text,
          substr(regexp_replace(query, E'[\\n\\r]+', ' ', 'g' ), 1, 1024) AS query,
          calls,
          total_plan_time + total_exec_time as total_time,
          total_plan_time,
          total_exec_time,
          rows,
          shared_blks_hit,
          shared_blks_read,
          shared_blks_dirtied,
          shared_blks_written,
          local_blks_hit,
          local_blks_read,
          local_blks_dirtied,
          local_blks_written,
          temp_blks_read,
          temp_blks_written
          FROM w_pg_stat_statements pss JOIN pg_database pd ON pss.dbid = pd.oid
          JOIN pg_user pu ON pss.userid = pu.usesysid
          ORDER BY 6 DESC
          LIMIT 25)
          UNION
          (SELECT
          usename::text,
          datname::text,
          queryid::text,
          substr(regexp_replace(query, E'[\\n\\r]+', ' ', 'g' ), 1, 1024) AS query,
          calls,
          total_plan_time + total_exec_time as total_time,
          total_plan_time,
          total_exec_time,
          rows,
          shared_blks_hit,
          shared_blks_read,
          shared_blks_dirtied,
          shared_blks_written,
          local_blks_hit,
          local_blks_read,
          local_blks_dirtied,
          local_blks_written,
          temp_blks_read,
          temp_blks_written
          FROM w_pg_stat_statements pss2 JOIN pg_database pd2 ON pss2.dbid = pd2.oid
          JOIN pg_user pu2 ON pss2.userid = pu2.usesysid
          ORDER BY calls DESC
          LIMIT 25)

- name: "txid"
  help: "current txid"
  scope: cluster
  values:
    - "txid_current"
  query: SELECT CASE WHEN pg_is_in_recovery() THEN 0 ELSE txid_current() END

- name: "prepared_transactions"
  help: "prepared transactions"
  scope: cluster
  labels:
    - "datname"
  values:
    - "count"
  query: >-
          SELECT
          datname::text,
          COUNT(transaction) AS count
          FROM pg_database d
          LEFT JOIN pg_prepared_xacts x ON d.datname = x.database
          WHERE NOT d.datname ~ '^template(0|1)$'
          GROUP BY datname

# queries run for each database (except template0/template1)

- name: "pg_stat_user_tables"
  help: "table statistics"
  scope: database
  labels:
    - "datname"
    - "schemaname"
    - "relname"
  values:
    - "seq_scan"
    - "seq_tup_read"
    - "idx_scan"
    - "idx_tup_fetch"
    - "n_tup_ins"
    - "n_tup_upd"
    - "n_tup_del"
    - "n_tup_hot_upd"
    - "n_live_tup"
    - "n_dead_tup"
    - "vacuum_count"
    - "autovacuum_count"
    - "analyze_count"
    - "autoanalyze_count"
  query: >-
          SELECT
          current_database()::text AS datname,
          COALESCE(schemaname::text, 'null') AS schemaname,
          COALESCE(relname::text, 'null') AS relname,
          COALESCE(seq_scan, 0)::float AS seq_scan,
          COALESCE(seq_tup_read, 0)::float AS seq_tup_read,
          COALESCE(idx_scan, 0)::float AS idx_scan,
          COALESCE(idx_tup_fetch, 0)::float AS idx_tup_fetch,
          COALESCE(n_tup_ins, 0)::float AS n_tup_ins,
          COALESCE(n_tup_upd, 0)::float AS n_tup_upd,
          COALESCE(n_tup_del, 0)::float AS n_tup_del,
          COALESCE(n_tup_hot_upd, 0)::float AS n_tup_hot_upd,
          COALESCE(n_live_tup, 0)::float AS n_live_tup,
          COALESCE(n_dead_tup, 0)::float AS n_dead_tup,
          COALESCE(vacuum_count, 0)::float AS vacuum_count,
          COALESCE(autovacuum_count, 0)::float AS autovacuum_count,
          COALESCE(analyze_count, 0)::float AS analyze_count,
          COALESCE(autoanalyze_count, 0)::float AS autoanalyze_count
          FROM pg_stat_user_tables FULL JOIN (VALUES(0)) filler(i) ON TRUE  ORDER BY n_live_tup DESC LIMIT 1000

- name: "pg_statio_user_tables"
  help: "IO statistics"
  scope: database
  labels:
    - "datname"
    - "schemaname"
    - "relname"
  values:
    - "heap_blks_read"
    - "heap_blks_hit"
    - "idx_blks_read"
    - "idx_blks_hit"
  query: >-
          SELECT
          current_database()::text AS datname,
          COALESCE(schemaname::text, 'null') AS schemaname,
          COALESCE(relname::text, 'null') AS relname,
          COALESCE(heap_blks_read::float, 0) AS heap_blks_read,
          COALESCE(heap_blks_hit::float, 0) AS heap_blks_hit,
          COALESCE(idx_blks_read::float, 0) AS idx_blks_read,
          COALESCE(idx_blks_hit::float, 0) AS idx_blks_hit
          FROM pg_statio_user_tables FULL JOIN (VALUES(0)) filler(i) ON TRUE ORDER BY 6 DESC LIMIT 1000

- name: "BufferAccess"
  help: "buffer access statistics"
  scope: database
  labels:
    - "datname"
    - "schemaname"
    - "relname"
  values:
    - "reads"
  query: >-
          SELECT
          current_database()::text AS datname,
          COALESCE(schemaname::text, 'null') AS schemaname,
          COALESCE(relname::text, 'null') AS relname,
          SUM(COALESCE(heap_blks_read, 0)
          + COALESCE(heap_blks_hit, 0)
          + COALESCE(idx_blks_hit, 0)
          + COALESCE(idx_blks_read, 0)
          + COALESCE(toast_blks_hit, 0)
          + COALESCE(toast_blks_read, 0)
          + COALESCE(tidx_blks_hit, 0)
          + COALESCE(tidx_blks_read, 0)) * 8192::bigint as reads
          FROM pg_statio_user_tables FULL JOIN (VALUES(0)) filler(i) ON TRUE
          GROUP BY 1, 2, 3 ORDER BY 3 DESC,2,1 LIMIT 1000

- name: "Maintenancecounters"
  help: "table maintenance job counters"
  scope: database
  labels:
    - "datname"
  values:
    - "vacuum_count"
    - "autovacuum_count"
    - "analyze_count"
    - "autoanalyze_count"
  query: >-
          SELECT
          current_database()::text AS datname,
          COALESCE(SUM(vacuum_count), 0) vacuum_count,
          COALESCE(SUM(autovacuum_count), 0) autovacuum_count,
          COALESCE(SUM(analyze_count), 0) analyze_count,
          COALESCE(SUM(autoanalyze_count), 0) autoanalyze_count
          FROM pg_stat_user_tables  ORDER BY 1,2,3 LIMIT 1000
