{"id":19236858,"url":"https://github.com/crunchydata/pgmonitor-extension","last_synced_at":"2026-01-27T01:33:02.496Z","repository":{"id":249882753,"uuid":"739479527","full_name":"CrunchyData/pgmonitor-extension","owner":"CrunchyData","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-09T18:41:24.000Z","size":84,"stargazers_count":91,"open_issues_count":6,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-29T06:12:42.432Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PLpgSQL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CrunchyData.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-01-05T17:03:30.000Z","updated_at":"2025-08-21T14:34:30.000Z","dependencies_parsed_at":"2024-09-02T04:06:11.716Z","dependency_job_id":"bbdbb75e-583e-439e-ab3e-58c867233735","html_url":"https://github.com/CrunchyData/pgmonitor-extension","commit_stats":null,"previous_names":["crunchydata/pgmonitor-extension"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/CrunchyData/pgmonitor-extension","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrunchyData%2Fpgmonitor-extension","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrunchyData%2Fpgmonitor-extension/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrunchyData%2Fpgmonitor-extension/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrunchyData%2Fpgmonitor-extension/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CrunchyData","download_url":"https://codeload.github.com/CrunchyData/pgmonitor-extension/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrunchyData%2Fpgmonitor-extension/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28795468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T01:07:07.743Z","status":"ssl_error","status_checked_at":"2026-01-27T01:07:06.974Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T16:23:43.708Z","updated_at":"2026-01-27T01:33:02.483Z","avatar_url":"https://github.com/CrunchyData.png","language":"PLpgSQL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pgMonitor Extension\n\n## Overview\n\nThis extension provides a means to collect metrics within a PostgreSQL database to be used by an external collection source (Prometheus exporter, Icinga/Nagios scraper, etc). Certain metrics are collected, their results stored as materialized views or tables, and refreshed on a per-query configurable timer. This allows the metric scraper to not have to be concerned about the underlying runtime of queries that can be more expensive, especially as the size of the database grows (object size, table statistics, etc). It also allows a functional interface for some metrics to account for differences in underlying system catalogs between PostgreSQL major versions (Ex. new columns in pg_stat_activity, pg_stat_statements).\n\nA background worker is provided to refresh the materialized views and tables automatically without the need for any third-party schedulers.\n\nTo see a practical application of this extension using Prometheus/Grafana we welcome you to try out pgMonitor - https://github.com/CrunchyData/pgmonitor\n\n## INSTALLATION\n\nRequirement:\n\n * PostgreSQL \u003e= 12\n\n### From Source\nIn the directory where you downloaded pgmonitor, run\n\n    make install\n\nIf you do not want the background worker compiled and just want the plain SQL install, you can run this instead:\n\n    make NO_BGW=1 install\n\nNote that without the BGW, refreshing of the materialized views and tables will require manual management outside of the pgMonitor extension.\n\n\n## CONFIGURATION\n\n### PostgreSQL Setup\n\nThe background worker must be loaded on database start by adding the library to shared_preload_libraries in postgresql.conf\n\n    shared_preload_libraries = 'pgmonitor_bgw'     # (change requires restart)\n\nYou can also set other control variables for the BGW in postgresql.conf. These can be added/changed at anytime with a simple reload. See the documentation for more details.\n\n`pgmonitor_bgw.dbname` is required at a minimum for maintenance to run on the given database(s). This can be a comma separated list if pgMonitor is installed on more than one database to collect per-database metrics.\n\n    pgmonitor_bgw.dbname = 'proddb'\n\nAt this time `pgmonitor_bgw.role` must be a superuser due to elevated privileges that are required to gather all metrics as well as refresh the materialized views. Work is underway to see if this can be run as a non-supuseruser. It currently defaults to `postgres` if not set manually.\n\n    pgmonitor_bgw.role = 'postgres'\n\nThe interval defaults to 30 seconds and generally doesn't need to be changed. If you're trying to adjust materialized view or tables refresh timing, see the configuration tables below.\n\n    pgmonitor_bgw.interval = 30\n\nLog into PostgreSQL and run the following commands. Schema is optional (but recommended) and can be whatever you wish, but it cannot be changed after installation. If you're using the BGW, the database cluster can be safely started without having the extension first created in the configured database(s). You can create the extension at any time and the BGW will automatically pick up that it exists without restarting the cluster (as long as shared_preload_libraries was set) and begin running maintenance as configured.\n\n    CREATE SCHEMA pgmonitor_ext;\n    CREATE EXTENSION pgmonitor SCHEMA pgmonitor_ext;\n\n### Metric configuration\n\nThe names of all normal views are stored in `metric_views`. All metrics that are either normal views or have the option to be backed by either a normal view or materialized view are stored here. If a metric is only backed by a materialized view and has no option for a normal view, it will only be stored in `metrics_matviews`.\n```\n                   Table \"pgmonitor_ext.metric_views\"\n     Column     |  Type   | Collation | Nullable |        Default        \n----------------+---------+-----------+----------+-----------------------\n view_schema    | text    |           | not null | 'pgmonitor_ext'::text\n view_name      | text    |           | not null | \n matview_source | boolean |           | not null | false\n active         | boolean |           | not null | true\n scope          | text    |           | not null | 'global'::text\nIndexes:\n```\n\n - `view_schema`\n    - Schema containing the view_name\n - `view_name`\n    - Name of the view or materialized view in system catalogs\n - `matview_source`\n    - Boolean to set whether the metric view is backed by a materialized view. If true, the view must be defined in a way that allows a choice to be made. Example: built in metrics use a function-backed view that checks this flag. Defaults to false. \n - `active`\n    - Boolean that external monitoring tools can use to determine whether this metric is actively used or not\n - `scope`\n    - Valid values are \"global\" or \"database\"\n    - \"global\" means the values of this metric are the same on every database in the instance (ex. connections, replication, etc)\n    - \"database\" means the values of this metric are only defined on a per database basis (database and table statisics, bloat, etc)\n    - Can be used by external scrape tools to be able to determine whether to collect these metrics only once per PostgreSQL instance or once per database inside that instance\n\nMaterialized views are stored in the `metric_matviews` configuration table. The background worker uses this table to determine which materialized views are \"active\" to be refreshed and how often to refresh them.\n```\n                            Table \"pgmonitor_ext.metric_matviews\"\n       Column       |           Type           | Collation | Nullable |        Default        \n--------------------+--------------------------+-----------+----------+-----------------------\n view_schema        | text                     |           | not null | 'pgmonitor_ext'::text\n view_name          | text                     |           | not null | \n concurrent_refresh | boolean                  |           | not null | true\n run_interval       | interval                 |           | not null | '00:14:00'::interval\n last_run           | timestamp with time zone |           |          | \n last_run_time      | interval                 |           |          | \n active             | boolean                  |           | not null | true\n scope              | text                     |           | not null | 'global'::text\n```\n - `view_schema`\n    - Schema containing the view_name\n - `view_name`\n    - Name of the view or materialized view in system catalogs\n - `concurrent_refresh`\n    - Boolean to set whether the materalized view can be refreshed concurrently. It is highly recommended that all matviews be written in a manner to support a unique key. Concurrent refreshes avoid any contention while metrics are being scraped by external tools.\n - `run_interval`\n    - How often the materalized view should be refreshed. Must be a valid value of the PostgreSQL interval type\n - `last_run`\n    - Timestamp of the last time this materalized view was refreshed\n - `last_run_time`\n    - How long the last run of this refresh took\n - `active`\n    - Boolean to determine whether this materialized view is refreshed as part of automatic maintenance. If false, this matview will not be refreshed automatically. Defaults to true. \n - `scope`\n    - See `metric_views` for the purpose of this column\n\n\nFor metrics that still require storage of results for fast scraping but cannot use a normal or materialized view, it is also possible to use a table and give pgMonitor an SQL statement to run to refresh that table. For example, the included pgBackRest metrics need to use a function that uses a COPY statement.\n```\n                             Table \"pgmonitor_ext.metric_tables\"\n      Column       |           Type           | Collation | Nullable |        Default  \n-------------------+--------------------------+-----------+----------+-----------------------\n table_schema      | text                     |           | not null | 'pgmonitor_ext'::text\n table_name        | text                     |           | not null |\n refresh_statement | text                     |           | not null |\n run_interval      | interval                 |           | not null | '00:10:00'::interval\n last_run          | timestamp with time zone |           |          |\n last_run_time     | interval                 |           |          |\n active            | boolean                  |           | not null | true\n scope             | text                     |           | not null | 'global'::text\n```\n\n - `table_schema`\n    - Schema containing the table_name\n - `table_name`\n    - Name of the table in system catalogs\n - `refresh_statement`\n    - The full SQL statement that is run to refresh the data in `table_name`. Ex: `SELECT pgmonitor_ext.pgbackrest_info()`\n - `active`\n    - Boolean to determin whether maintenance will call the refresh_statement as part of regular maintenance. If false, this refresh will not run.\n - See `metric_matviews` for purpose of remaining columns\n\nNORMAL VIEWS:\n```\n ccp_archive_command_status\n ccp_backrest_last_diff_backup\n ccp_backrest_last_full_backup\n ccp_backrest_last_incr_backup\n ccp_backrest_last_info\n ccp_backrest_oldest_full_backup\n ccp_connection_stats\n ccp_database_size\n ccp_data_checksum_failure\n ccp_locks\n ccp_pg_is_in_recovery\n ccp_postgresql_version\n ccp_postmaster_runtime\n ccp_postmaster_uptime\n ccp_replication_lag\n ccp_replication_lag_size\n ccp_replication_slots\n ccp_settings_pending_restart\n ccp_stat_bgwriter\n ccp_stat_checkpointer\n ccp_stat_database\n ccp_stat_io_bgwriter\n ccp_stat_user_tables\n ccp_table_size\n ccp_transaction_wraparound\n ccp_wal_activity\n\n```\n\nMAT VIEWS:\n```\n ccp_database_size_matview\n ccp_pg_hba_checksum\n ccp_sequence_exhaustion\n ccp_stat_user_tables_matview\n ccp_table_size_matview\n```\n\nTABLES:\n```\n metric_matviews\n metric_tables\n metric_views\n pgbackrest_info\n pg_hba_checksum\n pg_stat_statements_reset_info\n```\nFUNCTIONS:\n```\n ccp_database_size_view_choice() RETURNS TABLE\n ccp_replication_slots_func() RETURNS TABLE\n ccp_stat_checkpointer_func() RETURNS TABLE\n ccp_stat_io_bgwriter_func() RETURNS TABLE\n ccp_stat_user_tables_func() RETURNS TABLE\n ccp_stat_user_tables_view_choice() RETURNS TABLE\n ccp_table_size_view_choice() RETURNS TABLE\n pgbackrest_info() RETURNS SETOF pgbackrest_info\n pg_hba_checksum_set_valid() RETURNS smallint\n pg_hba_checksum(p_known_hba_hash text DEFAULT NULL)\n pg_stat_statements_func() RETURNS TABLE\n pg_stat_statements_reset_info() RETURNS bigint\n refresh_metrics_legacy (p_object_schema text DEFAULT 'monitor', p_object_name text DEFAULT NULL) RETURNS void\n sequence_exhaustion (p_percent integer DEFAULT 75, OUT count bigint)\n sequence_status() RETURNS TABLE (sequence_name text, last_value bigint, slots numeric, used numeric, percent int, cycle boolean, numleft numeric, table_usage text)\n```\nPROCEDURE:\n```\nrefresh_metrics (p_object_schema text DEFAULT 'monitor', p_object_name text DEFAULT NULL)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrunchydata%2Fpgmonitor-extension","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrunchydata%2Fpgmonitor-extension","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrunchydata%2Fpgmonitor-extension/lists"}