├── .commitlintrc.yml ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── pull_request_template.md └── workflows │ └── fragment.yml ├── .gitignore ├── .gitmodules ├── .pre-commit-config.yaml ├── CHANGELOG.rst ├── LICENSE ├── README.md ├── alertmanager ├── common │ └── crunchy-alertmanager.yml └── linux │ ├── crunchy-alertmanager-service-rhel.conf │ └── sysconfig.alertmanager ├── blackbox_exporter ├── common │ ├── blackbox_exporter.sysconfig │ └── crunchy-blackbox.yml └── linux │ └── .gitkeep ├── build └── packages.yml ├── changelogs ├── README.md ├── changelog.yaml ├── config.yaml └── fragments │ ├── .gitkeep │ ├── 470-containers-dashboard-updates.yml │ └── template.yml.example ├── grafana ├── common │ ├── crunchy_grafana_dashboards.yml │ └── crunchy_grafana_datasource.yml ├── containers │ ├── crunchy_grafana_dashboards.yml │ ├── crunchy_grafana_datasource.yml │ ├── pgbackrest.json │ ├── pgbouncer_direct.json │ ├── pod_details.json │ ├── postgresql_details.json │ ├── postgresql_overview.json │ ├── postgresql_service_health.json │ ├── prometheus_alerts.json │ └── query_statistics.json ├── etcd │ └── ETCD_Details.json ├── haproxy │ └── HAProxy.json ├── linux │ ├── Filesystem_Details.json │ ├── Network_Details.json │ ├── OS_Details.json │ └── OS_Overview.json ├── pgbouncer │ ├── direct │ │ └── PGBouncer_direct.json │ └── fdw │ │ └── PGBouncer_fdw.json ├── postgres │ ├── Bloat_Details.json │ ├── CRUD_Details.json │ ├── PGBackrest.json │ ├── PG_Details.json │ ├── QueryStatistics.json │ ├── TableSize_Details.json │ ├── postgres_exporter │ │ └── PG_Overview_postgres_exporter.json │ └── sql_exporter │ │ └── PG_Overview_sql_exporter.json └── prometheus │ └── Prometheus_Alerts.json ├── hugo ├── archetypes │ └── default.md ├── config.toml ├── content │ ├── .gitkeep │ ├── _index.md │ ├── changelog │ │ ├── _index.md │ │ └── v5_upgrade │ │ │ └── _index.md │ ├── contributing │ │ └── _index.md │ ├── exporter │ │ └── _index.md │ ├── grafana │ │ └── _index.md │ └── prometheus │ │ └── _index.md ├── data │ ├── .gitkeep │ └── css.toml ├── layouts │ ├── .gitkeep │ └── shortcodes │ │ ├── include-file.html │ │ ├── logo.html │ │ ├── note.html │ │ ├── role.html │ │ ├── shell.html │ │ ├── toc.html │ │ ├── warn.html │ │ └── yaml.html └── static │ ├── .gitkeep │ ├── css │ └── main.css │ ├── favicon.png │ └── images │ ├── 01-Overview.png │ ├── 10-OS Overview.png │ ├── 11-OS Details.png │ ├── 12-Filesystem Details.png │ ├── 20-PostgreSQL Overview.png │ ├── 21-PostgreSQL Details.png │ ├── 22-PGBackrest.png │ ├── 23-TableSize Details.png │ ├── 24-CRUD Details.png │ ├── 30-ETCD Details.png │ ├── PGMonitor.gif │ ├── btn.png │ ├── crunchy-monitoring-arch.png │ ├── crunchy_logo.png │ ├── pgmonitor_logo.svg │ ├── pgmonitor_pgdetails.png │ └── pgmonitor_top_level.png ├── node_exporter ├── common │ └── .gitkeep └── linux │ ├── ccp_io_queue.sh │ ├── crunchy-node-exporter-service-rhel.conf │ └── sysconfig.node_exporter ├── pgbadger └── run_pgbadger.py ├── postgres_exporter ├── common │ ├── pg11 │ │ ├── queries_general.yml │ │ ├── queries_pg_stat_statements.yml │ │ └── setup.sql │ ├── pg12 │ │ ├── queries_general.yml │ │ ├── queries_pg_stat_statements.yml │ │ ├── queries_pg_stat_statements_reset_info.yml │ │ └── setup.sql │ ├── pg13 │ │ ├── queries_general.yml │ │ ├── queries_pg_stat_statements.yml │ │ ├── queries_pg_stat_statements_reset_info.yml │ │ └── setup.sql │ ├── pg14 │ │ ├── queries_general.yml │ │ ├── queries_pg_stat_statements.yml │ │ ├── queries_pg_stat_statements_reset_info.yml │ │ └── setup.sql │ ├── pg15 │ │ ├── queries_general.yml │ │ ├── queries_pg_stat_statements.yml │ │ ├── queries_pg_stat_statements_reset_info.yml │ │ └── setup.sql │ ├── pg16 │ │ ├── queries_general.yml │ │ ├── queries_pg_stat_statements.yml │ │ ├── queries_pg_stat_statements_reset_info.yml │ │ └── setup.sql │ ├── pg17 │ │ ├── queries_general.yml │ │ ├── queries_pg_stat_statements.yml │ │ ├── queries_pg_stat_statements_reset_info.yml │ │ └── setup.sql │ ├── queries_bloat.yml │ ├── queries_global.yml │ ├── queries_global_dbsize.yml │ ├── queries_global_matview.yml │ ├── queries_nodemx.yml │ ├── queries_per_db.yml │ ├── queries_per_db_matview.yml │ ├── queries_pgbouncer.yml │ └── setup_metric_views.sql └── linux │ ├── crontab.txt │ ├── crunchy-postgres-exporter@.service │ ├── pg11 │ ├── sysconfig.postgres_exporter_pg11 │ └── sysconfig.postgres_exporter_pg11_per_db │ ├── pg12 │ ├── sysconfig.postgres_exporter_pg12 │ └── sysconfig.postgres_exporter_pg12_per_db │ ├── pg13 │ ├── sysconfig.postgres_exporter_pg13 │ └── sysconfig.postgres_exporter_pg13_per_db │ ├── pg14 │ ├── sysconfig.postgres_exporter_pg14 │ └── sysconfig.postgres_exporter_pg14_per_db │ ├── pg15 │ ├── sysconfig.postgres_exporter_pg15 │ └── sysconfig.postgres_exporter_pg15_per_db │ ├── pg16 │ ├── sysconfig.postgres_exporter_pg16 │ └── sysconfig.postgres_exporter_pg16_per_db │ ├── pg17 │ ├── sysconfig.postgres_exporter_pg17 │ └── sysconfig.postgres_exporter_pg17_per_db │ ├── pgbackrest-info.sh │ ├── pgmonitor.conf │ └── queries_backrest.yml ├── prometheus ├── common │ ├── alert-rules.d │ │ ├── crunchy-alert-rules-blackbox.yml.example │ │ ├── crunchy-alert-rules-etcd.yml.example │ │ ├── crunchy-alert-rules-patroni.yml.example │ │ └── crunchy-alert-rules-pg.yml.example │ └── auto.d │ │ ├── crunchy_dev.yml.example │ │ ├── crunchy_haproxy.yml.example │ │ └── crunchy_prod.yml.example ├── containers │ ├── alert-rules.d │ │ └── crunchy-alert-rules-pg.yml.containers.example │ ├── auto.d │ │ └── .gitkeep │ └── crunchy-prometheus.yml.containers └── linux │ ├── alert-rules.d │ └── crunchy-alert-rules-node.yml.example │ ├── auto.d │ ├── ProductionOS.yml.example │ └── ReplicaOS.yml.example │ ├── crunchy-prometheus-service-rhel.conf │ ├── crunchy-prometheus.yml │ └── sysconfig.prometheus ├── release ├── RELEASE.md └── scripts │ └── check_capitalization └── sql_exporter ├── common ├── crunchy_backrest_collector.yml ├── crunchy_bloat_check_collector.yml ├── crunchy_global_collector.yml ├── crunchy_per_db_collector.yml ├── crunchy_pg_stat_statements_collector.yml ├── crunchy_pg_stat_statements_reset_collector.yml ├── crunchy_pgbouncer_121_collector.yml ├── crunchy_pgbouncer_124_collector.yml ├── crunchy_pgbouncer_fdw_collector.yml ├── setup_db.sql └── sql_exporter.yml.example └── linux ├── crontab.txt ├── crunchy-sql-exporter@.service └── sql_exporter.sysconfig /.commitlintrc.yml: -------------------------------------------------------------------------------- 1 | extends: 2 | - "@commitlint/config-conventional" 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Each line is a file pattern followed by one or more owners. 2 | # Order is important; the last matching pattern takes the most 3 | # precedence. 4 | 5 | # These owners will be the default owners for everything in 6 | # the repo. Unless a later match takes precedence, 7 | # all members of the @crunchydata/solutionsengineering 8 | # team will be added for review when someone opens a pull request. 9 | 10 | * @hunleyd @jchancojr @keithf4 @yorviarias 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'UNCONFIRMED' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the issue:** 11 | 12 | 13 | **Describe the expected behavior:** 14 | 15 | 16 | **Tell us about your environment:** 17 | - pgMonitor version: 18 | - Container or non-container: 19 | - Container name / image: 20 | - Operating System for non-container: 21 | - PostgreSQL Version: 22 | - Exporter(s) in use (incl. version): 23 | - Prometheus version: 24 | - AlertManager version: 25 | - Grafana version: 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an enhancement for this project 4 | title: '' 5 | labels: 'UNCONFIRMED' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the enhancement you are proposing:** 11 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | *Please fill this template out fully; failure to do so can result in rejection of your PR.* 4 | 5 | Please describe the changes made by your PR. This description should be at a high-level but detailed enough that a reviewer understands the scope of the fix or enhancement and can easily judge the PRs validity at addressing the stated issue/feature. Please fully describe any new or changed feature and whether said change is user-facing or not: 6 | 7 | 8 | 9 | Please indicate what kind of change your PR includes (multiple selections are acceptable): 10 | 11 | - [ ] Bugfix 12 | - [ ] Enhancement 13 | - [ ] Breaking Change 14 | - [ ] Documentation 15 | 16 | PRs should be against existing issues, so please list each issue using a separate 'closes' line: 17 | 18 | closes # 19 | 20 | If this PR depends on another PR or resolution of another issue, please indicate that here using a separate 'depends' line for each dependency. 21 | 22 | depends on # 23 | 24 | If you have an **external** dependency (packages, portal updates, etc), add the 'BLOCKED' tag to your PR. 25 | 26 | 27 | ## Testing 28 | *None of the testing listed below is optional.* 29 | 30 | - Installation method: 31 | - [ ] Binary install from source, version: 32 | - [ ] OS package repository, distro, and version: 33 | - [ ] Local package server, version: 34 | - [ ] Custom-built package, version: 35 | - [ ] Other: 36 | - [ ] PostgreSQL, Specify version(s): 37 | - [ ] docs tested with hugo version(s): 38 | 39 | ### Code testing 40 | 41 | Have you tested your changes against: 42 | - [ ] RedHat/CentOS 43 | - [ ] Ubuntu 44 | - [ ] Not applicable 45 | 46 | If your code touches sql_exporter, have you: 47 | - [ ] Tested against all versions of PostgreSQL affected 48 | - [ ] Ensure that exporter runs with no scrape errors 49 | - [ ] Not applicable 50 | 51 | If your code touches node_exporter, have you: 52 | - [ ] Ensure that exporter runs with no scrape errors 53 | - [ ] Not applicable 54 | 55 | If your code touches Prometheus, have you: 56 | - [ ] Ensured all configuration changes pass `promtool check config` 57 | - [ ] Ensured all alert rule changes pass `promtool check rules` 58 | - [ ] Prometheus runs without issue 59 | - [ ] Alertmanager runs without issue 60 | - [ ] Not applicable 61 | 62 | If your code touches Grafana, have you: 63 | - [ ] Ensured Grafana runs without issue 64 | - [ ] Ensured relevant dashboards load without issue 65 | - [ ] Not applicable 66 | 67 | ### Checklist: 68 | - I have made corresponding changes to: 69 | - [ ] the documentation 70 | - [ ] the release notes 71 | - [ ] the upgrade doc 72 | -------------------------------------------------------------------------------- /.github/workflows/fragment.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | 4 | jobs: 5 | changelog-fragment: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: "Check for Changelog fragment" 9 | uses: brettcannon/check-for-changed-files@v1 10 | with: 11 | file-pattern: "changelogs/fragments/*.yml" 12 | failure-message: "Missing a Changelog fragment in ${file-pattern}; please add one or wait for a maintainer to push one for you." 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | exporter/postgres/queries.yml 3 | hugo/.hugo_build.lock 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "hugo/themes/crunchy-hugo-theme"] 2 | path = hugo/themes/crunchy-hugo-theme 3 | url = https://github.com/crunchydata/crunchy-hugo-theme 4 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_install_hook_types: 2 | - commit-msg 3 | - pre-commit 4 | repos: 5 | - repo: https://github.com/pre-commit/pre-commit-hooks 6 | rev: v5.0.0 7 | hooks: 8 | - id: check-merge-conflict 9 | - id: check-symlinks 10 | - id: check-yaml 11 | - id: end-of-file-fixer 12 | - id: fix-byte-order-marker 13 | - id: mixed-line-ending 14 | args: ['--fix=auto'] 15 | - id: trailing-whitespace 16 | args: ['--markdown-linebreak-ext=md'] 17 | - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook 18 | rev: v9.16.0 19 | hooks: 20 | - id: commitlint 21 | stages: [commit-msg] 22 | additional_dependencies: ['@commitlint/config-conventional'] 23 | - repo: https://github.com/codespell-project/codespell 24 | rev: v2.3.0 25 | hooks: 26 | - id: codespell 27 | # if you need to add more words to ignore, they are comme separated 28 | # e.g. [-L, 'lod,foo'] 29 | args: [-L, 'lod'] 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pgMonitor 2 | 3 | ### [pgMonitor](https://github.com/CrunchyData/pgMonitor) is your all-in-one tool to easily create an environment to visualize the health and performance of your [PostgreSQL](http://www.postgresql.org/) cluster. 4 | 5 | ![pgMonitor](hugo/static/images/PGMonitor.gif) 6 | 7 | pgMonitor combines a suite of tools to facilitate the collection and visualization of important metrics that you need be aware of in your PostgreSQL database and your host environment, including: 8 | 9 | - Connection counts: how busy is your system being accessed and if connections are hanging 10 | - Database size: how much disk your cluster is using 11 | - Replication lag: know if your replicas are falling behind in loading data from your primary 12 | - Transaction wraparound: don't let your PostgreSQL database stop working 13 | - Bloat: how much extra space are your tables and indexes using 14 | - System metrics: CPU, Memory, I/O, uptime 15 | 16 | pgMonitor is also highly configurable, and advanced users can design their own metrics, visualizations, and add in other features such as alerting. 17 | 18 | Running pgMonitor will give you confidence in understanding how well your PostgreSQL cluster is performing, and will provide you the information to make calculated adjustments to your environment. 19 | 20 | --- 21 | 22 | Please view the official Crunchy Data pgMonitor documentation [here](https://access.crunchydata.com/documentation/pgmonitor/latest/). If you are interested in contributing or making an update to the documentation, please view the [Contributing Guidelines](https://access.crunchydata.com/documentation/pgmonitor/latest/contributing/). 23 | 24 | [](https://access.crunchydata.com/documentation/pgmonitor/latest/) 25 | 26 | --- 27 | 28 | ## Sponsors 29 | 30 | [![Crunchy Data](/hugo/static/images/crunchy_logo.png)](https://www.crunchydata.com/) 31 | 32 | [Crunchy Data](https://www.crunchydata.com/) is pleased to sponsor pgMonitor and many other [open-source projects](https://github.com/CrunchyData/) to help promote support the PostgreSQL community and software ecosystem. 33 | 34 | --- 35 | 36 | ## Legal Notices 37 | 38 | Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 39 | 40 | CRUNCHY DATA SOLUTIONS, INC. PROVIDES THIS GUIDE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 41 | 42 | Crunchy, Crunchy Data Solutions, Inc. and the Crunchy Hippo Logo are trademarks of Crunchy Data Solutions, Inc. All Rights Reserved. 43 | -------------------------------------------------------------------------------- /alertmanager/common/crunchy-alertmanager.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # Based on upstream example file found here: https://github.com/prometheus/alertmanager/blob/master/doc/examples/simple.yml 8 | global: 9 | smtp_smarthost: 'localhost: 25' 10 | smtp_require_tls: false 11 | smtp_from: 'Alertmanager ' 12 | # smtp_smarthost: 'smtp.example.com:587' 13 | # smtp_from: 'Alertmanager ' 14 | # smtp_auth_username: '' 15 | # smtp_auth_password: '' 16 | 17 | # templates: 18 | # - '/etc/alertmanager/template/*.tmpl' 19 | 20 | inhibit_rules: 21 | # Apply inhibition of warning if the alertname for the same system and service is already critical 22 | - source_match: 23 | severity: 'critical' 24 | target_match: 25 | severity: 'warning' 26 | equal: ['alertname', 'job', 'service'] 27 | 28 | receivers: 29 | - name: 'default-receiver' 30 | email_configs: 31 | - to: 'example@crunchydata.com' 32 | send_resolved: true 33 | 34 | ## Examples of alternative alert receivers. See documentation for more info on how to configure these fully 35 | #- name: 'pagerduty-dba' 36 | # pagerduty_configs: 37 | # - service_key: 38 | 39 | #- name: 'pagerduty-sre' 40 | # pagerduty_configs: 41 | # - service_key: 42 | 43 | #- name: 'dba-team' 44 | # email_configs: 45 | # - to: 'example-dba-team@crunchydata.com' 46 | # send_resolved: true 47 | 48 | #- name: 'sre-team' 49 | # email_configs: 50 | # - to: 'example-sre-team@crunchydata.com' 51 | # send_resolved: true 52 | 53 | route: 54 | receiver: default-receiver 55 | group_by: [severity, service, job, alertname] 56 | group_wait: 30s 57 | group_interval: 5m 58 | repeat_interval: 24h 59 | 60 | ## Example routes to show how to route outgoing alerts based on the content of that alert 61 | # routes: 62 | # - match_re: 63 | # service: ^(postgresql|mysql|oracle)$ 64 | # receiver: dba-team 65 | # # sub route to send critical dba alerts to pagerduty 66 | # routes: 67 | # - match: 68 | # severity: critical 69 | # receiver: pagerduty-dba 70 | # 71 | # - match: 72 | # service: system 73 | # receiver: sre-team 74 | # # sub route to send critical sre alerts to pagerduty 75 | # routes: 76 | # - match: 77 | # severity: critical 78 | # receiver: pagerduty-sre 79 | -------------------------------------------------------------------------------- /alertmanager/linux/crunchy-alertmanager-service-rhel.conf: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must have a .conf extension to override the default service and activate the crunchy specific configuration 8 | # Note this file must live in /etc/systemd/system/alertmanager.service.d/ to work 9 | # 10 | # Override package service config with our own as needed. ExecStart must be reset. 11 | 12 | [Service] 13 | PermissionsStartOnly=true 14 | User=ccp_monitoring 15 | EnvironmentFile=/etc/sysconfig/alertmanager 16 | ExecStart= 17 | ExecStart=/usr/bin/alertmanager $OPT 18 | ExecReload=/usr/bin/kill -HUP $MAINPID 19 | Restart=always 20 | -------------------------------------------------------------------------------- /alertmanager/linux/sysconfig.alertmanager: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/alertmanager) 8 | # 9 | # --config.file: path to the alertmanager server configuration file 10 | # --storage.path: location that the alertmanager will keep files it generates 11 | # --log.level: how verbose to make system logging. Setting to "debug" can help with diagnosing issues, but should not be left that way. 12 | 13 | OPT="--config.file=/etc/prometheus/crunchy-alertmanager.yml --storage.path=/var/lib/ccp_monitoring/alertmanager --log.level=info" 14 | -------------------------------------------------------------------------------- /blackbox_exporter/common/blackbox_exporter.sysconfig: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/blackbox_exporter) 8 | # 9 | OPT="--config.file=/etc/blackbox_exporter/crunchy-blackbox.yml" 10 | -------------------------------------------------------------------------------- /blackbox_exporter/common/crunchy-blackbox.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | modules: 8 | tcp_connect: 9 | prober: tcp 10 | tcp: 11 | preferred_ip_protocol: "ip4" 12 | tcp_connect_tls: 13 | prober: tcp 14 | tcp: 15 | preferred_ip_protocol: "ip4" 16 | tls: true 17 | -------------------------------------------------------------------------------- /blackbox_exporter/linux/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/blackbox_exporter/linux/.gitkeep -------------------------------------------------------------------------------- /changelogs/README.md: -------------------------------------------------------------------------------- 1 | Changelog Fragment Categories 2 | ============================= 3 | 4 | This document describes the section categories created in the default config. 5 | 6 | The categories are the same as the ones in the `Ansible-case changelog fragments `_. 7 | 8 | Note the use of _double backticks_ inside the fragments. This is required if you want the rendered output to contain backticks. 9 | 10 | The full list of categories is: 11 | 12 | **release_summary** 13 | This is a special section: as opposed to a list of strings, it accepts one string. This string will be inserted at the top of the changelog entry for the current version, before any section. There can only be one fragment with a ``release_summary`` section. 14 | 15 | **breaking_changes** 16 | This category should list all changes to features which absolutely require attention from users when upgrading, because an existing behavior is changed. This section should only appear in a initial major release (`x.0.0`) according to semantic versioning. 17 | 18 | **major_changes** 19 | This category contains major changes to the project. It should only contain a few items per major version, describing high-level changes. This section should not appear in patch releases according to semantic versioning. 20 | 21 | **minor_changes** 22 | This category should mention all new features not contained elsewhere. This section should not appear in patch releases according to semantic versioning. 23 | 24 | **removed_features** 25 | This category should mention all features that have been removed in this release. This section should only appear in a initial major release (`x.0.0`) according to semantic versioning. 26 | 27 | **deprecated_features** 28 | This category should contain all features which have been deprecated and will be removed in a future release. This section should not appear in patch releases according to semantic versioning. 29 | 30 | **security_fixes** 31 | This category should mention all security relevant fixes, including CVEs if available. 32 | 33 | **bugfixes** 34 | This category should be a list of all bug fixes which fix a bug that was present in a previous version. 35 | 36 | **known_issues** 37 | This category should mention known issues that are currently not fixed or will not be fixed. 38 | 39 | **trivial** 40 | This category will **not be shown** in the changelog. It can be used to describe changes that are not touching user-facing code, like changes in tests. This is useful if every PR is required to have a changelog fragment. 41 | 42 | Examples 43 | -------- 44 | 45 | A guide on how to write changelog fragments can be found in the `Ansible docs `_. 46 | 47 | Example of a regular changelog fragment:: 48 | 49 | bugfixes: 50 | - crunchydata.pg.backrest - wait for removal of repoN (https://github.com/CrunchyData/priv-all-ansible-roles/issues/65811). 51 | 52 | The filename in this case was ``changelogs/fragments/65854-backrest-wait-for-removal.yml``, because this was implemented in `PR #65854`_. 53 | 54 | A fragment can also contain multiple sections, or multiple entries in one section:: 55 | 56 | deprecated_features: 57 | - docker_container - the ``trust_image_content`` option will be removed. It has always been ignored by the module. 58 | - docker_stack - the return values ``err`` and ``out`` have been deprecated. Use ``stdout`` and ``stderr`` from now on instead. 59 | 60 | breaking_changes: 61 | - "docker_container - no longer passes information on non-anonymous volumes or binds as ``Volumes`` to the Docker daemon. This increases compatibility with the ``docker`` CLI program. Note that if you specify ``volumes: strict`` in ``comparisons``, this could cause existing containers created with docker_container from Ansible 2.9 or earlier to restart." 62 | 63 | The ``release_summary`` section is special, in that it doesn't contain a list of strings, but a string, and that only one such entry can be shown in the changelog of a release. Usually for every release (pre-release or regular release), at most one fragment is added which contains a ``release_summary``, and this is only done by the person doing the release. The ``release_summary`` should include some global information on the release; for example, it always mentions the release date and links to the user guide. 64 | 65 | An example of how a fragment with ``release_summary`` could look like:: 66 | 67 | release_summary: | 68 | This is the first proper release of ``antsibull-changelog`` on 2020-06-20. 69 | -------------------------------------------------------------------------------- /changelogs/config.yaml: -------------------------------------------------------------------------------- 1 | changelog_filename_template: ../CHANGELOG.rst 2 | changelog_filename_version_depth: 0 3 | changes_file: changelog.yaml 4 | changes_format: combined 5 | ignore_other_fragment_extensions: true 6 | is_other_project: true 7 | keep_fragments: false 8 | mention_ancestor: true 9 | new_plugins_after_name: removed_features 10 | notesdir: fragments 11 | prelude_section_name: release_summary 12 | prelude_section_title: Release Summary 13 | sanitize_changelog: true 14 | sections: 15 | - - major_changes 16 | - Major Changes 17 | - - minor_changes 18 | - Minor Changes 19 | - - breaking_changes 20 | - Breaking Changes / Porting Guide 21 | - - deprecated_features 22 | - Deprecated Features 23 | - - removed_features 24 | - Removed Features (previously deprecated) 25 | - - security_fixes 26 | - Security Fixes 27 | - - bugfixes 28 | - Bugfixes 29 | - - known_issues 30 | - Known Issues 31 | title: pgMonitor 32 | trivial_section_name: trivial 33 | use_fqcn: true 34 | use_semantic_versioning: true 35 | -------------------------------------------------------------------------------- /changelogs/fragments/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/changelogs/fragments/.gitkeep -------------------------------------------------------------------------------- /changelogs/fragments/470-containers-dashboard-updates.yml: -------------------------------------------------------------------------------- 1 | minor_changes: 2 | - Updated containers dashboards to use latest ccp metrics in v5.2.1 3 | - Add pgBouncer dashboard to containers folder 4 | -------------------------------------------------------------------------------- /changelogs/fragments/template.yml.example: -------------------------------------------------------------------------------- 1 | --- 2 | breaking_changes: 3 | - area affected (roles, specific role, playbooks, docs) - This category should list all changes to features which absolutely require attention from users when upgrading, because an existing behavior is changed. This section should only appear in a initial major release (`x.0.0`) according to semantic versioning. 4 | 5 | major_changes: 6 | - area affected (roles, specific role, playbooks, docs) - This category contains major changes to the project. It should only contain a few items per major version, describing high-level changes. This section should not appear in patch releases according to semantic versioning. 7 | 8 | minor_changes: 9 | - area affected (roles, specific role, playbooks, docs) - This category should mention all new features not contained elsewhere. This section should not appear in patch releases according to semantic versioning. 10 | 11 | removed_features: 12 | - area affected (roles, specific role, playbooks, docs) - This category should mention all features that have been removed in this release. This section should only appear in a initial major release (`x.0.0`) according to semantic versioning. 13 | 14 | deprecated_features: 15 | - area affected (roles, specific role, playbooks, docs) - This category should contain all features which have been deprecated and will be removed in a future release. This section should not appear in patch releases according to semantic versioning. 16 | 17 | security_fixes: 18 | - area affected (roles, specific role, playbooks, docs) - This category should mention all security relevant fixes, including CVEs if available. 19 | 20 | bugfixes: 21 | - area affected (roles, specific role, playbooks, docs) - This category should be a list of all bug fixes which fix a bug that was present in a previous version. 22 | 23 | known_issues: 24 | - area affected (roles, specific role, playbooks, docs) - This category should mention known issues that are currently not fixed or will not be fixed. 25 | 26 | trivial: 27 | - area affected (roles, specific role, playbooks, docs) - This category will **not be shown** in the changelog. It can be used to describe changes that are not touching user-facing code, like changes in tests. This is useful if every PR is required to have a changelog fragment. 28 | -------------------------------------------------------------------------------- /grafana/common/crunchy_grafana_dashboards.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | apiVersion: 1 7 | 8 | providers: 9 | - name: 'crunchy_dashboards' 10 | orgId: 1 11 | folder: '' 12 | type: file 13 | disableDeletion: false 14 | updateIntervalSeconds: 3 #how often Grafana will scan for changed dashboards 15 | options: 16 | path: /etc/grafana/crunchy_dashboards 17 | -------------------------------------------------------------------------------- /grafana/common/crunchy_grafana_datasource.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # config file version 8 | apiVersion: 1 9 | 10 | datasources: 11 | - name: PROMETHEUS 12 | uid: PDC1078F23EBDF0E5 13 | type: prometheus 14 | access: proxy 15 | url: http://localhost:9090 16 | isDefault: True 17 | editable: False 18 | orgId: 1 19 | version: 1 20 | -------------------------------------------------------------------------------- /grafana/containers/crunchy_grafana_dashboards.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | apiVersion: 1 7 | 8 | providers: 9 | - name: 'crunchy_dashboards' 10 | orgId: 1 11 | folder: '' 12 | type: file 13 | disableDeletion: false 14 | updateIntervalSeconds: 3 #how often Grafana will scan for changed dashboards 15 | options: 16 | path: /etc/grafana/provisioning/dashboards 17 | -------------------------------------------------------------------------------- /grafana/containers/crunchy_grafana_datasource.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # config file version 8 | apiVersion: 1 9 | 10 | datasources: 11 | - name: PROMETHEUS 12 | type: prometheus 13 | access: proxy 14 | url: http://$PROM_HOST:$PROM_PORT 15 | isDefault: True 16 | editable: False 17 | orgId: 1 18 | version: 1 19 | -------------------------------------------------------------------------------- /grafana/linux/OS_Overview.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "datasource", 8 | "uid": "grafana" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "editable": false, 19 | "fiscalYearStartMonth": 0, 20 | "graphTooltip": 0, 21 | "links": [], 22 | "panels": [ 23 | { 24 | "datasource": { 25 | "type": "prometheus", 26 | "uid": "${ccp_datasource}" 27 | }, 28 | "fieldConfig": { 29 | "defaults": { 30 | "color": { 31 | "mode": "thresholds" 32 | }, 33 | "links": [ 34 | { 35 | "targetBlank": true, 36 | "title": "OS Details", 37 | "url": "/d/4t6SO2Fik/os-details?$__all_variables" 38 | } 39 | ], 40 | "mappings": [ 41 | { 42 | "options": { 43 | "0": { 44 | "text": "DOWN" 45 | }, 46 | "1": { 47 | "text": "UP" 48 | } 49 | }, 50 | "type": "value" 51 | }, 52 | { 53 | "options": { 54 | "match": "null", 55 | "result": { 56 | "text": "DOWN" 57 | } 58 | }, 59 | "type": "special" 60 | } 61 | ], 62 | "thresholds": { 63 | "mode": "absolute", 64 | "steps": [ 65 | { 66 | "color": "rgba(245, 54, 54, 0.9)", 67 | "value": null 68 | }, 69 | { 70 | "color": "rgba(68, 126, 188, 0.9)", 71 | "value": 0.5 72 | }, 73 | { 74 | "color": "rgba(50, 172, 45, 0.9)", 75 | "value": 0.5 76 | } 77 | ] 78 | }, 79 | "unit": "none" 80 | }, 81 | "overrides": [] 82 | }, 83 | "gridPos": { 84 | "h": 4, 85 | "w": 6, 86 | "x": 0, 87 | "y": 0 88 | }, 89 | "id": 1, 90 | "maxDataPoints": 100, 91 | "options": { 92 | "colorMode": "background", 93 | "graphMode": "none", 94 | "justifyMode": "auto", 95 | "orientation": "horizontal", 96 | "reduceOptions": { 97 | "calcs": [ 98 | "last" 99 | ], 100 | "fields": "", 101 | "values": false 102 | }, 103 | "showPercentChange": false, 104 | "text": { 105 | "valueSize": 50 106 | }, 107 | "textMode": "auto", 108 | "wideLayout": true 109 | }, 110 | "pluginVersion": "10.4.2", 111 | "repeat": "osnodes", 112 | "repeatDirection": "h", 113 | "targets": [ 114 | { 115 | "datasource": { 116 | "type": "prometheus", 117 | "uid": "${ccp_datasource}" 118 | }, 119 | "expr": "up{job=~\"[[osnodes]]\", exp_type=\"node\"}", 120 | "format": "time_series", 121 | "interval": "", 122 | "intervalFactor": 1, 123 | "legendFormat": "", 124 | "metric": "up", 125 | "refId": "A", 126 | "step": 2 127 | } 128 | ], 129 | "title": "[[osnodes]]", 130 | "type": "stat" 131 | } 132 | ], 133 | "refresh": "5m", 134 | "schemaVersion": 39, 135 | "tags": [], 136 | "templating": { 137 | "list": [ 138 | { 139 | "current": { 140 | "selected": false, 141 | "text": "PROMETHEUS", 142 | "value": "PDC1078F23EBDF0E5" 143 | }, 144 | "hide": 0, 145 | "includeAll": false, 146 | "label": "Datasource", 147 | "multi": false, 148 | "name": "ccp_datasource", 149 | "options": [], 150 | "query": "prometheus", 151 | "refresh": 1, 152 | "regex": "", 153 | "skipUrlSync": false, 154 | "type": "datasource" 155 | }, 156 | { 157 | "current": { 158 | "selected": true, 159 | "text": [ 160 | "All" 161 | ], 162 | "value": [ 163 | "$__all" 164 | ] 165 | }, 166 | "datasource": { 167 | "type": "prometheus", 168 | "uid": "PDC1078F23EBDF0E5" 169 | }, 170 | "definition": "", 171 | "hide": 2, 172 | "includeAll": true, 173 | "label": "Node", 174 | "multi": true, 175 | "name": "osnodes", 176 | "options": [], 177 | "query": { 178 | "query": "label_values(up{exp_type='node'}, job)", 179 | "refId": "PROMETHEUS-osnodes-Variable-Query" 180 | }, 181 | "refresh": 1, 182 | "regex": "", 183 | "skipUrlSync": false, 184 | "sort": 1, 185 | "tagValuesQuery": "", 186 | "tagsQuery": "", 187 | "type": "query", 188 | "useTags": false 189 | } 190 | ] 191 | }, 192 | "time": { 193 | "from": "now-5m", 194 | "to": "now" 195 | }, 196 | "timepicker": { 197 | "time_options": [ 198 | "5m", 199 | "15m", 200 | "1h", 201 | "6h", 202 | "12h", 203 | "24h", 204 | "2d", 205 | "7d", 206 | "30d" 207 | ] 208 | }, 209 | "timezone": "browser", 210 | "title": "OS Overview", 211 | "uid": "pxinDnKik", 212 | "version": 1, 213 | "weekStart": "" 214 | } 215 | -------------------------------------------------------------------------------- /grafana/postgres/postgres_exporter/PG_Overview_postgres_exporter.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "datasource", 8 | "uid": "grafana" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "editable": false, 19 | "fiscalYearStartMonth": 0, 20 | "graphTooltip": 0, 21 | "links": [], 22 | "panels": [ 23 | { 24 | "datasource": { 25 | "type": "prometheus", 26 | "uid": "${ccp_datasource}" 27 | }, 28 | "fieldConfig": { 29 | "defaults": { 30 | "color": { 31 | "mode": "thresholds" 32 | }, 33 | "links": [ 34 | { 35 | "targetBlank": true, 36 | "title": "PG Details", 37 | "url": "/d/6jtN_vfiz/postgresql-details?$__all_variables&var-pgcluster=${__field.labels.cluster_name}" 38 | } 39 | ], 40 | "mappings": [ 41 | { 42 | "options": { 43 | "0": { 44 | "text": "DOWN" 45 | }, 46 | "1": { 47 | "text": "REPLICA" 48 | }, 49 | "0.5": { 50 | "text": "PRIMARY" 51 | } 52 | }, 53 | "type": "value" 54 | }, 55 | { 56 | "options": { 57 | "match": "null", 58 | "result": { 59 | "text": "DOWN" 60 | } 61 | }, 62 | "type": "special" 63 | } 64 | ], 65 | "thresholds": { 66 | "mode": "absolute", 67 | "steps": [ 68 | { 69 | "color": "rgba(245, 54, 54, 0.9)", 70 | "value": null 71 | }, 72 | { 73 | "color": "rgba(50, 172, 45, 0.9)", 74 | "value": 0.5 75 | }, 76 | { 77 | "color": "rgba(68, 126, 188, 0.9)", 78 | "value": 1 79 | } 80 | ] 81 | }, 82 | "unit": "none" 83 | }, 84 | "overrides": [] 85 | }, 86 | "gridPos": { 87 | "h": 4, 88 | "w": 8, 89 | "x": 0, 90 | "y": 0 91 | }, 92 | "id": 1, 93 | "maxDataPoints": 100, 94 | "options": { 95 | "colorMode": "background", 96 | "graphMode": "none", 97 | "justifyMode": "auto", 98 | "orientation": "horizontal", 99 | "reduceOptions": { 100 | "calcs": [ 101 | "last" 102 | ], 103 | "fields": "", 104 | "values": false 105 | }, 106 | "showPercentChange": false, 107 | "text": { 108 | "valueSize": 47 109 | }, 110 | "textMode": "auto", 111 | "wideLayout": true 112 | }, 113 | "pluginVersion": "10.4.2", 114 | "repeat": "pgnodes", 115 | "repeatDirection": "h", 116 | "targets": [ 117 | { 118 | "datasource": { 119 | "type": "prometheus", 120 | "uid": "${ccp_datasource}" 121 | }, 122 | "expr": "pg_up{job=~\"[[pgnodes]]\"} / ccp_is_in_recovery_status{job=~\"[[pgnodes]]\"}", 123 | "format": "time_series", 124 | "interval": "", 125 | "intervalFactor": 1, 126 | "legendFormat": "", 127 | "metric": "up", 128 | "refId": "A", 129 | "step": 2 130 | } 131 | ], 132 | "title": "[[pgnodes]]", 133 | "type": "stat" 134 | } 135 | ], 136 | "refresh": "5m", 137 | "schemaVersion": 39, 138 | "tags": [], 139 | "templating": { 140 | "list": [ 141 | { 142 | "current": { 143 | "selected": false, 144 | "text": "PROMETHEUS", 145 | "value": "PDC1078F23EBDF0E5" 146 | }, 147 | "hide": 0, 148 | "includeAll": false, 149 | "label": "Datasource", 150 | "multi": false, 151 | "name": "ccp_datasource", 152 | "options": [], 153 | "query": "prometheus", 154 | "refresh": 1, 155 | "regex": "", 156 | "skipUrlSync": false, 157 | "type": "datasource" 158 | }, 159 | { 160 | "current": { 161 | "selected": true, 162 | "text": [ 163 | "All" 164 | ], 165 | "value": [ 166 | "$__all" 167 | ] 168 | }, 169 | "datasource": { 170 | "type": "prometheus", 171 | "uid": "PDC1078F23EBDF0E5" 172 | }, 173 | "definition": "", 174 | "hide": 2, 175 | "includeAll": true, 176 | "label": "PGCluster", 177 | "multi": true, 178 | "name": "pgnodes", 179 | "options": [], 180 | "query": { 181 | "query": "label_values(up{exp_type='pg'}, job)", 182 | "refId": "PROMETHEUS-pgnodes-Variable-Query" 183 | }, 184 | "refresh": 1, 185 | "regex": "", 186 | "skipUrlSync": false, 187 | "sort": 1, 188 | "tagValuesQuery": "", 189 | "tagsQuery": "", 190 | "type": "query", 191 | "useTags": false 192 | } 193 | ] 194 | }, 195 | "time": { 196 | "from": "now-5m", 197 | "to": "now" 198 | }, 199 | "timepicker": { 200 | "time_options": [ 201 | "5m", 202 | "15m", 203 | "1h", 204 | "6h", 205 | "12h", 206 | "24h", 207 | "2d", 208 | "7d", 209 | "30d" 210 | ] 211 | }, 212 | "timezone": "browser", 213 | "title": "PostgreSQL Overview", 214 | "uid": "pxinDnNik", 215 | "version": 1, 216 | "weekStart": "" 217 | } 218 | -------------------------------------------------------------------------------- /grafana/postgres/sql_exporter/PG_Overview_sql_exporter.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "datasource", 8 | "uid": "grafana" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "editable": false, 19 | "fiscalYearStartMonth": 0, 20 | "graphTooltip": 0, 21 | "links": [], 22 | "liveNow": false, 23 | "panels": [ 24 | { 25 | "datasource": { 26 | "type": "prometheus", 27 | "uid": "${ccp_datasource}" 28 | }, 29 | "fieldConfig": { 30 | "defaults": { 31 | "color": { 32 | "mode": "thresholds" 33 | }, 34 | "links": [ 35 | { 36 | "targetBlank": true, 37 | "title": "PG Details", 38 | "url": "/d/6jtN_vfiz/postgresql-details?$__all_variables&var-pgcluster=${__field.labels.cluster_name}" 39 | } 40 | ], 41 | "mappings": [ 42 | { 43 | "options": { 44 | "0": { 45 | "text": "DOWN" 46 | }, 47 | "1": { 48 | "text": "REPLICA" 49 | }, 50 | "0.5": { 51 | "text": "PRIMARY" 52 | } 53 | }, 54 | "type": "value" 55 | }, 56 | { 57 | "options": { 58 | "match": "null", 59 | "result": { 60 | "text": "DOWN" 61 | } 62 | }, 63 | "type": "special" 64 | } 65 | ], 66 | "thresholds": { 67 | "mode": "absolute", 68 | "steps": [ 69 | { 70 | "color": "rgba(245, 54, 54, 0.9)", 71 | "value": null 72 | }, 73 | { 74 | "color": "rgba(50, 172, 45, 0.9)", 75 | "value": 0.5 76 | }, 77 | { 78 | "color": "rgba(68, 126, 188, 0.9)", 79 | "value": 1 80 | } 81 | ] 82 | }, 83 | "unit": "none" 84 | }, 85 | "overrides": [] 86 | }, 87 | "gridPos": { 88 | "h": 4, 89 | "w": 8, 90 | "x": 0, 91 | "y": 0 92 | }, 93 | "id": 1, 94 | "maxDataPoints": 100, 95 | "options": { 96 | "colorMode": "background", 97 | "graphMode": "none", 98 | "justifyMode": "auto", 99 | "orientation": "horizontal", 100 | "reduceOptions": { 101 | "calcs": [ 102 | "last" 103 | ], 104 | "fields": "", 105 | "values": false 106 | }, 107 | "showPercentChange": false, 108 | "text": { 109 | "valueSize": 47 110 | }, 111 | "textMode": "auto", 112 | "wideLayout": true 113 | }, 114 | "pluginVersion": "10.4.2", 115 | "repeat": "pgnodes", 116 | "repeatDirection": "h", 117 | "targets": [ 118 | { 119 | "datasource": { 120 | "type": "prometheus", 121 | "uid": "${ccp_datasource}" 122 | }, 123 | "editorMode": "code", 124 | "expr": "up{exp_type=\"pg\", job=~\"[[pgnodes]]\"} / ccp_is_in_recovery_status{exp_type=\"pg\",job=~\"[[pgnodes]]\"}", 125 | "format": "time_series", 126 | "interval": "", 127 | "intervalFactor": 1, 128 | "legendFormat": "", 129 | "metric": "up", 130 | "range": true, 131 | "refId": "A", 132 | "step": 2 133 | } 134 | ], 135 | "title": "[[pgnodes]]", 136 | "type": "stat" 137 | } 138 | ], 139 | "refresh": "5m", 140 | "schemaVersion": 39, 141 | "tags": [], 142 | "templating": { 143 | "list": [ 144 | { 145 | "current": { 146 | "selected": false, 147 | "text": "PROMETHEUS", 148 | "value": "PDC1078F23EBDF0E5" 149 | }, 150 | "hide": 0, 151 | "includeAll": false, 152 | "label": "Datasource", 153 | "multi": false, 154 | "name": "ccp_datasource", 155 | "options": [], 156 | "query": "prometheus", 157 | "refresh": 1, 158 | "regex": "", 159 | "skipUrlSync": false, 160 | "type": "datasource" 161 | }, 162 | { 163 | "current": { 164 | "selected": true, 165 | "text": [ 166 | "All" 167 | ], 168 | "value": [ 169 | "$__all" 170 | ] 171 | }, 172 | "datasource": { 173 | "type": "prometheus", 174 | "uid": "PDC1078F23EBDF0E5" 175 | }, 176 | "definition": "label_values(up{exp_type='pg'},job)", 177 | "hide": 2, 178 | "includeAll": true, 179 | "label": "PGCluster", 180 | "multi": true, 181 | "name": "pgnodes", 182 | "options": [], 183 | "query": { 184 | "query": "label_values(up{exp_type='pg'},job)", 185 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 186 | }, 187 | "refresh": 1, 188 | "regex": "", 189 | "skipUrlSync": false, 190 | "sort": 1, 191 | "tagValuesQuery": "", 192 | "tagsQuery": "", 193 | "type": "query", 194 | "useTags": false 195 | } 196 | ] 197 | }, 198 | "time": { 199 | "from": "now-5m", 200 | "to": "now" 201 | }, 202 | "timepicker": { 203 | "time_options": [ 204 | "5m", 205 | "15m", 206 | "1h", 207 | "6h", 208 | "12h", 209 | "24h", 210 | "2d", 211 | "7d", 212 | "30d" 213 | ] 214 | }, 215 | "timezone": "browser", 216 | "title": "PostgreSQL Overview (sql_exporter)", 217 | "uid": "d991a161-466f-44fc-9fa4-dbf395c20279", 218 | "version": 1, 219 | "weekStart": "" 220 | } 221 | -------------------------------------------------------------------------------- /hugo/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | -------------------------------------------------------------------------------- /hugo/config.toml: -------------------------------------------------------------------------------- 1 | baseURL = "" 2 | 3 | canonifyurls = true 4 | DefaultContentLanguage = "current" 5 | languageCode = "en-us" 6 | relativeURLs = true 7 | 8 | title = "pgMonitor" 9 | theme = "crunchy-hugo-theme" 10 | 11 | pygmentsCodeFences = true 12 | pygmentsStyle = "solarized" 13 | publishDir = "../docs" 14 | 15 | defaultContentLanguage = "current" 16 | defaultContentLanguageInSubdir= true 17 | enableMissingTranslationPlaceholders = true 18 | 19 | [Languages] 20 | [Languages.current] 21 | title = "pgMonitor" 22 | weight = 1 23 | languageName = "current" 24 | 25 | [markup] 26 | [markup.goldmark.renderer] 27 | unsafe = true 28 | [markup.goldmark.extensions] 29 | typographer = false 30 | [markup.tableOfContents] 31 | endLevel = 3 32 | 33 | [params] 34 | showVisitedLinks = false # default is false 35 | themeStyle = "flex" # "original" or "flex" # default "flex" 36 | themeVariant = "" # choose theme variant "green", "gold" , "gray", "blue" (default) 37 | ordersectionsby = "weight" # ordersectionsby = "title" 38 | disableHomeIcon = false # default is false 39 | disableSearch = false # default is false 40 | disableNavChevron = false # set true to hide next/prev chevron, default is false 41 | highlightClientSide = false # set true to use highlight.pack.js instead of the default hugo chroma highlighter 42 | menushortcutsnewtab = true # set true to open shortcuts links to a new tab/window 43 | enableGitInfo = true 44 | 45 | [outputs] 46 | home = [ "HTML", "RSS", "JSON"] 47 | 48 | [[menu.shortcuts]] 49 | pre = "

More

" 50 | name = " " 51 | identifier = "ds" 52 | url = "https://github.com/CrunchyData/pgmonitor" 53 | weight = 10 54 | 55 | [[menu.shortcuts]] 56 | name = " " 57 | url = "https://github.com/CrunchyData/pgmonitor/blob/master/LICENSE" 58 | weight = 20 59 | 60 | [[menu.shortcuts]] 61 | name = " " 62 | url = "https://access.crunchydata.com/documentation" 63 | weight = 30 64 | 65 | [[menu.downloads]] 66 | name = " " 67 | url = "/pdf/pgmonitor.pdf" 68 | weight = 20 69 | 70 | [[menu.downloads]] 71 | name = " " 72 | url = "/epub/pgmonitor.epub" 73 | weight = 30 74 | -------------------------------------------------------------------------------- /hugo/content/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/content/.gitkeep -------------------------------------------------------------------------------- /hugo/content/_index.md: -------------------------------------------------------------------------------- 1 | # pgMonitor 2 | 3 | {{< logo src="/images/pgmonitor_logo.svg" text="Crunchy Monitoring" >}} 4 | 5 | ### [pgMonitor](https://github.com/CrunchyData/pgMonitor) is your all-in-one tool to easily create an environment to visualize the health and performance of your [PostgreSQL](http://www.postgresql.org/) cluster. 6 | 7 | ![pgMonitor](/images/PGMonitor.gif) 8 | 9 | pgMonitor combines a suite of tools to facilitate the collection and visualization of important metrics that you need be aware of in your PostgreSQL database and your host environment, including: 10 | 11 | - Connection counts: how busy is your system being accessed and if connections are hanging 12 | - Database size: how much disk your cluster is using 13 | - Replication lag: know if your replicas are falling behind in loading data from your primary 14 | - Transaction wraparound: don't let your PostgreSQL database stop working 15 | - Bloat: how much extra space are your tables and indexes using 16 | - System metrics: CPU, Memory, I/O, uptime 17 | 18 | pgMonitor is also highly configurable, and advanced users can design their own metrics, visualizations, and add in other features such as alerting. 19 | 20 | Running pgMonitor will give you confidence in understanding how well your PostgreSQL cluster is performing, and will provide you the information to make calculated adjustments to your environment. 21 | 22 | --- 23 | 24 | ## Contents 25 | 26 | - [Purpose](#purpose) 27 | - [Supported Platforms](#supported-platforms) 28 | - [Operating Systems](#operating-systems) 29 | - [PostgreSQL](#postgresql) 30 | - [Installation](#installation) 31 | - [Roadmap](#roadmap) 32 | - [Version History](#version-history) 33 | - [Sponsors](#sponsors) 34 | - [Legal Notices](#legal-notices) 35 | 36 | --- 37 | 38 | ## Purpose 39 | 40 | pgMonitor is an open-source monitoring solution for PostgreSQL and the systems that it runs on. pgMonitor came from the need to provide a way to easily create a visual environment to monitor all the metrics a database administrator needs to proactively ensure the health of the system. 41 | 42 | pgMonitor combines multiple open-source software services to create a robust PostgreSQL monitoring environment. These include: 43 | 44 | - [Prometheus](https://prometheus.io/) - an open-source metrics collector that is highly customizable. 45 | - [Grafana](https://grafana.com/) - an open-source data visualizer that allows you to generate many different kinds of charts and graphs. 46 | - [SQL Exporter](https://github.com/burningalchemist/sql_exporter) - an open-source exporter for Prometheus that supports collecting metrics from multiple database systems including PostgreSQL. 47 | - [pgMonitor extension](https://github.com/CrunchyData/pgmonitor-extension) - a PostgreSQL extension that provides a means to collect metrics that can be used by an external collection source. 48 | 49 | ![pgMonitor](/images/crunchy-monitoring-arch.png) 50 | 51 | ## Supported Platforms 52 | 53 | ### pgMonitor Extension 54 | - As of pgMonitor version 5.2, the pgMonitor extension version requirement is a minimum of 2.1.0 55 | 56 | ### Operating Systems 57 | 58 | - RHEL 8/9 (Build/Run Testing, Setup Instructions) 59 | - Ubuntu 20/22 (Build/Run Testing) 60 | 61 | ### PostgreSQL 62 | 63 | - pgMonitor plans to support all PostgreSQL versions that are actively supported by the PostgreSQL community. Once a major version of PostgreSQL reaches its end-of-life (EOL), pgMonitor will cease supporting that major version soon after. Please see the official PostgreSQL website for [community supported releases](https://www.postgresql.org/support/versioning/). 64 | 65 | ### etcd 66 | 67 | - Version 3.5 and greater is supported for the Grafana dashboard 68 | 69 | ### HAProxy 70 | 71 | - Version 2.x for Grafana dashboard 72 | 73 | ### PgBouncer 74 | 75 | - PgBouncer 1.21+ 76 | - pgbouncer_fdw 1.1.0 (optional with sql_exporter) 77 | 78 | ## Installation 79 | 80 | Installation instructions for each package are provided in that packages subfolder. Each step in the installation process is listed here, with a link to additional to further installation instructions for each package. 81 | 82 | ### 1. [exporter](/exporter) 83 | 84 | ### 2. [Prometheus](/prometheus) 85 | 86 | ### 3. [Grafana](/grafana) 87 | 88 | Notes on upgrading can be found in each relevant section. 89 | 90 | ## Version History 91 | 92 | For the [full history](/changelog) of pgMonitor, please see the [CHANGELOG](/changelog). 93 | 94 | ## Sponsors 95 | 96 | [{{< logo src="/images/crunchy_logo.png" text="Crunchy Data" >}}](https://www.crunchydata.com/) 97 | 98 | [Crunchy Data](https://www.crunchydata.com/) is pleased to sponsor pgMonitor and many other [open-source projects](https://github.com/CrunchyData/) to help promote support the PostgreSQL community and software ecosystem. 99 | 100 | ## Legal Notices 101 | 102 | Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 103 | 104 | CRUNCHY DATA SOLUTIONS, INC. PROVIDES THIS GUIDE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 105 | 106 | Crunchy, Crunchy Data Solutions, Inc. and the Crunchy Hippo Logo are trademarks of Crunchy Data Solutions, Inc. All Rights Reserved. 107 | -------------------------------------------------------------------------------- /hugo/content/contributing/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Contributing" 3 | draft: false 4 | weight: 4 5 | --- 6 | 7 | ## Getting Started 8 | 9 | Welcome! Thank you for your interest in contributing. Before submitting a new [issue](https://github.com/CrunchyData/pgmonitor/issues/new) 10 | or [pull request](https://github.com/CrunchyData/pgmonitor/pulls) to the [pgmonitor](https://github.com/CrunchyData/pgmonitor/) project on GitHub, 11 | *please review any open or closed issues* [here](https://github.com/crunchydata/pgmonitor/issues) in addition to any existing open pull requests. 12 | 13 | ## Documentation 14 | 15 | The [documentation website](https://crunchydata.github.io/pgmonitor/) is generated using [Hugo](https://gohugo.io/) and 16 | [GitHub Pages](https://pages.github.com/). 17 | 18 | ## Hosting Hugo Locally (Optional) 19 | 20 | If you would like to build the documentation locally, view the 21 | [official Installing Hugo](https://gohugo.io/getting-started/installing/) guide to set up Hugo locally. You can then start the server by 22 | running the following commands - 23 | 24 | ```sh 25 | cd $CCPROOT/hugo/ 26 | vi config.toml 27 | hugo server 28 | ``` 29 | 30 | The local version of the Hugo server is accessible by default from 31 | `localhost:1313`. Once you've run `hugo server`, that will let you interactively make changes to the documentation as desired and view the updates 32 | in real-time. 33 | -------------------------------------------------------------------------------- /hugo/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/data/.gitkeep -------------------------------------------------------------------------------- /hugo/data/css.toml: -------------------------------------------------------------------------------- 1 | file = "main.css" 2 | -------------------------------------------------------------------------------- /hugo/layouts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/layouts/.gitkeep -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/include-file.html: -------------------------------------------------------------------------------- 1 | {{ $file := .Get "file" }} 2 | {{- with .Site.GetPage $file -}}{{ .Content }}{{- end -}} 3 | -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/logo.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/note.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | {{.Inner|markdownify}} 7 |
8 |
9 | -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/role.html: -------------------------------------------------------------------------------- 1 | {{.Inner|markdownify}} 2 | -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/shell.html: -------------------------------------------------------------------------------- 1 | {{.Inner|markdownify}} 2 | -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/toc.html: -------------------------------------------------------------------------------- 1 | {{ if .Page.Params.toc }} 2 |
3 | {{ .Page.TableOfContents }} 4 |
5 | {{ end }} 6 | -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/warn.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | {{.Inner|markdownify}} 7 |
8 |
9 | -------------------------------------------------------------------------------- /hugo/layouts/shortcodes/yaml.html: -------------------------------------------------------------------------------- 1 | {{.Inner|markdownify}} 2 | -------------------------------------------------------------------------------- /hugo/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/.gitkeep -------------------------------------------------------------------------------- /hugo/static/css/main.css: -------------------------------------------------------------------------------- 1 | * { 2 | line-height: 1.75rem; 3 | } 4 | 5 | div.content nav#TableOfContents ul li { 6 | list-style-type: none; 7 | } 8 | 9 | div.note { 10 | -moz-border-radius: 6px; 11 | -webkit-border-radius: 6px; 12 | background-color: #f0f7fb; 13 | background-image: url(/images/Note-48.png); 14 | background-position: left center; 15 | background-repeat: no-repeat; 16 | border: solid 1px #3498db; 17 | border-radius: 6px; 18 | line-height: 18px; 19 | overflow: hidden; 20 | padding: 1rem 4rem; 21 | margin-bottom: 1rem; 22 | } 23 | 24 | div.warn { 25 | -moz-border-radius: 6px; 26 | -webkit-border-radius: 6px; 27 | background-color: #fffacd; 28 | background-image: url(/images/Warn-48.png); 29 | background-position: left center; 30 | background-repeat: no-repeat; 31 | border: solid 1px #ccc688; 32 | border-radius: 6px; 33 | line-height: 18px; 34 | overflow: hidden; 35 | padding: 1rem 4rem; 36 | margin-bottom: 1rem; 37 | } 38 | 39 | img.logo { 40 | max-height: 200px; 41 | height: auto; 42 | width: auto; 43 | } 44 | 45 | span { 46 | padding: 0.25rem; 47 | } 48 | 49 | span.role { 50 | background: #4d99d0; 51 | color: ghostwhite; 52 | font-family: monospace; 53 | } 54 | 55 | span.shell { 56 | background: #085584; 57 | color: white; 58 | font-family: monospace; 59 | } 60 | 61 | span.yaml { 62 | background: #edc606; 63 | color: darkslategray; 64 | font-family: monospace; 65 | font-weight: bold; 66 | } 67 | .notice { 68 | -moz-border-radius: 6px; 69 | -webkit-border-radius: 6px; 70 | border-radius: 6px; 71 | line-height: 18px; 72 | overflow: hidden; 73 | padding: 1rem 2rem; 74 | margin-bottom: 1rem; 75 | margin-top: 1rem; 76 | display: inline-flex; 77 | width: 100%; 78 | } 79 | 80 | .notice .content { 81 | display: inline-block; 82 | margin: auto 0; 83 | } 84 | 85 | .notice .content * { 86 | word-wrap: break-word; 87 | white-space: pre-wrap; 88 | } 89 | 90 | .notice .icon { 91 | display: flex; 92 | justify-content: center; 93 | margin: auto 2rem auto 0; 94 | } 95 | 96 | .notice.note { 97 | background-color: #f0f7fb; 98 | border: solid 1px #3498db; 99 | } 100 | 101 | .notice.note .icon { 102 | color: #3498db; 103 | } 104 | 105 | .notice.warn { 106 | background-color: #fffacd; 107 | border: solid 1px #ff6347; 108 | } 109 | 110 | .notice.warn .icon { 111 | color: #ff6347; 112 | } 113 | 114 | @media (min-width: 1200px) { 115 | .notice i { 116 | font-size: 3rem; 117 | } 118 | } 119 | 120 | @media (max-width: 1199.98px) { 121 | .notice i { 122 | font-size: 2rem; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /hugo/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/favicon.png -------------------------------------------------------------------------------- /hugo/static/images/01-Overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/01-Overview.png -------------------------------------------------------------------------------- /hugo/static/images/10-OS Overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/10-OS Overview.png -------------------------------------------------------------------------------- /hugo/static/images/11-OS Details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/11-OS Details.png -------------------------------------------------------------------------------- /hugo/static/images/12-Filesystem Details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/12-Filesystem Details.png -------------------------------------------------------------------------------- /hugo/static/images/20-PostgreSQL Overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/20-PostgreSQL Overview.png -------------------------------------------------------------------------------- /hugo/static/images/21-PostgreSQL Details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/21-PostgreSQL Details.png -------------------------------------------------------------------------------- /hugo/static/images/22-PGBackrest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/22-PGBackrest.png -------------------------------------------------------------------------------- /hugo/static/images/23-TableSize Details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/23-TableSize Details.png -------------------------------------------------------------------------------- /hugo/static/images/24-CRUD Details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/24-CRUD Details.png -------------------------------------------------------------------------------- /hugo/static/images/30-ETCD Details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/30-ETCD Details.png -------------------------------------------------------------------------------- /hugo/static/images/PGMonitor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/PGMonitor.gif -------------------------------------------------------------------------------- /hugo/static/images/btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/btn.png -------------------------------------------------------------------------------- /hugo/static/images/crunchy-monitoring-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/crunchy-monitoring-arch.png -------------------------------------------------------------------------------- /hugo/static/images/crunchy_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/crunchy_logo.png -------------------------------------------------------------------------------- /hugo/static/images/pgmonitor_pgdetails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/pgmonitor_pgdetails.png -------------------------------------------------------------------------------- /hugo/static/images/pgmonitor_top_level.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/hugo/static/images/pgmonitor_top_level.png -------------------------------------------------------------------------------- /node_exporter/common/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/node_exporter/common/.gitkeep -------------------------------------------------------------------------------- /node_exporter/linux/ccp_io_queue.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### 3 | # 4 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 5 | # 6 | ### 7 | 8 | # Additional metric option to monitor disk queue depth with node_exporter. Set the DISK variable to the disk system that is to be monitored 9 | 10 | IODIR=/var/lib/ccp_monitoring 11 | IOTMP=io_queue.tmp 12 | IOFILE=io_queue.prom 13 | DISK=vda 14 | if [ ! -d ${IODIR} ]; then 15 | mkdir ${IODIR} 16 | fi 17 | rm -f ${IODIR}/${IOTMP} 18 | echo "node_disk_queue_max{device=\"${DISK}\"} $(cat /sys/block/${DISK}/queue/nr_requests)" >>${IODIR}/${IOTMP} 19 | echo "node_disk_queue_cur{device=\"${DISK}\"} $(iostat -xmt -d 1 1 ${DISK} | grep ^${DISK} | awk '{print $9}')" >>${IODIR}/${IOTMP} 20 | mv ${IODIR}/${IOTMP} ${IODIR}/${IOFILE} 21 | -------------------------------------------------------------------------------- /node_exporter/linux/crunchy-node-exporter-service-rhel.conf: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must have a .conf extension to override the default service and activate the crunchy specific configuration 8 | # Note this file must live in /etc/systemd/system/node_exporter.service.d/ to work 9 | # 10 | # Override package service config with our own as needed. ExecStart must be reset. 11 | 12 | [Service] 13 | PermissionsStartOnly=true 14 | User=ccp_monitoring 15 | EnvironmentFile=/etc/sysconfig/node_exporter 16 | ExecStart= 17 | ExecStart=/usr/bin/node_exporter $OPT 18 | ExecReload=/usr/bin/kill -HUP $MAINPID 19 | Restart=always 20 | -------------------------------------------------------------------------------- /node_exporter/linux/sysconfig.node_exporter: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/node_exporter) 8 | # 9 | # --collector.textfile.directory: location that node_exporter will look for additional metric collection scripts to run 10 | # --collector.diskstats.ignored-devices: regex string of devices to ignore 11 | 12 | OPT="--collector.textfile.directory=/var/lib/ccp_monitoring/node_exporter --collector.diskstats.device-exclude=^(ram|loop|fd)\\d+$" 13 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg11/queries_general.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG11 queries_general.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_stat_bgwriter: 10 | query: "SELECT checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time, buffers_checkpoint, buffers_clean, maxwritten_clean, buffers_backend, buffers_backend_fsync, buffers_alloc, stats_reset FROM pg_catalog.pg_stat_bgwriter" 11 | metrics: 12 | - checkpoints_timed: 13 | usage: "GAUGE" 14 | description: "Number of scheduled checkpoints that have been performed" 15 | - checkpoints_req: 16 | usage: "GAUGE" 17 | description: "Number of requested checkpoints that have been performed" 18 | - checkpoint_write_time: 19 | usage: "GAUGE" 20 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds" 21 | - checkpoint_sync_time: 22 | usage: "GAUGE" 23 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds" 24 | - buffers_checkpoint: 25 | usage: "GAUGE" 26 | description: "Number of buffers written during checkpoints" 27 | - buffers_clean: 28 | usage: "GAUGE" 29 | description: "Number of buffers written by the background writer" 30 | - maxwritten_clean: 31 | usage: "GAUGE" 32 | description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" 33 | - buffers_backend: 34 | usage: "GAUGE" 35 | description: "Number of buffers written directly by a backend" 36 | - buffers_backend_fsync: 37 | usage: "GAUGE" 38 | description: "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)" 39 | - buffers_alloc: 40 | usage: "GAUGE" 41 | description: "Number of buffers allocated" 42 | - stats_reset: 43 | usage: "GAUGE" 44 | description: "Time at which these statistics were last reset" 45 | 46 | ### 47 | # 48 | # End File: PG11 queries_general.yml 49 | # 50 | ### 51 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg11/queries_pg_stat_statements.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG11 queries_pg_stat_statements.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_pg_stat_statements_total: 10 | query: "SELECT pg_get_userbyid(s.userid) as role, 11 | d.datname AS dbname, 12 | sum(s.calls) AS calls_count, 13 | sum(s.total_time) AS exec_time_ms, 14 | avg(s.mean_time) AS mean_exec_time_ms, 15 | sum(s.rows) AS row_count 16 | FROM public.pg_stat_statements s 17 | JOIN pg_catalog.pg_database d 18 | ON d.oid = s.dbid 19 | GROUP BY 1,2" 20 | metrics: 21 | - role: 22 | usage: "LABEL" 23 | description: "Role that executed the statement" 24 | - dbname: 25 | usage: "LABEL" 26 | description: "Database in which the statement was executed" 27 | - calls_count: 28 | usage: "GAUGE" 29 | description: "Total number of queries run per user/database" 30 | - exec_time_ms: 31 | usage: "GAUGE" 32 | description: "Total runtime of all queries per user/database" 33 | - mean_exec_time_ms: 34 | usage: "GAUGE" 35 | description: "Mean runtime of all queries per user/database" 36 | - row_count: 37 | usage: "GAUGE" 38 | description: "Total rows returned from all queries per user/database" 39 | 40 | 41 | ccp_pg_stat_statements_top_mean: 42 | query: "SELECT pg_get_userbyid(s.userid) as role, 43 | d.datname AS dbname, 44 | s.queryid, 45 | btrim(replace(left(s.query, 40), '\n', '')) AS query, 46 | max(s.mean_time) exec_time_ms 47 | FROM public.pg_stat_statements s 48 | JOIN pg_catalog.pg_database d 49 | ON d.oid = s.dbid 50 | GROUP BY 1,2,3,4 51 | ORDER BY 5 DESC 52 | LIMIT #PG_STAT_STATEMENTS_LIMIT#" 53 | metrics: 54 | - role: 55 | usage: "LABEL" 56 | description: "Role that executed the statement" 57 | - dbname: 58 | usage: "LABEL" 59 | description: "Database in which the statement was executed" 60 | - queryid: 61 | usage: "LABEL" 62 | description: "Internal hash code, computed from the statement's parse tree" 63 | - query: 64 | usage: "LABEL" 65 | description: "First 40 characters of query text" 66 | - exec_time_ms: 67 | usage: "GAUGE" 68 | description: "Average query runtime in milliseconds" 69 | 70 | 71 | # Note that individual query stats can only be reset in PG12 72 | ccp_pg_stat_statements_top_total: 73 | query: "SELECT pg_get_userbyid(s.userid) as role, 74 | d.datname AS dbname, 75 | s.queryid, 76 | btrim(replace(left(s.query, 40), '\n', '')) AS query, 77 | s.total_time exec_time_ms 78 | FROM public.pg_stat_statements s 79 | JOIN pg_catalog.pg_database d 80 | ON d.oid = s.dbid 81 | ORDER BY 5 DESC 82 | LIMIT #PG_STAT_STATEMENTS_LIMIT#" 83 | metrics: 84 | - role: 85 | usage: "LABEL" 86 | description: "Role that executed the statement" 87 | - dbname: 88 | usage: "LABEL" 89 | description: "Database in which the statement was executed" 90 | - queryid: 91 | usage: "LABEL" 92 | description: "Internal hash code, computed from the statement's parse tree" 93 | - query: 94 | usage: "LABEL" 95 | description: "First 40 characters of query text" 96 | - exec_time_ms: 97 | usage: "GAUGE" 98 | description: "Total time spent in the statement in milliseconds" 99 | 100 | 101 | # Note that individual query stats can only be reset in PG12 102 | ccp_pg_stat_statements_top_max: 103 | query: "SELECT pg_get_userbyid(s.userid) as role, 104 | d.datname AS dbname, 105 | s.queryid, 106 | btrim(replace(left(s.query, 40), '\n', '')) AS query, 107 | s.max_time AS exec_time_ms 108 | FROM public.pg_stat_statements s 109 | JOIN pg_catalog.pg_database d 110 | ON d.oid = s.dbid 111 | ORDER BY 5 DESC 112 | LIMIT #PG_STAT_STATEMENTS_LIMIT#" 113 | metrics: 114 | - role: 115 | usage: "LABEL" 116 | description: "Role that executed the statement" 117 | - dbname: 118 | usage: "LABEL" 119 | description: "Database in which the statement was executed" 120 | - queryid: 121 | usage: "LABEL" 122 | description: "Internal hash code, computed from the statement's parse tree" 123 | - query: 124 | usage: "LABEL" 125 | description: "First 40 characters of query text" 126 | - exec_time_ms: 127 | usage: "GAUGE" 128 | description: "Maximum time spent in the statement in milliseconds" 129 | 130 | 131 | ### 132 | # 133 | # End File: PG11 queries_pg_stat_statements.yml 134 | # 135 | ### 136 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg12/queries_general.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG12 queries_general.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_stat_bgwriter: 10 | query: "SELECT checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time, buffers_checkpoint, buffers_clean, maxwritten_clean, buffers_backend, buffers_backend_fsync, buffers_alloc, stats_reset FROM pg_catalog.pg_stat_bgwriter" 11 | metrics: 12 | - checkpoints_timed: 13 | usage: "GAUGE" 14 | description: "Number of scheduled checkpoints that have been performed" 15 | - checkpoints_req: 16 | usage: "GAUGE" 17 | description: "Number of requested checkpoints that have been performed" 18 | - checkpoint_write_time: 19 | usage: "GAUGE" 20 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds" 21 | - checkpoint_sync_time: 22 | usage: "GAUGE" 23 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds" 24 | - buffers_checkpoint: 25 | usage: "GAUGE" 26 | description: "Number of buffers written during checkpoints" 27 | - buffers_clean: 28 | usage: "GAUGE" 29 | description: "Number of buffers written by the background writer" 30 | - maxwritten_clean: 31 | usage: "GAUGE" 32 | description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" 33 | - buffers_backend: 34 | usage: "GAUGE" 35 | description: "Number of buffers written directly by a backend" 36 | - buffers_backend_fsync: 37 | usage: "GAUGE" 38 | description: "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)" 39 | - buffers_alloc: 40 | usage: "GAUGE" 41 | description: "Number of buffers allocated" 42 | - stats_reset: 43 | usage: "GAUGE" 44 | description: "Time at which these statistics were last reset" 45 | 46 | ccp_data_checksum_failure: 47 | query: "SELECT datname AS dbname 48 | , checksum_failures AS count 49 | , coalesce(extract(epoch from (clock_timestamp() - checksum_last_failure)), 0) AS time_since_last_failure_seconds 50 | FROM pg_catalog.pg_stat_database;" 51 | metrics: 52 | - dbname: 53 | usage: "LABEL" 54 | description: "Database name" 55 | - count: 56 | usage: "GAUGE" 57 | description: "Total number of checksum failures on this database" 58 | - time_since_last_failure_seconds: 59 | usage: "GAUGE" 60 | description: "Time interval in seconds since the last checksum failure was encountered" 61 | 62 | 63 | ### 64 | # 65 | # End File: PG12 queries_general.yml 66 | # 67 | ### 68 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg12/queries_pg_stat_statements.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG12 queries_pg_stat_statements.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_pg_stat_statements_total: 10 | query: "SELECT pg_get_userbyid(s.userid) as role, 11 | d.datname AS dbname, 12 | sum(s.calls) AS calls_count, 13 | sum(s.total_time) AS exec_time_ms, 14 | avg(s.mean_time) AS mean_exec_time_ms, 15 | sum(s.rows) AS row_count 16 | FROM public.pg_stat_statements s 17 | JOIN pg_catalog.pg_database d 18 | ON d.oid = s.dbid 19 | GROUP BY 1,2" 20 | metrics: 21 | - role: 22 | usage: "LABEL" 23 | description: "Role that executed the statement" 24 | - dbname: 25 | usage: "LABEL" 26 | description: "Database in which the statement was executed" 27 | - calls_count: 28 | usage: "GAUGE" 29 | description: "Total number of queries run per user/database" 30 | - exec_time_ms: 31 | usage: "GAUGE" 32 | description: "Total runtime of all queries per user/database" 33 | - mean_exec_time_ms: 34 | usage: "GAUGE" 35 | description: "Mean runtime of all queries per user/database" 36 | - row_count: 37 | usage: "GAUGE" 38 | description: "Total rows returned from all queries per user/database" 39 | 40 | 41 | ccp_pg_stat_statements_top_mean: 42 | query: "SELECT pg_get_userbyid(s.userid) as role, 43 | d.datname AS dbname, 44 | s.queryid, 45 | btrim(replace(left(s.query, 40), '\n', '')) AS query, 46 | max(s.mean_time) exec_time_ms 47 | FROM public.pg_stat_statements s 48 | JOIN pg_catalog.pg_database d 49 | ON d.oid = s.dbid 50 | GROUP BY 1,2,3,4 51 | ORDER BY 5 DESC 52 | LIMIT #PG_STAT_STATEMENTS_LIMIT#" 53 | metrics: 54 | - role: 55 | usage: "LABEL" 56 | description: "Role that executed the statement" 57 | - dbname: 58 | usage: "LABEL" 59 | description: "Database in which the statement was executed" 60 | - queryid: 61 | usage: "LABEL" 62 | description: "Internal hash code, computed from the statement's parse tree" 63 | - query: 64 | usage: "LABEL" 65 | description: "First 40 characters of query text" 66 | - exec_time_ms: 67 | usage: "GAUGE" 68 | description: "Average query runtime in milliseconds" 69 | 70 | 71 | # Note that individual query stats can only be reset in PG12 72 | ccp_pg_stat_statements_top_total: 73 | query: "SELECT pg_get_userbyid(s.userid) as role, 74 | d.datname AS dbname, 75 | s.queryid, 76 | btrim(replace(left(s.query, 40), '\n', '')) AS query, 77 | s.total_time exec_time_ms 78 | FROM public.pg_stat_statements s 79 | JOIN pg_catalog.pg_database d 80 | ON d.oid = s.dbid 81 | ORDER BY 5 DESC 82 | LIMIT #PG_STAT_STATEMENTS_LIMIT#" 83 | metrics: 84 | - role: 85 | usage: "LABEL" 86 | description: "Role that executed the statement" 87 | - dbname: 88 | usage: "LABEL" 89 | description: "Database in which the statement was executed" 90 | - queryid: 91 | usage: "LABEL" 92 | description: "Internal hash code, computed from the statement's parse tree" 93 | - query: 94 | usage: "LABEL" 95 | description: "First 40 characters of query text" 96 | - exec_time_ms: 97 | usage: "GAUGE" 98 | description: "Total time spent in the statement in milliseconds" 99 | 100 | 101 | # Note that individual query stats can only be reset in PG12 102 | ccp_pg_stat_statements_top_max: 103 | query: "SELECT pg_get_userbyid(s.userid) as role, 104 | d.datname AS dbname, 105 | s.queryid, 106 | btrim(replace(left(s.query, 40), '\n', '')) AS query, 107 | s.max_time AS exec_time_ms 108 | FROM public.pg_stat_statements s 109 | JOIN pg_catalog.pg_database d 110 | ON d.oid = s.dbid 111 | ORDER BY 5 DESC 112 | LIMIT #PG_STAT_STATEMENTS_LIMIT#" 113 | metrics: 114 | - role: 115 | usage: "LABEL" 116 | description: "Role that executed the statement" 117 | - dbname: 118 | usage: "LABEL" 119 | description: "Database in which the statement was executed" 120 | - queryid: 121 | usage: "LABEL" 122 | description: "Internal hash code, computed from the statement's parse tree" 123 | - query: 124 | usage: "LABEL" 125 | description: "First 40 characters of query text" 126 | - exec_time_ms: 127 | usage: "GAUGE" 128 | description: "Maximum time spent in the statement in milliseconds" 129 | 130 | 131 | ### 132 | # 133 | # End File: PG12 queries_pg_stat_statements.yml 134 | # 135 | ### 136 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg12/queries_pg_stat_statements_reset_info.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: pg_stat_statements_reset_info.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | ccp_pg_stat_statements_reset: 9 | query: "select monitor.pg_stat_statements_reset_info(#PG_STAT_STATEMENTS_THROTTLE_MINUTES#) as time" 10 | metrics: 11 | - time: 12 | usage: "GAUGE" 13 | description: "Epoch time when stats were reset" 14 | 15 | ### 16 | # 17 | # End File: pg_stat_statements_reset_info.yml 18 | # 19 | ### 20 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg13/queries_general.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG13 queries_general.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_stat_bgwriter: 10 | query: "SELECT checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time, buffers_checkpoint, buffers_clean, maxwritten_clean, buffers_backend, buffers_backend_fsync, buffers_alloc, stats_reset FROM pg_catalog.pg_stat_bgwriter" 11 | metrics: 12 | - checkpoints_timed: 13 | usage: "GAUGE" 14 | description: "Number of scheduled checkpoints that have been performed" 15 | - checkpoints_req: 16 | usage: "GAUGE" 17 | description: "Number of requested checkpoints that have been performed" 18 | - checkpoint_write_time: 19 | usage: "GAUGE" 20 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds" 21 | - checkpoint_sync_time: 22 | usage: "GAUGE" 23 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds" 24 | - buffers_checkpoint: 25 | usage: "GAUGE" 26 | description: "Number of buffers written during checkpoints" 27 | - buffers_clean: 28 | usage: "GAUGE" 29 | description: "Number of buffers written by the background writer" 30 | - maxwritten_clean: 31 | usage: "GAUGE" 32 | description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" 33 | - buffers_backend: 34 | usage: "GAUGE" 35 | description: "Number of buffers written directly by a backend" 36 | - buffers_backend_fsync: 37 | usage: "GAUGE" 38 | description: "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)" 39 | - buffers_alloc: 40 | usage: "GAUGE" 41 | description: "Number of buffers allocated" 42 | - stats_reset: 43 | usage: "GAUGE" 44 | description: "Time at which these statistics were last reset" 45 | 46 | ccp_data_checksum_failure: 47 | query: "SELECT datname AS dbname 48 | , checksum_failures AS count 49 | , coalesce(extract(epoch from (clock_timestamp() - checksum_last_failure)), 0) AS time_since_last_failure_seconds 50 | FROM pg_catalog.pg_stat_database;" 51 | metrics: 52 | - dbname: 53 | usage: "LABEL" 54 | description: "Database name" 55 | - count: 56 | usage: "GAUGE" 57 | description: "Total number of checksum failures on this database" 58 | - time_since_last_failure_seconds: 59 | usage: "GAUGE" 60 | description: "Time interval in seconds since the last checksum failure was encountered" 61 | 62 | 63 | ### 64 | # 65 | # End File: PG13 queries_general.yml 66 | # 67 | ### 68 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg13/queries_pg_stat_statements_reset_info.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: pg_stat_statements_reset_info.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | ccp_pg_stat_statements_reset: 9 | query: "select monitor.pg_stat_statements_reset_info(#PG_STAT_STATEMENTS_THROTTLE_MINUTES#) as time" 10 | metrics: 11 | - time: 12 | usage: "GAUGE" 13 | description: "Epoch time when stats were reset" 14 | 15 | ### 16 | # 17 | # End File: pg_stat_statements_reset_info.yml 18 | # 19 | ### 20 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg14/queries_general.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG14 queries_general.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_stat_bgwriter: 10 | query: "SELECT checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time, buffers_checkpoint, buffers_clean, maxwritten_clean, buffers_backend, buffers_backend_fsync, buffers_alloc, stats_reset FROM pg_catalog.pg_stat_bgwriter" 11 | metrics: 12 | - checkpoints_timed: 13 | usage: "GAUGE" 14 | description: "Number of scheduled checkpoints that have been performed" 15 | - checkpoints_req: 16 | usage: "GAUGE" 17 | description: "Number of requested checkpoints that have been performed" 18 | - checkpoint_write_time: 19 | usage: "GAUGE" 20 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds" 21 | - checkpoint_sync_time: 22 | usage: "GAUGE" 23 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds" 24 | - buffers_checkpoint: 25 | usage: "GAUGE" 26 | description: "Number of buffers written during checkpoints" 27 | - buffers_clean: 28 | usage: "GAUGE" 29 | description: "Number of buffers written by the background writer" 30 | - maxwritten_clean: 31 | usage: "GAUGE" 32 | description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" 33 | - buffers_backend: 34 | usage: "GAUGE" 35 | description: "Number of buffers written directly by a backend" 36 | - buffers_backend_fsync: 37 | usage: "GAUGE" 38 | description: "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)" 39 | - buffers_alloc: 40 | usage: "GAUGE" 41 | description: "Number of buffers allocated" 42 | - stats_reset: 43 | usage: "GAUGE" 44 | description: "Time at which these statistics were last reset" 45 | 46 | ccp_data_checksum_failure: 47 | query: "SELECT datname AS dbname 48 | , checksum_failures AS count 49 | , coalesce(extract(epoch from (clock_timestamp() - checksum_last_failure)), 0) AS time_since_last_failure_seconds 50 | FROM pg_catalog.pg_stat_database;" 51 | metrics: 52 | - dbname: 53 | usage: "LABEL" 54 | description: "Database name" 55 | - count: 56 | usage: "GAUGE" 57 | description: "Total number of checksum failures on this database" 58 | - time_since_last_failure_seconds: 59 | usage: "GAUGE" 60 | description: "Time interval in seconds since the last checksum failure was encountered" 61 | 62 | 63 | ### 64 | # 65 | # End File: PG14 queries_general.yml 66 | # 67 | ### 68 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg14/queries_pg_stat_statements_reset_info.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: pg_stat_statements_reset_info.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | ccp_pg_stat_statements_reset: 9 | query: "select monitor.pg_stat_statements_reset_info(#PG_STAT_STATEMENTS_THROTTLE_MINUTES#) as time" 10 | metrics: 11 | - time: 12 | usage: "GAUGE" 13 | description: "Epoch time when stats were reset" 14 | 15 | ### 16 | # 17 | # End File: pg_stat_statements_reset_info.yml 18 | # 19 | ### 20 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg15/queries_general.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG15 queries_general.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_stat_bgwriter: 10 | query: "SELECT checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time, buffers_checkpoint, buffers_clean, maxwritten_clean, buffers_backend, buffers_backend_fsync, buffers_alloc, stats_reset FROM pg_catalog.pg_stat_bgwriter" 11 | metrics: 12 | - checkpoints_timed: 13 | usage: "GAUGE" 14 | description: "Number of scheduled checkpoints that have been performed" 15 | - checkpoints_req: 16 | usage: "GAUGE" 17 | description: "Number of requested checkpoints that have been performed" 18 | - checkpoint_write_time: 19 | usage: "GAUGE" 20 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds" 21 | - checkpoint_sync_time: 22 | usage: "GAUGE" 23 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds" 24 | - buffers_checkpoint: 25 | usage: "GAUGE" 26 | description: "Number of buffers written during checkpoints" 27 | - buffers_clean: 28 | usage: "GAUGE" 29 | description: "Number of buffers written by the background writer" 30 | - maxwritten_clean: 31 | usage: "GAUGE" 32 | description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" 33 | - buffers_backend: 34 | usage: "GAUGE" 35 | description: "Number of buffers written directly by a backend" 36 | - buffers_backend_fsync: 37 | usage: "GAUGE" 38 | description: "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)" 39 | - buffers_alloc: 40 | usage: "GAUGE" 41 | description: "Number of buffers allocated" 42 | - stats_reset: 43 | usage: "GAUGE" 44 | description: "Time at which these statistics were last reset" 45 | 46 | 47 | ccp_data_checksum_failure: 48 | query: "SELECT datname AS dbname 49 | , checksum_failures AS count 50 | , coalesce(extract(epoch from (clock_timestamp() - checksum_last_failure)), 0) AS time_since_last_failure_seconds 51 | FROM pg_catalog.pg_stat_database;" 52 | metrics: 53 | - dbname: 54 | usage: "LABEL" 55 | description: "Database name" 56 | - count: 57 | usage: "GAUGE" 58 | description: "Total number of checksum failures on this database" 59 | - time_since_last_failure_seconds: 60 | usage: "GAUGE" 61 | description: "Time interval in seconds since the last checksum failure was encountered" 62 | 63 | 64 | ### 65 | # 66 | # End File: PG15 queries_general.yml 67 | # 68 | ### 69 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg15/queries_pg_stat_statements_reset_info.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: pg_stat_statements_reset_info.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | ccp_pg_stat_statements_reset: 9 | query: "select monitor.pg_stat_statements_reset_info(#PG_STAT_STATEMENTS_THROTTLE_MINUTES#) as time" 10 | metrics: 11 | - time: 12 | usage: "GAUGE" 13 | description: "Epoch time when stats were reset" 14 | 15 | ### 16 | # 17 | # End File: pg_stat_statements_reset_info.yml 18 | # 19 | ### 20 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg16/queries_general.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG16 queries_general.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_stat_bgwriter: 10 | query: "SELECT checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time, buffers_checkpoint, buffers_clean, maxwritten_clean, buffers_backend, buffers_backend_fsync, buffers_alloc, stats_reset FROM pg_catalog.pg_stat_bgwriter" 11 | metrics: 12 | - checkpoints_timed: 13 | usage: "GAUGE" 14 | description: "Number of scheduled checkpoints that have been performed" 15 | - checkpoints_req: 16 | usage: "GAUGE" 17 | description: "Number of requested checkpoints that have been performed" 18 | - checkpoint_write_time: 19 | usage: "GAUGE" 20 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds" 21 | - checkpoint_sync_time: 22 | usage: "GAUGE" 23 | description: "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds" 24 | - buffers_checkpoint: 25 | usage: "GAUGE" 26 | description: "Number of buffers written during checkpoints" 27 | - buffers_clean: 28 | usage: "GAUGE" 29 | description: "Number of buffers written by the background writer" 30 | - maxwritten_clean: 31 | usage: "GAUGE" 32 | description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" 33 | - buffers_backend: 34 | usage: "GAUGE" 35 | description: "Number of buffers written directly by a backend" 36 | - buffers_backend_fsync: 37 | usage: "GAUGE" 38 | description: "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)" 39 | - buffers_alloc: 40 | usage: "GAUGE" 41 | description: "Number of buffers allocated" 42 | - stats_reset: 43 | usage: "GAUGE" 44 | description: "Time at which these statistics were last reset" 45 | 46 | 47 | ccp_data_checksum_failure: 48 | query: "SELECT datname AS dbname 49 | , checksum_failures AS count 50 | , coalesce(extract(epoch from (clock_timestamp() - checksum_last_failure)), 0) AS time_since_last_failure_seconds 51 | FROM pg_catalog.pg_stat_database;" 52 | metrics: 53 | - dbname: 54 | usage: "LABEL" 55 | description: "Database name" 56 | - count: 57 | usage: "GAUGE" 58 | description: "Total number of checksum failures on this database" 59 | - time_since_last_failure_seconds: 60 | usage: "GAUGE" 61 | description: "Time interval in seconds since the last checksum failure was encountered" 62 | 63 | 64 | ### 65 | # 66 | # End File: PG16 queries_general.yml 67 | # 68 | ### 69 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg16/queries_pg_stat_statements_reset_info.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: pg_stat_statements_reset_info.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | ccp_pg_stat_statements_reset: 9 | query: "select monitor.pg_stat_statements_reset_info(#PG_STAT_STATEMENTS_THROTTLE_MINUTES#) as time" 10 | metrics: 11 | - time: 12 | usage: "GAUGE" 13 | description: "Epoch time when stats were reset" 14 | 15 | ### 16 | # 17 | # End File: pg_stat_statements_reset_info.yml 18 | # 19 | ### 20 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg17/queries_general.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: PG17 queries_general.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | 9 | ccp_stat_bgwriter: 10 | query: "SELECT buffers_clean, maxwritten_clean, buffers_alloc FROM pg_catalog.pg_stat_bgwriter" 11 | metrics: 12 | - buffers_clean: 13 | usage: "GAUGE" 14 | description: "Number of buffers written by the background writer" 15 | - maxwritten_clean: 16 | usage: "GAUGE" 17 | description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" 18 | - buffers_alloc: 19 | usage: "GAUGE" 20 | description: "Number of buffers allocated" 21 | 22 | 23 | ccp_data_checksum_failure: 24 | query: "SELECT datname AS dbname 25 | , checksum_failures AS count 26 | , coalesce(extract(epoch from (clock_timestamp() - checksum_last_failure)), 0) AS time_since_last_failure_seconds 27 | FROM pg_catalog.pg_stat_database;" 28 | metrics: 29 | - dbname: 30 | usage: "LABEL" 31 | description: "Database name" 32 | - count: 33 | usage: "GAUGE" 34 | description: "Total number of checksum failures on this database" 35 | - time_since_last_failure_seconds: 36 | usage: "GAUGE" 37 | description: "Time interval in seconds since the last checksum failure was encountered" 38 | 39 | 40 | ### 41 | # 42 | # End File: PG17 queries_general.yml 43 | # 44 | ### 45 | -------------------------------------------------------------------------------- /postgres_exporter/common/pg17/queries_pg_stat_statements_reset_info.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Begin File: pg_stat_statements_reset_info.yml 4 | # 5 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 6 | # 7 | ### 8 | ccp_pg_stat_statements_reset: 9 | query: "select monitor.pg_stat_statements_reset_info(#PG_STAT_STATEMENTS_THROTTLE_MINUTES#) as time" 10 | metrics: 11 | - time: 12 | usage: "GAUGE" 13 | description: "Epoch time when stats were reset" 14 | 15 | ### 16 | # 17 | # End File: pg_stat_statements_reset_info.yml 18 | # 19 | ### 20 | -------------------------------------------------------------------------------- /postgres_exporter/common/queries_bloat.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | # Begin File: queries_bloat.yml 6 | # 7 | ### 8 | 9 | ccp_bloat_check: 10 | query: "SELECT current_database() AS dbname 11 | , schemaname 12 | , objectname 13 | , size_bytes 14 | , (dead_tuple_size_bytes + (free_space_bytes - (relpages - (fillfactor/100) * relpages ) * current_setting('block_size')::bigint ))::bigint AS total_wasted_space_bytes 15 | FROM bloat_stats" 16 | metrics: 17 | - dbname: 18 | usage: "LABEL" 19 | description: "Database name" 20 | - schemaname: 21 | usage: "LABEL" 22 | description: "Schema name" 23 | - objectname: 24 | usage: "LABEL" 25 | description: "Table or index name" 26 | - size_bytes: 27 | usage: "GAUGE" 28 | description: "Size of object in bytes" 29 | - total_wasted_space_bytes: 30 | usage: "GAUGE" 31 | description: "Total wasted space in bytes of given object" 32 | 33 | ### 34 | # 35 | # End File: queries_bloat.yml 36 | # 37 | ### 38 | -------------------------------------------------------------------------------- /postgres_exporter/common/queries_global_dbsize.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | # Begin File: queries_global_dbsize.yml 6 | # 7 | ### 8 | 9 | ccp_database_size: 10 | query: "SELECT datname as dbname, pg_database_size(datname) as bytes FROM pg_catalog.pg_database WHERE datistemplate = false" 11 | metrics: 12 | - dbname: 13 | usage: "LABEL" 14 | description: "Database name" 15 | - bytes: 16 | usage: "GAUGE" 17 | description: "Database size in bytes" 18 | 19 | ### 20 | # 21 | # End File: queries_global_dbsize.yml 22 | # 23 | ### 24 | -------------------------------------------------------------------------------- /postgres_exporter/common/queries_global_matview.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | # Begin File: queries_global_matview.yml 6 | # 7 | ### 8 | 9 | ccp_database_size: 10 | query: "SELECT dbname, bytes FROM monitor.ccp_database_size" 11 | metrics: 12 | - dbname: 13 | usage: "LABEL" 14 | description: "Database name" 15 | - bytes: 16 | usage: "GAUGE" 17 | description: "Database size in bytes" 18 | 19 | 20 | ### 21 | # 22 | # End File: queries_global_matview.yml 23 | # 24 | ### 25 | -------------------------------------------------------------------------------- /postgres_exporter/common/queries_per_db.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | # Begin File: queries_per_db.yml 6 | # 7 | ### 8 | 9 | ccp_stat_user_tables: 10 | query: "SELECT current_database() as dbname, schemaname, relname, 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 FROM pg_catalog.pg_stat_user_tables" 11 | metrics: 12 | - dbname: 13 | usage: "LABEL" 14 | description: "Database name" 15 | - schemaname: 16 | usage: "LABEL" 17 | description: "Name of the schema that this table is in" 18 | - relname: 19 | usage: "LABEL" 20 | description: "Name of this table" 21 | - seq_scan: 22 | usage: "COUNTER" 23 | description: "Number of sequential scans initiated on this table" 24 | - seq_tup_read: 25 | usage: "COUNTER" 26 | description: "Number of live rows fetched by sequential scans" 27 | - idx_scan: 28 | usage: "COUNTER" 29 | description: "Number of index scans initiated on this table" 30 | - idx_tup_fetch: 31 | usage: "COUNTER" 32 | description: "Number of live rows fetched by index scans" 33 | - n_tup_ins: 34 | usage: "COUNTER" 35 | description: "Number of rows inserted" 36 | - n_tup_upd: 37 | usage: "COUNTER" 38 | description: "Number of rows updated" 39 | - n_tup_del: 40 | usage: "COUNTER" 41 | description: "Number of rows deleted" 42 | - n_tup_hot_upd: 43 | usage: "COUNTER" 44 | description: "Number of rows HOT updated (i.e., with no separate index update required)" 45 | - n_live_tup: 46 | usage: "GAUGE" 47 | description: "Estimated number of live rows" 48 | - n_dead_tup: 49 | usage: "GAUGE" 50 | description: "Estimated number of dead rows" 51 | - vacuum_count: 52 | usage: "COUNTER" 53 | description: "Number of times this table has been manually vacuumed (not counting VACUUM FULL)" 54 | - autovacuum_count: 55 | usage: "COUNTER" 56 | description: "Number of times this table has been vacuumed by the autovacuum daemon" 57 | - analyze_count: 58 | usage: "COUNTER" 59 | description: "Number of times this table has been manually analyzed" 60 | - autoanalyze_count: 61 | usage: "COUNTER" 62 | description: "Number of times this table has been analyzed by the autovacuum daemon" 63 | 64 | 65 | ccp_table_size: 66 | query: "SELECT current_database() as dbname, relnamespace::regnamespace as schemaname, relname, pg_total_relation_size(oid) as size_bytes FROM pg_class WHERE NOT pg_is_other_temp_schema(relnamespace) AND relkind IN ('r', 'm', 'f')" 67 | metrics: 68 | - dbname: 69 | usage: "LABEL" 70 | description: "Database name" 71 | - schemaname: 72 | usage: "LABEL" 73 | description: "Schema name" 74 | - relname: 75 | usage: "LABEL" 76 | description: "Table name" 77 | - bytes: 78 | usage: "GAUGE" 79 | description: "Table size including indexes" 80 | 81 | ### 82 | # 83 | # End File: queries_per_db.yml 84 | # 85 | ### 86 | -------------------------------------------------------------------------------- /postgres_exporter/common/queries_per_db_matview.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | # Begin File: queries_per_db_matview.yml 6 | # 7 | ### 8 | 9 | ccp_stat_user_tables: 10 | query: "SELECT current_database() as dbname, schemaname, relname, 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 FROM monitor.ccp_stat_user_tables" 11 | metrics: 12 | - dbname: 13 | usage: "LABEL" 14 | description: "Database name" 15 | - schemaname: 16 | usage: "LABEL" 17 | description: "Name of the schema that this table is in" 18 | - relname: 19 | usage: "LABEL" 20 | description: "Name of this table" 21 | - seq_scan: 22 | usage: "COUNTER" 23 | description: "Number of sequential scans initiated on this table" 24 | - seq_tup_read: 25 | usage: "COUNTER" 26 | description: "Number of live rows fetched by sequential scans" 27 | - idx_scan: 28 | usage: "COUNTER" 29 | description: "Number of index scans initiated on this table" 30 | - idx_tup_fetch: 31 | usage: "COUNTER" 32 | description: "Number of live rows fetched by index scans" 33 | - n_tup_ins: 34 | usage: "COUNTER" 35 | description: "Number of rows inserted" 36 | - n_tup_upd: 37 | usage: "COUNTER" 38 | description: "Number of rows updated" 39 | - n_tup_del: 40 | usage: "COUNTER" 41 | description: "Number of rows deleted" 42 | - n_tup_hot_upd: 43 | usage: "COUNTER" 44 | description: "Number of rows HOT updated (i.e., with no separate index update required)" 45 | - n_live_tup: 46 | usage: "GAUGE" 47 | description: "Estimated number of live rows" 48 | - n_dead_tup: 49 | usage: "GAUGE" 50 | description: "Estimated number of dead rows" 51 | - vacuum_count: 52 | usage: "COUNTER" 53 | description: "Number of times this table has been manually vacuumed (not counting VACUUM FULL)" 54 | - autovacuum_count: 55 | usage: "COUNTER" 56 | description: "Number of times this table has been vacuumed by the autovacuum daemon" 57 | - analyze_count: 58 | usage: "COUNTER" 59 | description: "Number of times this table has been manually analyzed" 60 | - autoanalyze_count: 61 | usage: "COUNTER" 62 | description: "Number of times this table has been analyzed by the autovacuum daemon" 63 | 64 | 65 | ccp_table_size: 66 | query: "SELECT dbname, schemaname, relname, size_bytes FROM monitor.ccp_table_size" 67 | metrics: 68 | - dbname: 69 | usage: "LABEL" 70 | description: "Database name" 71 | - schemaname: 72 | usage: "LABEL" 73 | description: "Schema name" 74 | - relname: 75 | usage: "LABEL" 76 | description: "Table name" 77 | - bytes: 78 | usage: "GAUGE" 79 | description: "Table size including indexes" 80 | 81 | ### 82 | # 83 | # End File: queries_per_db_matview.yml 84 | # 85 | ### 86 | -------------------------------------------------------------------------------- /postgres_exporter/common/queries_pgbouncer.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | # Begin File: queries_pgbouncer.yml 6 | # 7 | ### 8 | 9 | ccp_pgbouncer_pools: 10 | query: "SELECT pgbouncer_target_host 11 | , database || '.' || p.user as conn_pool 12 | , sum(cl_active) AS client_active 13 | , sum(cl_waiting) AS client_waiting 14 | , sum(sv_active) AS server_active 15 | , sum(sv_idle) AS server_idle 16 | , sum(sv_used) AS server_used 17 | FROM pgbouncer_pools as p 18 | GROUP BY 1,2" 19 | metrics: 20 | - pgbouncer_target_host: 21 | usage: "LABEL" 22 | description: "FDW server name for the target PgBouncer host" 23 | - conn_pool: 24 | usage: "LABEL" 25 | description: "Connection Pool" 26 | - client_active: 27 | usage: "GAUGE" 28 | description: "Client connections that are linked to server connection and can process queries." 29 | - client_waiting: 30 | usage: "GAUGE" 31 | description: "Client connections that have sent queries but have not yet gotten a server connection." 32 | - server_active: 33 | usage: "GAUGE" 34 | description: "Server connections that are linked to a client." 35 | - server_idle: 36 | usage: "GAUGE" 37 | description: "Server connections that unused and immediately usable for client queries." 38 | - server_used: 39 | usage: "GAUGE" 40 | description: "Server connections that have been idle more than server_check_delay, so they need server_check_query to run on it before it can be used." 41 | 42 | ccp_pgbouncer_databases: 43 | query: "SELECT pgbouncer_target_host 44 | , name AS pool_db 45 | , CASE WHEN max_connections != 0 46 | THEN ((current_connections::float / max_connections::float) * 100)::int 47 | ELSE ((current_connections::float / pool_size::float) * 100)::int 48 | END AS db_conn_perc_used 49 | , paused 50 | , disabled 51 | FROM pgbouncer_databases" 52 | metrics: 53 | - pgbouncer_target_host: 54 | usage: "LABEL" 55 | description: "FDW server name for the target PgBouncer host" 56 | - pool_db: 57 | usage: "LABEL" 58 | description: "Database as known to pgbouncer" 59 | - db_conn_perc_used: 60 | usage: "GAUGE" 61 | description: "Percentage of available pooler connections for this database that are in use." 62 | - paused: 63 | usage: "GAUGE" 64 | description: "Pooler connections to this database are currently paused." 65 | - disabled: 66 | usage: "GAUGE" 67 | description: "Pooler connections to this database are currently disabled." 68 | 69 | ccp_pgbouncer_clients: 70 | query: "SELECT pgbouncer_target_host 71 | , database || '.' || p.user as conn_pool 72 | , state AS client_state 73 | , count(*) AS client_state_count 74 | FROM pgbouncer_clients as p 75 | GROUP BY 1,2,3" 76 | metrics: 77 | - pgbouncer_target_host: 78 | usage: "LABEL" 79 | description: "FDW server name for the target PgBouncer host" 80 | - conn_pool: 81 | usage: "LABEL" 82 | description: "Connection Pool" 83 | - client_state: 84 | usage: "LABEL" 85 | description: "Client connection statuses per database" 86 | - client_state_count: 87 | usage: "GAUGE" 88 | description: "Count of the client connections with this status." 89 | 90 | ccp_pgbouncer_servers: 91 | query: "SELECT pgbouncer_target_host 92 | , database || '.' || p.user as conn_pool 93 | , state as server_state 94 | , count(*) AS server_state_count 95 | FROM pgbouncer_servers as p 96 | GROUP BY 1,2,3" 97 | metrics: 98 | - pgbouncer_target_host: 99 | usage: "LABEL" 100 | description: "FDW server name for the target PgBouncer host" 101 | - conn_pool: 102 | usage: "LABEL" 103 | description: "Connection Pool" 104 | - server_state: 105 | usage: "LABEL" 106 | description: "Server connection statuses per database" 107 | - server_state_count: 108 | usage: "GAUGE" 109 | description: "Count of the server connections with this status." 110 | 111 | ccp_pgbouncer_lists: 112 | query: "SELECT pgbouncer_target_host 113 | , list AS item 114 | , items AS item_count 115 | FROM pgbouncer_lists 116 | WHERE list IN ('databases', 'pools', 'free_clients', 'free_servers', 'used_servers')" 117 | metrics: 118 | - pgbouncer_target_host: 119 | usage: "LABEL" 120 | description: "FDW server name for the target PgBouncer host" 121 | - item: 122 | usage: "LABEL" 123 | description: "Items that have registered with pgBouncer" 124 | - item_count: 125 | usage: "GAUGE" 126 | description: "Count of said items registered with pgBouncer" 127 | 128 | 129 | ### 130 | # 131 | # End File: queries_pgbouncer.yml 132 | # 133 | ### 134 | -------------------------------------------------------------------------------- /postgres_exporter/common/setup_metric_views.sql: -------------------------------------------------------------------------------- 1 | -- ######################### 2 | -- Metric View Objects 3 | -- ######################### 4 | 5 | CREATE SCHEMA IF NOT EXISTS monitor; 6 | 7 | -- Preserve existing data if users added more views or changed schedule. Allows setup call to be idempodent. 8 | DO $pgmonitor$ 9 | DECLARE 10 | v_exists smallint; 11 | BEGIN 12 | 13 | SELECT count(*) INTO v_exists FROM information_schema.tables WHERE table_schema = 'monitor' AND table_name = 'metric_views'; 14 | IF v_exists > 0 THEN 15 | CREATE TEMPORARY TABLE metric_views_preserve_temp (LIKE monitor.metric_views); 16 | INSERT INTO metric_views_preserve_temp SELECT * FROM monitor.metric_views; 17 | DROP TABLE monitor.metric_views; 18 | END IF; 19 | 20 | CREATE TABLE IF NOT EXISTS monitor.metric_views ( 21 | view_schema text NOT NULL DEFAULT 'monitor' 22 | , view_name text NOT NULL 23 | , concurrent_refresh boolean NOT NULL DEFAULT true 24 | , run_interval interval NOT NULL 25 | , last_run timestamptz 26 | , active boolean NOT NULL DEFAULT true 27 | , scope text NOT NULL default 'global' 28 | , CONSTRAINT metric_views_pk PRIMARY KEY (view_schema, view_name) 29 | , CONSTRAINT metric_views_scope_ck CHECK (scope IN ('global', 'database')) 30 | ); 31 | 32 | IF v_exists > 0 THEN 33 | INSERT INTO monitor.metric_views SELECT * FROM metric_views_preserve_temp; 34 | DROP TABLE metric_views_preserve_temp; 35 | END IF; 36 | 37 | END 38 | $pgmonitor$; 39 | 40 | 41 | DROP PROCEDURE IF EXISTS monitor.refresh_metric_views (text, text); 42 | CREATE PROCEDURE monitor.refresh_metric_views (p_view_schema text DEFAULT 'monitor', p_view_name text DEFAULT NULL) 43 | LANGUAGE plpgsql 44 | AS $$ 45 | DECLARE 46 | 47 | v_loop_sql text; 48 | v_refresh_sql text; 49 | v_recovery boolean; 50 | v_row record; 51 | 52 | BEGIN 53 | 54 | SELECT pg_is_in_recovery() INTO v_recovery; 55 | IF v_recovery THEN 56 | RAISE DEBUG 'Database instance in recovery mode. Exiting without view refresh'; 57 | RETURN; 58 | END IF; 59 | 60 | v_loop_sql := format('SELECT view_schema, view_name, concurrent_refresh 61 | FROM monitor.metric_views 62 | WHERE active 63 | AND ( last_run IS NULL OR (CURRENT_TIMESTAMP - last_run) > run_interval )'); 64 | 65 | IF p_view_name IS NOT NULL THEN 66 | v_loop_sql := format('%s AND view_schema = %L AND view_name = %L', v_loop_sql, p_view_schema, p_view_name); 67 | END IF; 68 | 69 | FOR v_row IN EXECUTE v_loop_sql LOOP 70 | 71 | v_refresh_sql := 'REFRESH MATERIALIZED VIEW '; 72 | IF v_row.concurrent_refresh THEN 73 | v_refresh_sql := v_refresh_sql || 'CONCURRENTLY '; 74 | END IF; 75 | v_refresh_sql := format('%s %I.%I', v_refresh_sql, v_row.view_schema, v_row.view_name); 76 | RAISE DEBUG 'pgmonitor view refresh: %s', v_refresh_sql; 77 | EXECUTE v_refresh_sql; 78 | 79 | UPDATE monitor.metric_views 80 | SET last_run = CURRENT_TIMESTAMP 81 | WHERE view_schema = v_row.view_schema 82 | AND view_name = v_row.view_name; 83 | 84 | COMMIT; 85 | 86 | END LOOP; 87 | 88 | END 89 | $$; 90 | 91 | DROP MATERIALIZED VIEW IF EXISTS monitor.ccp_stat_user_tables; 92 | CREATE MATERIALIZED VIEW monitor.ccp_stat_user_tables 93 | AS SELECT current_database() as dbname 94 | , schemaname 95 | , relname 96 | , seq_scan 97 | , seq_tup_read 98 | , idx_scan 99 | , idx_tup_fetch 100 | , n_tup_ins 101 | , n_tup_upd 102 | , n_tup_del 103 | , n_tup_hot_upd 104 | , n_live_tup 105 | , n_dead_tup 106 | , vacuum_count 107 | , autovacuum_count 108 | , analyze_count 109 | , autoanalyze_count 110 | FROM pg_catalog.pg_stat_user_tables; 111 | CREATE UNIQUE INDEX ccp_user_tables_db_schema_relname_idx ON monitor.ccp_stat_user_tables (dbname, schemaname, relname); 112 | ALTER MATERIALIZED VIEW monitor.ccp_stat_user_tables OWNER TO ccp_monitoring; 113 | 114 | 115 | DROP MATERIALIZED VIEW IF EXISTS monitor.ccp_table_size; 116 | CREATE MATERIALIZED VIEW monitor.ccp_table_size 117 | AS SELECT current_database() as dbname 118 | , n.nspname as schemaname 119 | , c.relname 120 | , pg_total_relation_size(c.oid) as size_bytes 121 | FROM pg_catalog.pg_class c 122 | JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid 123 | WHERE NOT pg_is_other_temp_schema(n.oid) 124 | AND relkind IN ('r', 'm', 'f'); 125 | CREATE UNIQUE INDEX ccp_table_size_idx ON monitor.ccp_table_size (dbname, schemaname, relname); 126 | ALTER MATERIALIZED VIEW monitor.ccp_table_size OWNER TO ccp_monitoring; 127 | 128 | 129 | DROP MATERIALIZED VIEW IF EXISTS monitor.ccp_database_size; 130 | CREATE MATERIALIZED VIEW monitor.ccp_database_size 131 | AS SELECT datname as dbname 132 | , pg_database_size(datname) as bytes 133 | FROM pg_catalog.pg_database 134 | WHERE datistemplate = false; 135 | CREATE UNIQUE INDEX ccp_database_size_idx ON monitor.ccp_database_size (dbname); 136 | ALTER MATERIALIZED VIEW monitor.ccp_database_size OWNER TO ccp_monitoring; 137 | 138 | 139 | GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA monitor TO ccp_monitoring; 140 | GRANT ALL ON ALL TABLES IN SCHEMA monitor TO ccp_monitoring; 141 | 142 | -- Don't alter any existing data that is already there for any given view 143 | INSERT INTO monitor.metric_views ( 144 | view_name 145 | , run_interval 146 | , scope ) 147 | VALUES ( 148 | 'ccp_stat_user_tables' 149 | , '10 minutes'::interval 150 | , 'database') 151 | ON CONFLICT DO NOTHING; 152 | 153 | INSERT INTO monitor.metric_views ( 154 | view_name 155 | , run_interval 156 | , scope ) 157 | VALUES ( 158 | 'ccp_table_size' 159 | , '10 minutes'::interval 160 | , 'database') 161 | ON CONFLICT DO NOTHING; 162 | 163 | INSERT INTO monitor.metric_views ( 164 | view_name 165 | , run_interval 166 | , scope ) 167 | VALUES ( 168 | 'ccp_database_size' 169 | , '10 minutes'::interval 170 | , 'global') 171 | ON CONFLICT DO NOTHING; 172 | -------------------------------------------------------------------------------- /postgres_exporter/linux/crontab.txt: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | # The below script must be run as a user with the pg_read_all_data role or a superuser. You may have to adjust your pg_hba.conf to allow this and/or use a .pgpass file 7 | # By default only scans and stores statistics for objects that are at least 1GB in size (--min_size). Setting --quiet twice, as shown, suppresses all output. 8 | # 08 03 * * 0 /usr/bin/pg_bloat_check.py --quiet --quiet -c "dbname=postgres user=ccp_monitoring" --min_size=1073741824 9 | 10 | # If using the materialized views for certain metrics, set the below cronjob to run at least as often as the lowest configured refresh interval 11 | # If collecting per-database metrics, additional entries, one per database, will be needed 12 | # */06 * * * * psql -h localhost -U ccp_monitoring -d postgres -q -c "CALL monitor.refresh_metric_views()" 13 | -------------------------------------------------------------------------------- /postgres_exporter/linux/crunchy-postgres-exporter@.service: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | # Template systemd service file to allow multiple postgres exporters to run with 7 | # a simple variable in service name to distinguish the environment file 8 | # Ex: systemctl enable postgres_exporter@postgres_exporter_mydb.service 9 | 10 | [Unit] 11 | Description=Postgres Exporter Server - Service Instance: %I 12 | After=network.target 13 | 14 | [Service] 15 | PermissionsStartOnly=true 16 | User=ccp_monitoring 17 | EnvironmentFile=/etc/sysconfig/%i 18 | ExecStartPre=/bin/bash -c "set -o pipefail; cat $QUERY_FILE_LIST | sed -e 's/#PG_STAT_STATEMENTS_THROTTLE_MINUTES#/${PG_STAT_STATEMENTS_THROTTLE_MINUTES}/g' -e 's/#PGBACKREST_INFO_THROTTLE_MINUTES#/${PGBACKREST_INFO_THROTTLE_MINUTES}/g' -e 's/#PG_STAT_STATEMENTS_LIMIT#/${PG_STAT_STATEMENTS_LIMIT}/g' > $(echo $OPT | sed 's/.*--extend.query-path=\([^\ ]*\.yml\).*/\1/')" 19 | ExecStart=/usr/bin/postgres_exporter $OPT 20 | ExecReload=/usr/bin/kill -HUP $MAINPID 21 | Restart=always 22 | 23 | [Install] 24 | WantedBy=multi-user.target 25 | DefaultInstance=postgres_exporter 26 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg11/sysconfig.postgres_exporter_pg11: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | PGBACKREST_INFO_THROTTLE_MINUTES=10 15 | PG_STAT_STATEMENTS_LIMIT=20 16 | PG_STAT_STATEMENTS_THROTTLE_MINUTES=-1 17 | OPT="--web.listen-address=0.0.0.0:9187 --extend.query-path=/etc/postgres_exporter/11/queries.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 18 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # For global / cluster metric 21 | QUERY_FILE_LIST="/etc/postgres_exporter/11/queries_global.yml /etc/postgres_exporter/11/queries_general.yml /etc/postgres_exporter/11/queries_global_dbsize.yml" 22 | 23 | # Recommend running separate exporter service to collect per-db metrics, even if there is only one database in the instance. Allows easier expansion to support multiple databases at a later time. See postgres_exporter_pg##_per_db file. 24 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg11/sysconfig.postgres_exporter_pg11_per_db: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | # Ensure that listening port is different than global postgres_exporter (9188 below). Also ensure that query-path file is different from global one (queries_all_db_stats.yml below). 15 | OPT="--web.listen-address=0.0.0.0:9188 --extend.query-path=/etc/postgres_exporter/11/queries_all_db_stats.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 16 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 17 | # Multiple DSN's can be given to connect to multiple databases with a single exporter. Separate DSNs with a comma and no spaces. Database name in example below is first the value after the "///" before the "?". Additional connection options can be given after "?", separated by "&". 18 | #DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb1?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb2?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # Ex: For per db metric. DO NOT add queries that return the same labels/values on all databases otherwise the exporter will throw errors. The queries that pgmonitor provides for per-db metrics all include a "dbname" label to distinguish them. 21 | QUERY_FILE_LIST="/etc/postgres_exporter/11/queries_per_db.yml" 22 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg12/sysconfig.postgres_exporter_pg12: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | PGBACKREST_INFO_THROTTLE_MINUTES=10 15 | PG_STAT_STATEMENTS_LIMIT=20 16 | PG_STAT_STATEMENTS_THROTTLE_MINUTES=-1 17 | OPT="--web.listen-address=0.0.0.0:9187 --extend.query-path=/etc/postgres_exporter/12/queries.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 18 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # For global / cluster metric 21 | QUERY_FILE_LIST="/etc/postgres_exporter/12/queries_global.yml /etc/postgres_exporter/12/queries_general.yml /etc/postgres_exporter/12/queries_global_dbsize.yml" 22 | 23 | # Recommend running separate exporter service to collect per-db metrics, even if there is only one database in the instance. Allows easier expansion to support multiple databases at a later time. See postgres_exporter_pg##_per_db file. 24 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg12/sysconfig.postgres_exporter_pg12_per_db: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | # Ensure that listening port is different than global postgres_exporter (9188 below). Also ensure that query-path file is different from global one (queries_all_db_stats.yml below). 15 | OPT="--web.listen-address=0.0.0.0:9188 --extend.query-path=/etc/postgres_exporter/12/queries_all_db_stats.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 16 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 17 | # Multiple DSN's can be given to connect to multiple databases with a single exporter. Separate DSNs with a comma and no spaces. Database name in example below is first the value after the "///" before the "?". Additional connection options can be given after "?", separated by "&". 18 | #DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb1?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb2?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # Ex: For per db metric. DO NOT add queries that return the same labels/values on all databases otherwise the exporter will throw errors. The queries that pgmonitor provides for per-db metrics all include a "dbname" label to distinguish them. 21 | QUERY_FILE_LIST="/etc/postgres_exporter/12/queries_per_db.yml" 22 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg13/sysconfig.postgres_exporter_pg13: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | PGBACKREST_INFO_THROTTLE_MINUTES=10 15 | PG_STAT_STATEMENTS_LIMIT=20 16 | PG_STAT_STATEMENTS_THROTTLE_MINUTES=-1 17 | OPT="--web.listen-address=0.0.0.0:9187 --extend.query-path=/etc/postgres_exporter/13/queries.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 18 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # For global / cluster metric 21 | QUERY_FILE_LIST="/etc/postgres_exporter/13/queries_global.yml /etc/postgres_exporter/13/queries_general.yml /etc/postgres_exporter/13/queries_global_dbsize.yml" 22 | 23 | # Recommend running separate exporter service to collect per-db metrics, even if there is only one database in the instance. Allows easier expansion to support multiple databases at a later time. See postgres_exporter_pg##_per_db file. 24 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg13/sysconfig.postgres_exporter_pg13_per_db: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | # Ensure that listening port is different than global postgres_exporter (9188 below). Also ensure that query-path file is different from global one (queries_all_db_stats.yml below). 15 | OPT="--web.listen-address=0.0.0.0:9188 --extend.query-path=/etc/postgres_exporter/13/queries_all_db_stats.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 16 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 17 | # Multiple DSN's can be given to connect to multiple databases with a single exporter. Separate DSNs with a comma and no spaces. Database name in example below is first the value after the "///" before the "?". Additional connection options can be given after "?", separated by "&". 18 | #DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb1?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb2?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # Ex: For per db metric. DO NOT add queries that return the same labels/values on all databases otherwise the exporter will throw errors. The queries that pgmonitor provides for per-db metrics all include a "dbname" label to distinguish them. 21 | QUERY_FILE_LIST="/etc/postgres_exporter/13/queries_per_db.yml" 22 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg14/sysconfig.postgres_exporter_pg14: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | PGBACKREST_INFO_THROTTLE_MINUTES=10 15 | PG_STAT_STATEMENTS_LIMIT=20 16 | PG_STAT_STATEMENTS_THROTTLE_MINUTES=-1 17 | OPT="--web.listen-address=0.0.0.0:9187 --extend.query-path=/etc/postgres_exporter/14/queries.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 18 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # For global / cluster metric 21 | QUERY_FILE_LIST="/etc/postgres_exporter/14/queries_global.yml /etc/postgres_exporter/14/queries_general.yml /etc/postgres_exporter/14/queries_global_dbsize.yml" 22 | 23 | # Recommend running separate exporter service to collect per-db metrics, even if there is only one database in the instance. Allows easier expansion to support multiple databases at a later time. See postgres_exporter_pg##_per_db file. 24 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg14/sysconfig.postgres_exporter_pg14_per_db: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | # Ensure that listening port is different than global postgres_exporter (9188 below). Also ensure that query-path file is different from global one (queries_all_db_stats.yml below). 15 | OPT="--web.listen-address=0.0.0.0:9188 --extend.query-path=/etc/postgres_exporter/14/queries_all_db_stats.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 16 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 17 | # Multiple DSN's can be given to connect to multiple databases with a single exporter. Separate DSNs with a comma and no spaces. Database name in example below is first the value after the "///" before the "?". Additional connection options can be given after "?", separated by "&". 18 | #DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb1?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb2?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # Ex: For per db metric. DO NOT add queries that return the same labels/values on all databases otherwise the exporter will throw errors. The queries that pgmonitor provides for per-db metrics all include a "dbname" label to distinguish them. 21 | QUERY_FILE_LIST="/etc/postgres_exporter/14/queries_per_db.yml" 22 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg15/sysconfig.postgres_exporter_pg15: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | PGBACKREST_INFO_THROTTLE_MINUTES=10 15 | PG_STAT_STATEMENTS_LIMIT=20 16 | PG_STAT_STATEMENTS_THROTTLE_MINUTES=-1 17 | OPT="--web.listen-address=0.0.0.0:9187 --extend.query-path=/etc/postgres_exporter/15/queries.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 18 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # For global / cluster metric 21 | QUERY_FILE_LIST="/etc/postgres_exporter/15/queries_global.yml /etc/postgres_exporter/15/queries_general.yml /etc/postgres_exporter/15/queries_global_dbsize.yml" 22 | 23 | # Recommend running separate exporter service to collect per-db metrics, even if there is only one database in the instance. Allows easier expansion to support multiple databases at a later time. See postgres_exporter_pg##_per_db file. 24 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg15/sysconfig.postgres_exporter_pg15_per_db: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | # Ensure that listening port is different than global postgres_exporter (9188 below). Also ensure that query-path file is different from global one (queries_all_db_stats.yml below). 15 | OPT="--web.listen-address=0.0.0.0:9188 --extend.query-path=/etc/postgres_exporter/15/queries_all_db_stats.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 16 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 17 | # Multiple DSN's can be given to connect to multiple databases with a single exporter. Separate DSNs with a comma and no spaces. Database name in example below is first the value after the "///" before the "?". Additional connection options can be given after "?", separated by "&". 18 | #DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb1?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb2?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # Ex: For per db metric. DO NOT add queries that return the same labels/values on all databases otherwise the exporter will throw errors. The queries that pgmonitor provides for per-db metrics all include a "dbname" label to distinguish them. 21 | QUERY_FILE_LIST="/etc/postgres_exporter/15/queries_per_db.yml" 22 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg16/sysconfig.postgres_exporter_pg16: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | PGBACKREST_INFO_THROTTLE_MINUTES=10 15 | PG_STAT_STATEMENTS_LIMIT=20 16 | PG_STAT_STATEMENTS_THROTTLE_MINUTES=-1 17 | OPT="--web.listen-address=0.0.0.0:9187 --extend.query-path=/etc/postgres_exporter/16/queries.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 18 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # For global / cluster metric 21 | QUERY_FILE_LIST="/etc/postgres_exporter/16/queries_global.yml /etc/postgres_exporter/16/queries_general.yml /etc/postgres_exporter/16/queries_global_dbsize.yml" 22 | 23 | # Recommend running separate exporter service to collect per-db metrics, even if there is only one database in the instance. Allows easier expansion to support multiple databases at a later time. See postgres_exporter_pg##_per_db file. 24 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg16/sysconfig.postgres_exporter_pg16_per_db: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | # Ensure that listening port is different than global postgres_exporter (9188 below). Also ensure that query-path file is different from global one (queries_all_db_stats.yml below). 15 | OPT="--web.listen-address=0.0.0.0:9188 --extend.query-path=/etc/postgres_exporter/16/queries_all_db_stats.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 16 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 17 | # Multiple DSN's can be given to connect to multiple databases with a single exporter. Separate DSNs with a comma and no spaces. Database name in example below is first the value after the "///" before the "?". Additional connection options can be given after "?", separated by "&". 18 | #DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb1?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb2?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # Ex: For per db metric. DO NOT add queries that return the same labels/values on all databases otherwise the exporter will throw errors. The queries that pgmonitor provides for per-db metrics all include a "dbname" label to distinguish them. 21 | QUERY_FILE_LIST="/etc/postgres_exporter/16/queries_per_db.yml" 22 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg17/sysconfig.postgres_exporter_pg17: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | PGBACKREST_INFO_THROTTLE_MINUTES=10 15 | PG_STAT_STATEMENTS_LIMIT=20 16 | PG_STAT_STATEMENTS_THROTTLE_MINUTES=-1 17 | OPT="--web.listen-address=0.0.0.0:9187 --extend.query-path=/etc/postgres_exporter/17/queries.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 18 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # For global / cluster metric 21 | QUERY_FILE_LIST="/etc/postgres_exporter/17/queries_global.yml /etc/postgres_exporter/17/queries_general.yml /etc/postgres_exporter/17/queries_global_dbsize.yml" 22 | 23 | # Recommend running separate exporter service to collect per-db metrics, even if there is only one database in the instance. Allows easier expansion to support multiple databases at a later time. See postgres_exporter_pg##_per_db file. 24 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pg17/sysconfig.postgres_exporter_pg17_per_db: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/postgres_exporter) 8 | 9 | # --web.listen-address: change '0.0.0.0' to the network IP assigned to this system if necessary, otherwise it will listen on any IP. Change port as necessary if running multiple instances. 10 | # --extend.query-path: location of file containing custom queries to run. Location below is one recommended by crunchy setup steps. 11 | # DATA_SOURCE_NAME: psql connection string. set the database that the exporter will connect to. Default is `postgres`. 12 | # QUERY_FILE_LIST: space delimited yml files that will be concatenated to a single queries.yml file. This should only be set once. If set multiple times, last one wins. 13 | 14 | # Ensure that listening port is different than global postgres_exporter (9188 below). Also ensure that query-path file is different from global one (queries_all_db_stats.yml below). 15 | OPT="--web.listen-address=0.0.0.0:9188 --extend.query-path=/etc/postgres_exporter/17/queries_all_db_stats.yml --disable-default-metrics --disable-settings-metrics --no-collector.database --no-collector.database_wraparound --no-collector.locks --no-collector.long_running_transactions --no-collector.postmaster --no-collector.process_idle --no-collector.replication --no-collector.replication_slot --no-collector.stat_activity_autovacuum --no-collector.stat_bgwriter --no-collector.stat_database --no-collector.stat_statements --no-collector.stat_user_tables --no-collector.stat_wal_receiver --no-collector.statio_user_indexes --no-collector.statio_user_tables --no-collector.wal --no-collector.xlog_location" 16 | DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 17 | # Multiple DSN's can be given to connect to multiple databases with a single exporter. Separate DSNs with a comma and no spaces. Database name in example below is first the value after the "///" before the "?". Additional connection options can be given after "?", separated by "&". 18 | #DATA_SOURCE_NAME="postgresql:///postgres?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb1?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable,postgresql:///mydb2?host=/var/run/postgresql/&user=ccp_monitoring&sslmode=disable" 19 | 20 | # Ex: For per db metric. DO NOT add queries that return the same labels/values on all databases otherwise the exporter will throw errors. The queries that pgmonitor provides for per-db metrics all include a "dbname" label to distinguish them. 21 | QUERY_FILE_LIST="/etc/postgres_exporter/17/queries_per_db.yml" 22 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pgbackrest-info.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### 3 | # 4 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 5 | # 6 | ### 7 | 8 | if [ "$1" == "" ]; then 9 | echo "Usage: $(basename $0) " 10 | exit 1 11 | fi 12 | 13 | SYSTEM_ID=$1 14 | 15 | [ -f /etc/pgmonitor.conf ] && . /etc/pgmonitor.conf 16 | 17 | if [ ${BACKREST_AUTOCONFIG_STANZAS:-0} -gt 0 ]; then 18 | BACKREST_STANZAS=$(grep '^\[' /etc/pgbackrest.conf /etc/pgbackrest/ -srh |sort -u |grep -v ':\|global' |sed 's/\[\|\]//g' | tr '\n' ' ' ) 19 | BACKREST_CONFIGS="" 20 | fi 21 | 22 | conf="default" 23 | 24 | if [ -z "$BACKREST_CONFIGS" ] && [ -z "$BACKREST_STANZAS" ]; then 25 | echo $(echo -n "$conf|" | tr '/' '_'; pgbackrest --output=json info | tr -d '\n') 26 | elif [ ! -z "$BACKREST_CONFIGS" ] && [ -z "$BACKREST_STANZAS" ]; then 27 | read -r -a config_array <<< "$BACKREST_CONFIGS" 28 | for conf in "${config_array[@]}" 29 | do 30 | echo $(echo -n "$conf|" | tr '/' '_'; pgbackrest --config=$conf --output=json --log-level-console=info --log-level-stderr=warn info | tr -d '\n') | grep $SYSTEM_ID 31 | if [ $? == 0 ]; then 32 | break 33 | fi 34 | done 35 | elif [ -z "$BACKREST_CONFIGS" ] && [ ! -z "$BACKREST_STANZAS" ]; then 36 | read -r -a stanza_array <<< "$BACKREST_STANZAS" 37 | for stanza in "${stanza_array[@]}" 38 | do 39 | export PGBACKREST_STANZA=$stanza 40 | echo $(echo -n "$conf|" | tr '/' '_'; pgbackrest --output=json --log-level-console=info --log-level-stderr=warn info | tr -d '\n') | grep $SYSTEM_ID 41 | if [ $? == 0 ]; then 42 | break 43 | fi 44 | done 45 | fi 46 | -------------------------------------------------------------------------------- /postgres_exporter/linux/pgmonitor.conf: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # 8 | # If you only have a single pgbackrest repository on one system, the following settings (BACKREST_CONFIGS, BACKREST_STANZAS, BACKREST_AUTO_CONFIG_STANZAS) are generally not needed. These are mostly used in container environments where multiple repositories are running on a single system. If you're unsure if you need to set these, it is recommended to leave them unset. 9 | # 10 | # BACKREST_CONFIGS sets config files to process 11 | # ex: BACKREST_CONFIGS="/etc/pg10backrest.conf /etc/pg11backrest.conf" 12 | # 13 | # BACKREST_STANZAS sets stanza names to process 14 | # ex: BACKREST_STANZAS="mypg10 mypg11" 15 | # 16 | # BACKREST_AUTO_CONFIG_STANZAS will auto detect stanza names 17 | # 0 = Disabled 18 | # 1 = Enabled 19 | # 20 | # Note: When BACKREST_AUTO_CONFIG_STANZAS is set it supersedes BACKREST_CONFIGS and BACKREST_STANZAS 21 | # 22 | 23 | BACKREST_CONFIGS="" 24 | BACKREST_STANZAS="" 25 | BACKREST_AUTOCONFIG_STANZAS=0 26 | -------------------------------------------------------------------------------- /prometheus/common/alert-rules.d/crunchy-alert-rules-blackbox.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | groups: 8 | - name: alert-rules 9 | rules: 10 | 11 | ########## BLACKBOX EXPORTER RULES ########## 12 | - alert: BlackBoxProbe 13 | expr: probe_success == 0 14 | for: 60s 15 | labels: 16 | service: blackbox 17 | severity: critical 18 | severity_num: 300 19 | annotations: 20 | summary: 'Blackbox probe {{ $labels.job }} for instance {{ $labels.instance }} is failing' 21 | -------------------------------------------------------------------------------- /prometheus/common/alert-rules.d/crunchy-alert-rules-etcd.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | groups: 8 | - name: alert-rules 9 | rules: 10 | 11 | ########## ETCD EXPORTER RULES ########## 12 | 13 | #### IMPORTANT NOTE: These alerts only support monitoring a single etcd cluster per prometheus instance #### 14 | 15 | # Ensure there is at least one etcd node reporting metrics 16 | - alert: ETCDAbsent 17 | expr: absent(etcd_server_has_leader) 18 | for: 10s 19 | labels: 20 | service: etcd 21 | severity: critical 22 | severity_num: 300 23 | annotations: 24 | description: 'No etcd metric endpoints found' 25 | 26 | # Ensure there are an odd number of etcd nodes providing metrics 27 | - alert: ETCDOddCount 28 | expr: (count(etcd_server_has_leader) % 2) != 1 29 | for: 10s 30 | labels: 31 | service: etcd 32 | severity: critical 33 | severity_num: 300 34 | annotations: 35 | description: 'An odd number of etcd nodes has not been found.' 36 | 37 | # Ensure there is a leader in the etcd cluster 38 | - alert: ETCDLeader 39 | expr: max(etcd_server_has_leader) < 1 40 | for: 10s 41 | labels: 42 | service: etcd 43 | severity: critical 44 | severity_num: 300 45 | annotations: 46 | description: 'An etcd leader node has not been elected' 47 | 48 | # Ensure an expected amount of etcd nodes are running and providing metrics. Set this threshold to the amount of nodes in your cluster 49 | # 50 | # - alert: ETCDMinimumNodeCount 51 | # expr: count(etcd_server_has_leader) < 3 52 | # for: 10s 53 | # labels: 54 | # service: etcd 55 | # severity: critical 56 | # severity_num: 300 57 | # annotations: 58 | # description: 'The expected minimum count of etcd nodes was not found. Current count {{ $value }}' 59 | 60 | # Absence alerts must be configured per named job, otherwise there's no way to know which job is down 61 | # Below is are some examples using the leader metric for a targets called "etcd#" for a 3 node etcd cluster 62 | 63 | # - alert: ETCDAbsent_etcd1 64 | # expr: absent(etcd_server_has_leader{job="ip11_etcd1"}) 65 | # for: 10s 66 | # labels: 67 | # service: etcd 68 | # severity: critical 69 | # severity_num: 300 70 | # annotations: 71 | # description: 'Leader metric is absent from target {{ $labels.job }}. Check that etcd is running on target host.' 72 | 73 | # - alert: ETCDAbsent_etcd2 74 | # expr: absent(etcd_server_has_leader{job="ip21_etcd2"}) 75 | # for: 10s 76 | # labels: 77 | # service: etcd 78 | # severity: critical 79 | # severity_num: 300 80 | # annotations: 81 | # description: 'Leader metric is absent from target {{ $labels.job }}. Check that etcd is running on target host.' 82 | 83 | # - alert: ETCDAbsent_etcd3 84 | # expr: absent(etcd_server_has_leader{job="ip31_etcd3"}) 85 | # for: 10s 86 | # labels: 87 | # service: etcd 88 | # severity: critical 89 | # severity_num: 300 90 | # annotations: 91 | # description: 'Leader metric is absent from target {{ $labels.job }}. Check that etcd is running on target host.' 92 | -------------------------------------------------------------------------------- /prometheus/common/alert-rules.d/crunchy-alert-rules-patroni.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | groups: 8 | - name: alert-rules 9 | rules: 10 | 11 | ########## PATRONI RULES ########## 12 | 13 | - alert: PatroniPGIsRunning 14 | expr: patroni_postgres_running != 1 15 | for: 60s 16 | labels: 17 | service: patroni 18 | severity: critical 19 | severity_num: 300 20 | annotations: 21 | summary: 'Patroni is reporting that PostgreSQL is not running on {{ $labels.job }}' 22 | 23 | - alert: PatroniPendingRestart 24 | expr: patroni_pending_restart != 0 25 | for: 1800s 26 | labels: 27 | service: patroni 28 | severity: warning 29 | severity_num: 300 30 | annotations: 31 | summary: 'Patroni is reporting a pending restart on {{ $labels.job }}' 32 | 33 | - alert: PatroniIsPaused 34 | expr: patroni_is_paused != 0 35 | for: 900s 36 | labels: 37 | service: patroni 38 | severity: critical 39 | severity_num: 300 40 | annotations: 41 | summary: 'Patroni is reporting that it is in maintenance mode (paused) on {{ $labels.job }}' 42 | 43 | # Threshold value here should be based on Patroni timeout values to its DCS target 44 | - alert: PatroniDCSLastSeen 45 | expr: (time() - patroni_dcs_last_seen) > 300 46 | for: 60s 47 | labels: 48 | service: patroni 49 | severity: warning 50 | severity_num: 200 51 | annotations: 52 | summary: 'Patroni running on {{ $labels.job }} has reported that it has not communicated with its DCS for at least 5 minutes' 53 | 54 | # Threshold value here should be based on Patroni timeout values to its DCS target 55 | - alert: PatroniDCSLastSeen 56 | expr: (time() - patroni_dcs_last_seen) > 1800 57 | for: 60s 58 | labels: 59 | service: patroni 60 | severity: critical 61 | severity_num: 300 62 | annotations: 63 | summary: 'Patroni running on {{ $labels.job }} has reported that it has not communicated with its DCS for at least 30 minutes' 64 | 65 | # Detects a given amount of timeline switches in a given time period. Default example is 5 switches within an hour. 66 | - alert: PatroniRapidTimelineSwitch 67 | expr: (patroni_postgres_timeline - (patroni_postgres_timeline offset 60m)) > 5 68 | for: 60s 69 | labels: 70 | service: patroni 71 | severity: critical 72 | severity_num: 200 73 | annotations: 74 | summary: 'Patroni detected multiple timeline switches in a short period of time on {{ $labels.job }}. This alert will auto-resolve if timeline switching stops.' 75 | 76 | 77 | # Detects one or more timeline switches in a given time 78 | - alert: PatroniTimelineSwitch 79 | expr: patroni_postgres_timeline != patroni_postgres_timeline offset 5m 80 | for: 60s 81 | labels: 82 | service: patroni 83 | severity: warning 84 | severity_num: 200 85 | annotations: 86 | summary: 'Patroni detected a PostgreSQL timeline switch on {{ $labels.job }}. This alert will auto-resolve in 5 minutes if no further timeline switches occur.' 87 | 88 | # Detect that no leader node exists on either the primary DC nor the standby DC 89 | # NOTE: This alert only triggers as expected if prometheus is only monitoring a single datacenter at a time or if all monitored datacenters are down 90 | - alert: PatroniNoLeader 91 | expr: (max by (cluster) (patroni_master) < 1) and (max by (cluster) (patroni_standby_leader) < 1) 92 | for: 60s 93 | labels: 94 | service: patroni 95 | severity: critical 96 | severity_num: 300 97 | annotations: 98 | summary: 'A leader node (neither primary nor standby) cannot be found for cluster {{ $labels.cluster }}.' 99 | -------------------------------------------------------------------------------- /prometheus/common/auto.d/crunchy_dev.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # Each pair of global and per-db exporters for each PostgreSQL instance should be given a matching "job" name so that Prometheus properly groups them together 8 | # Example below is a primary and its replica in a development envirnonment. Failover can make either one primary at any time. 9 | - targets: [ "10.120.100.13:9187" ] 10 | labels: 11 | job: "devdb1" 12 | exp_type: "pg" 13 | cluster_name: "crunchy_dev" 14 | - targets: [ "10.120.100.13:9188" ] 15 | labels: 16 | job: "devdb1" 17 | exp_type: "pg" 18 | cluster_name: "crunchy_dev" 19 | 20 | - targets: [ "10.120.100.14:9187" ] 21 | labels: 22 | job: "devdb2" 23 | exp_type: "pg" 24 | cluster_name: "crunchy_dev" 25 | - targets: [ "10.120.100.14:9188" ] 26 | labels: 27 | job: "devdb2" 28 | exp_type: "pg" 29 | cluster_name: "crunchy_dev" 30 | -------------------------------------------------------------------------------- /prometheus/common/auto.d/crunchy_haproxy.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # Example below is for a single haproxy target. See the following blog post for configuring HAProxy to provide metrics - https://www.haproxy.com/blog/haproxy-exposes-a-prometheus-metrics-endpoint 8 | - targets: [ "10.123.202.12:7000" ] 9 | labels: 10 | job: "prod_haproxy1" 11 | exp_type: "haproxy" 12 | -------------------------------------------------------------------------------- /prometheus/common/auto.d/crunchy_prod.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # Each pair of global and per-db exporters for each PostgreSQL instance should be given a matching "job" name so that Prometheus properly groups them together 8 | # Example below is a primary and its replica in production. Failover can make either one primary at any time. 9 | - targets: [ "10.123.202.12:9187" ] 10 | labels: 11 | job: "proddb1" 12 | exp_type: "pg" 13 | cluster_name: "crunchy_prod" 14 | - targets: [ "10.123.202.12:9188" ] 15 | labels: 16 | job: "proddb1" 17 | exp_type: "pg" 18 | cluster_name: "crunchy_prod" 19 | 20 | - targets: [ "10.123.202.13:9187" ] 21 | labels: 22 | job: "proddb2" 23 | exp_type: "pg" 24 | cluster_name: "crunchy_prod" 25 | - targets: [ "10.123.202.13:9188" ] 26 | labels: 27 | job: "proddb2" 28 | exp_type: "pg" 29 | cluster_name: "crunchy_prod" 30 | -------------------------------------------------------------------------------- /prometheus/containers/auto.d/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrunchyData/pgmonitor/29e6386c39302172fa94cad59bf28ead1e720fee/prometheus/containers/auto.d/.gitkeep -------------------------------------------------------------------------------- /prometheus/containers/crunchy-prometheus.yml.containers: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | --- 7 | global: 8 | scrape_interval: 15s 9 | scrape_timeout: 15s 10 | evaluation_interval: 5s 11 | 12 | scrape_configs: 13 | - job_name: 'crunchy-postgres-exporter' 14 | kubernetes_sd_configs: 15 | - role: pod 16 | selectors: 17 | - role: pod 18 | label: postgres-operator.crunchydata.com/crunchy-postgres-exporter=true 19 | relabel_configs: 20 | # Keep exporter port and drop all others 21 | - source_labels: [__meta_kubernetes_pod_container_port_number] 22 | action: keep 23 | regex: 9187 24 | # Set label for namespace 25 | - source_labels: [__meta_kubernetes_namespace] 26 | target_label: kubernetes_namespace 27 | # Set label for pod name 28 | - source_labels: [__meta_kubernetes_pod_name] 29 | target_label: pod 30 | # Convert namespace and cluster name to pg_cluster=namespace:cluster 31 | - source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_cluster] 32 | target_label: pg_cluster 33 | separator: ":" 34 | replacement: '$1$2' 35 | # Convert kubernetes pod ip to ip 36 | - source_labels: [__meta_kubernetes_pod_ip] 37 | target_label: ip 38 | # Convert postgres-operator.crunchydata.com/instance to deployment 39 | - source_labels: [__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_instance] 40 | target_label: deployment 41 | # Convert postgres-operator.crunchydata.com/role to role 42 | - source_labels: [__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_role] 43 | target_label: role 44 | 45 | - job_name: 'crunchy-postgres-exporter-v4' 46 | kubernetes_sd_configs: 47 | - role: pod 48 | selectors: 49 | - role: pod 50 | label: crunchy-postgres-exporter=true 51 | 52 | relabel_configs: 53 | # Keep exporter port and drop all others 54 | - source_labels: [__meta_kubernetes_pod_container_port_number] 55 | action: keep 56 | regex: 9187 57 | # Set label for namespace 58 | - source_labels: [__meta_kubernetes_namespace] 59 | target_label: kubernetes_namespace 60 | # Set label for pod name 61 | - source_labels: [__meta_kubernetes_pod_name] 62 | target_label: pod 63 | # Convert namespace and cluster name to pg_cluster=namespace:cluster 64 | - source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_pod_label_pg_cluster] 65 | target_label: pg_cluster 66 | separator: ":" 67 | replacement: '$1$2' 68 | # Convert kubernetes pod ip to ip 69 | - source_labels: [__meta_kubernetes_pod_ip] 70 | target_label: ip 71 | # Set deployment_name as deployment label 72 | - source_labels: [__meta_kubernetes_pod_label_deployment_name] 73 | target_label: deployment 74 | # Set label for role 75 | - source_labels: [__meta_kubernetes_pod_label_role] 76 | target_label: role 77 | rule_files: 78 | - /etc/prometheus/alert-rules.d/*.yml 79 | alerting: 80 | alertmanagers: 81 | - kubernetes_sd_configs: 82 | - role: pod 83 | selectors: 84 | - role: pod 85 | label: app.kubernetes.io/component=crunchy-alertmanager 86 | -------------------------------------------------------------------------------- /prometheus/linux/alert-rules.d/crunchy-alert-rules-node.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | groups: 8 | - name: alert-rules 9 | rules: 10 | 11 | ########## EXPORTER RULES ########## 12 | - alert: NodeExporterScrapeError 13 | expr: node_textfile_scrape_error > 0 14 | for: 60s 15 | labels: 16 | service: system 17 | severity: critical 18 | severity_num: 300 19 | annotations: 20 | summary: 'Node Exporter running on {{ $labels.job }} (instance: {{ $labels.instance }}) is encountering scrape errors processing custom metrics. Error count: ( {{ $value }} )' 21 | 22 | 23 | ########## SYSTEM RULES ########## 24 | - alert: ExporterDown 25 | expr: avg_over_time(up[5m]) < 0.5 26 | for: 10s 27 | labels: 28 | service: system 29 | severity: critical 30 | severity_num: 300 31 | annotations: 32 | description: 'Metrics exporter service for {{ $labels.job }} running on {{ $labels.instance }} has been down at least 50% of the time for the last 5 minutes. Service may be flapping or down.' 33 | summary: 'Prometheus Exporter Service Down' 34 | 35 | - alert: DiskUsagePerc 36 | expr: (100 - 100 * sum(node_filesystem_avail_bytes{device!~"tmpfs|by-uuid",fstype=~"xfs|ext[234]"} / node_filesystem_size_bytes{device!~"tmpfs|by-uuid",fstype=~"xfs|ext[234]"}) BY (job,device)) > 70 37 | for: 2m 38 | labels: 39 | service: system 40 | severity: warning 41 | severity_num: 200 42 | annotations: 43 | description: 'Disk usage on target {{ $labels.job }} at {{ $value }}%' 44 | 45 | - alert: DiskUsagePerc 46 | expr: (100 - 100 * sum(node_filesystem_avail_bytes{device!~"tmpfs|by-uuid",fstype=~"xfs|ext[234]"} / node_filesystem_size_bytes{device!~"tmpfs|by-uuid",fstype=~"xfs|ext[234]"}) BY (job,device)) > 85 47 | for: 2m 48 | labels: 49 | service: system 50 | severity: critical 51 | severity_num: 300 52 | annotations: 53 | description: 'Disk usage on target {{ $labels.job }} at {{ $value }}%' 54 | 55 | - alert: SystemLoad5m 56 | expr: node_load5 > (count(count(node_cpu_seconds_total) without (mode)) without (cpu)) * 2 57 | for: 10m 58 | labels: 59 | service: system 60 | severity: warning 61 | severity_num: 200 62 | annotations: 63 | description: 'System load for target {{ $labels.job }} is high ({{ $value }}) based on cpu count' 64 | 65 | - alert: SystemLoad5m 66 | expr: node_load5 > (count(count(node_cpu_seconds_total) without (mode)) without (cpu)) * 4 67 | for: 10m 68 | labels: 69 | service: system 70 | severity: critical 71 | severity_num: 300 72 | annotations: 73 | description: 'System load for target {{ $labels.job }} is high ({{ $value }}) based on cpu count' 74 | 75 | - alert: MemoryAvailable 76 | expr: (100 * (node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes) < 25 77 | for: 1m 78 | labels: 79 | service: system 80 | severity: warning 81 | severity_num: 200 82 | annotations: 83 | description: 'Memory available for target {{ $labels.job }} is at {{ $value }}%' 84 | 85 | - alert: MemoryAvailable 86 | expr: (100 * (node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes) < 10 87 | for: 1m 88 | labels: 89 | service: system 90 | severity: critical 91 | severity_num: 300 92 | annotations: 93 | description: 'Memory available for target {{ $labels.job }} is at {{ $value }}%' 94 | 95 | - alert: OOMKiller 96 | expr: changes(node_vmstat_oom_kill[5m]) != 0 97 | for: 1m 98 | labels: 99 | service: system 100 | severity: warning 101 | severity_num: 200 102 | annotations: 103 | description: 'Out of Memory Killer has triggered on {{ $labels.job }}' 104 | 105 | - alert: SwapUsage 106 | expr: (100 - (100 * (node_memory_SwapFree_bytes / node_memory_SwapTotal_bytes))) > 60 107 | for: 1m 108 | labels: 109 | service: system 110 | severity: warning 111 | severity_num: 200 112 | annotations: 113 | description: 'Swap usage for target {{ $labels.job }} is at {{ $value }}%' 114 | 115 | - alert: SwapUsage 116 | expr: (100 - (100 * (node_memory_SwapFree_bytes / node_memory_SwapTotal_bytes))) > 80 117 | for: 1m 118 | labels: 119 | service: system 120 | severity: critical 121 | severity_num: 300 122 | annotations: 123 | description: 'Swap usage for target {{ $labels.job }} is at {{ $value }}%' 124 | 125 | # - alert: DiskFillPredict 126 | # expr: predict_linear(node_filesystem_free_bytes{device!~"tmpfs|by-uuid",fstype=~"xfs|ext[234]"}[1h], 4 * 3600) < 0 127 | # for: 5m 128 | # labels: 129 | # service: system 130 | # severity: warning 131 | # severity_num: 200 132 | # annotations: 133 | # description: 'Disk {{ $labels.device }} on target {{ $labels.job }} is predicted to fill in 4 hrs based on current usage' 134 | -------------------------------------------------------------------------------- /prometheus/linux/auto.d/ProductionOS.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | - targets: [ "DB_SERVER_IP:NODE_EXPORTER_PORT" ] 8 | labels: 9 | job: "Prod" 10 | exp_type: "node" 11 | -------------------------------------------------------------------------------- /prometheus/linux/auto.d/ReplicaOS.yml.example: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | - targets: [ "DB_SERVER_IP:NODE_EXPORTER_PORT" ] 8 | labels: 9 | job: "Replica" 10 | exp_type: "node" 11 | -------------------------------------------------------------------------------- /prometheus/linux/crunchy-prometheus-service-rhel.conf: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must have a .conf extension to override the default service and activate the crunchy specific configuration 8 | # Note this file must live in /etc/systemd/system/prometheus.service.d/ to work 9 | # 10 | # Override package service config with our own as needed. ExecStart must be reset first before setting our value. 11 | 12 | [Service] 13 | PermissionsStartOnly=true 14 | User=ccp_monitoring 15 | EnvironmentFile=/etc/sysconfig/prometheus 16 | ExecStart= 17 | ExecStart=/usr/bin/prometheus $OPT 18 | ExecReload=/usr/bin/kill -HUP $MAINPID 19 | Restart=always 20 | -------------------------------------------------------------------------------- /prometheus/linux/crunchy-prometheus.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | global: 8 | scrape_interval: 15s # By default, scrape targets every 15 seconds. 9 | 10 | # A scrape configuration containing exactly one endpoint to scrape: 11 | # Here it's Prometheus itself. 12 | #scrape_configs: 13 | # - job_name: 'prometheus' 14 | # scrape_interval: 30s 15 | # static_configs: 16 | # - targets: ['localhost:9090'] 17 | 18 | scrape_configs: 19 | - job_name: 'default-auto-discovery' 20 | scrape_interval: 30s 21 | file_sd_configs: 22 | - files: 23 | - /etc/prometheus/auto.d/*.yml 24 | 25 | ### The following sections are only relevant if postgres_exporter is in use and MUST be enable if so. Remove the single # sections 26 | # 27 | #metric_relabel_configs: 28 | ## Do not store the metrics that come built into postgres_exporter 29 | #- source_labels: [ __name__ ] 30 | # regex: '(pg_locks_count.*|pg_settings.*|pg_stat_activity.*|pg_stat_bgwriter.*|pg_stat_database.*)' 31 | # action: drop 32 | ## Version 0.5+ of postgres_exporter automatically adds a "server" label to all custom query metrics. This breaks upgrades from older versions 33 | ## of pgmonitor and also breaks our PG Overview dashboard and several other single metric panels. 34 | ## pgmonitor only runs two exporters max by default and our per-db exporter distinguishes each metric by a dbname label, 35 | ## so we do not need the "server" label. This relabel will only target metrics that start with "ccp_", so shouldn't break users' custom metrics. 36 | #- source_labels: [__name__, server] 37 | # regex: "ccp_.*;.+" 38 | # action: replace 39 | # target_label: server 40 | # replacement: "" 41 | ### END postgres_exporter section 42 | 43 | ## Monitoring for tcp services that don't have an associated exporter can be accomplished using the tcp probe 44 | ## of the blackbox_exporter provided by the Prometheus developers. 45 | ## Note this only provides a simple up/down that the service is listening on the given IP/port. 46 | ## Below is an example to monitor the services indicated by the comment. 47 | ## The "targets" list is all that should need to be edited to customize to your setup assuming blackbox_exporter runs 48 | ## on same system as Prometheus. 49 | # - job_name: 'blackbox_tcp_services' 50 | # metrics_path: /probe 51 | # params: 52 | # module: [tcp_connect] 53 | # relabel_configs: 54 | # - source_labels: [__address__] 55 | # target_label: __param_target 56 | # - source_labels: [__param_target] 57 | # target_label: instance 58 | # - target_label: __address__ 59 | # replacement: 127.0.0.1:9115 60 | # static_configs: 61 | # - targets: 62 | # - 127.0.0.1:3000 # grafana 63 | # - 192.168.122.16:8009 # patroni 64 | # - 192.168.122.26:8009 # patroni 65 | # - 192.168.122.36:8009 # patroni 66 | # - 192.168.122.12:7000 # haproxy 67 | ## Some services require tls probes. Note that not all TLS services need this (Ex. pgbouncer) 68 | # - job_name: 'blackbox_tcp_tls_services' 69 | # metrics_path: /probe 70 | # params: 71 | # module: [tcp_connect_tls] 72 | # relabel_configs: 73 | # - source_labels: [__address__] 74 | # target_label: __param_target 75 | # - source_labels: [__param_target] 76 | # target_label: instance 77 | # - target_label: __address__ 78 | # replacement: 127.0.0.1:9115 79 | # static_configs: 80 | # - targets: 81 | # - 127.0.0.1:3000 # grafana 82 | # - 192.168.122.11:8009 # etcd 83 | # - 192.168.122.21:8009 # etcd 84 | # - 192.168.122.31:8009 # etcd 85 | 86 | 87 | #### Uncomment below if using alertmanager #### 88 | # 89 | rule_files: 90 | - /etc/prometheus/alert-rules.d/*.yml 91 | # 92 | #alerting: 93 | # alertmanagers: 94 | # - scheme: http 95 | # static_configs: 96 | # - targets: 97 | # - "127.0.0.1:9093" 98 | -------------------------------------------------------------------------------- /prometheus/linux/sysconfig.prometheus: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | # This file must be in a pathname that matches the EnvironmentFile entry in the service file (Default: /etc/sysconfig/prometheus) 8 | # 9 | # --config-file: the path to the prometheus server configuration file 10 | # --storage.tsdb.path: location that prometheus will store its time series database files 11 | # --storage.tsdb.retention: how long prometheus will keep data before expiring it. This is how much data will be available to trend in grafana. 12 | # --log.level: how verbose to make system logging. Setting to "debug" can help with diagnosing issues, but should not be left that way. 13 | # --web.enable-admin-api: set this to make the admin api available which allows database snapshot backups. Left off by default for security. 14 | 15 | OPT="--config.file=/etc/prometheus/crunchy-prometheus.yml --storage.tsdb.path=/var/lib/ccp_monitoring/prometheus --storage.tsdb.retention.time=7d --log.level=info" 16 | -------------------------------------------------------------------------------- /release/scripts/check_capitalization: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $(git rev-parse --show-toplevel) 4 | 5 | for product in PgBouncer pgBackRest pgMonitor PostgreSQL HAProxy; do 6 | git grep -i $product | grep -P "(?=(?i)$product)(?!${product,,}|$product)" 7 | done 8 | -------------------------------------------------------------------------------- /sql_exporter/common/crunchy_backrest_collector.yml: -------------------------------------------------------------------------------- 1 | collector_name: crunchy_pgbackrest 2 | 3 | metrics: 4 | - metric_name: ccp_backrest_last_info_backrest_repo_version 5 | type: gauge 6 | help: "pgBackRest version number when this backup was performed" 7 | values: [backrest_repo_version] 8 | key_labels: 9 | - config_file 10 | - stanza 11 | - repo 12 | - backup_type 13 | query_ref: ccp_backrest_last_info 14 | - metric_name: ccp_backrest_last_info_repo_backup_size_bytes 15 | type: gauge 16 | help: "Actual size of only this individual backup in the pgbackrest repository" 17 | values: [repo_backup_size_bytes] 18 | key_labels: 19 | - config_file 20 | - stanza 21 | - repo 22 | - backup_type 23 | query_ref: ccp_backrest_last_info 24 | - metric_name: ccp_backrest_last_info_backup_runtime_seconds 25 | type: gauge 26 | help: "Total runtime in seconds of this backup" 27 | values: [backup_runtime_seconds] 28 | key_labels: 29 | - config_file 30 | - stanza 31 | - repo 32 | - backup_type 33 | query_ref: ccp_backrest_last_info 34 | - metric_name: ccp_backrest_last_info_backup_error 35 | type: gauge 36 | help: "An error has been encountered in the backup. Check logs for more information." 37 | values: [backup_error] 38 | key_labels: 39 | - config_file 40 | - stanza 41 | - repo 42 | - backup_type 43 | query_ref: ccp_backrest_last_info 44 | 45 | 46 | - metric_name: ccp_backrest_oldest_full_backup_time_seconds 47 | type: gauge 48 | help: "Seconds since the oldest completed full backup" 49 | values: [time_seconds] 50 | key_labels: 51 | - config_file 52 | - stanza 53 | - repo 54 | query_ref: ccp_backrest_oldest_full_backup 55 | 56 | 57 | - metric_name: ccp_backrest_last_full_backup_time_since_completion_seconds 58 | type: gauge 59 | help: "Seconds since the last completed full backup" 60 | values: [time_since_completion_seconds] 61 | key_labels: 62 | - config_file 63 | - stanza 64 | - repo 65 | query_ref: ccp_backrest_last_full_backup 66 | 67 | 68 | - metric_name: ccp_backrest_last_diff_backup_time_since_completion_seconds 69 | type: gauge 70 | help: "Seconds since the last completed full or differential backup. Differential is always based off last full." 71 | values: [time_since_completion_seconds] 72 | key_labels: 73 | - config_file 74 | - stanza 75 | - repo 76 | query_ref: ccp_backrest_last_diff_backup 77 | 78 | 79 | - metric_name: ccp_backrest_last_incr_backup_time_since_completion_seconds 80 | type: gauge 81 | help: "Seconds since the last completed full, differential or incremental backup. Incremental is always based off last full or differential." 82 | values: [time_since_completion_seconds] 83 | key_labels: 84 | - config_file 85 | - stanza 86 | - repo 87 | query_ref: ccp_backrest_last_incr_backup 88 | 89 | 90 | ########## QUERIES ########## 91 | queries: 92 | - query_name: ccp_backrest_last_info 93 | query: | 94 | SELECT backrest_repo_version 95 | , config_file 96 | , stanza 97 | , repo 98 | , backup_type 99 | , repo_backup_size_bytes 100 | , backup_runtime_seconds 101 | , backup_error 102 | FROM pgmonitor_ext.ccp_backrest_last_info 103 | 104 | 105 | - query_name: ccp_backrest_oldest_full_backup 106 | query: | 107 | SELECT config_file 108 | , stanza 109 | , repo 110 | , time_seconds 111 | FROM pgmonitor_ext.ccp_backrest_oldest_full_backup 112 | 113 | 114 | - query_name: ccp_backrest_last_full_backup 115 | query: | 116 | SELECT config_file 117 | , stanza 118 | , repo 119 | , time_since_completion_seconds 120 | FROM pgmonitor_ext.ccp_backrest_last_full_backup 121 | 122 | 123 | - query_name: ccp_backrest_last_diff_backup 124 | query: | 125 | SELECT config_file 126 | , stanza 127 | , repo 128 | , time_since_completion_seconds 129 | FROM pgmonitor_ext.ccp_backrest_last_diff_backup 130 | 131 | 132 | - query_name: ccp_backrest_last_incr_backup 133 | query: | 134 | SELECT config_file 135 | , stanza 136 | , repo 137 | , time_since_completion_seconds 138 | FROM pgmonitor_ext.ccp_backrest_last_incr_backup 139 | -------------------------------------------------------------------------------- /sql_exporter/common/crunchy_bloat_check_collector.yml: -------------------------------------------------------------------------------- 1 | collector_name: crunchy_bloat_check 2 | 3 | metrics: 4 | - metric_name: ccp_bloat_check_size_bytes 5 | type: gauge 6 | help: "Size of object in bytes" 7 | values: [size_bytes] 8 | key_labels: 9 | - dbname 10 | - schemaname 11 | - objectname 12 | query_ref: ccp_bloat_check 13 | 14 | - metric_name: ccp_bloat_check_total_wasted_space_bytes 15 | type: gauge 16 | help: "Total wasted space in bytes of given object" 17 | values: [total_wasted_space_bytes] 18 | key_labels: 19 | - dbname 20 | - schemaname 21 | - objectname 22 | query_ref: ccp_bloat_check 23 | 24 | 25 | ########## QUERIES ########## 26 | queries: 27 | - query_name: ccp_bloat_check 28 | query: | 29 | SELECT current_database() AS dbname 30 | , schemaname 31 | , objectname 32 | , size_bytes 33 | , (dead_tuple_size_bytes + (free_space_bytes - (relpages - (fillfactor/100) * relpages ) * current_setting('block_size')::bigint ))::bigint AS total_wasted_space_bytes 34 | FROM bloat_stats 35 | -------------------------------------------------------------------------------- /sql_exporter/common/crunchy_pg_stat_statements_collector.yml: -------------------------------------------------------------------------------- 1 | 2 | collector_name: crunchy_pg_stat_statements 3 | 4 | metrics: 5 | - metric_name: ccp_pg_stat_statements_total_calls_count 6 | type: gauge 7 | help: "Total number of queries run per user/database" 8 | values: [calls_count] 9 | key_labels: 10 | - role 11 | - dbname 12 | query_ref: ccp_pg_stat_statements_total 13 | - metric_name: ccp_pg_stat_statements_total_exec_time_ms 14 | type: gauge 15 | help: "Total runtime of all queries per user/database" 16 | values: [exec_time_ms] 17 | key_labels: 18 | - role 19 | - dbname 20 | query_ref: ccp_pg_stat_statements_total 21 | - metric_name: ccp_pg_stat_statements_total_mean_exec_time_ms 22 | type: gauge 23 | help: "Mean runtime of all queries per user/database" 24 | values: [mean_exec_time_ms] 25 | key_labels: 26 | - role 27 | - dbname 28 | query_ref: ccp_pg_stat_statements_total 29 | - metric_name: ccp_pg_stat_statements_total_row_count 30 | type: gauge 31 | help: "Total rows returned from all queries per user/database" 32 | values: [row_count] 33 | key_labels: 34 | - role 35 | - dbname 36 | query_ref: ccp_pg_stat_statements_total 37 | 38 | 39 | - metric_name: ccp_pg_stat_statements_top_mean_exec_time_ms 40 | type: gauge 41 | help: "Average query runtime in milliseconds" 42 | values: [exec_time_ms] 43 | key_labels: 44 | - role 45 | - dbname 46 | - queryid 47 | - query 48 | query_ref: ccp_pg_stat_statements_top_mean 49 | 50 | 51 | - metric_name: ccp_pg_stat_statements_top_total_exec_time_ms 52 | type: gauge 53 | help: "Total time spent in the statement in milliseconds" 54 | values: [exec_time_ms] 55 | key_labels: 56 | - role 57 | - dbname 58 | - queryid 59 | - query 60 | query_ref: ccp_pg_stat_statements_top_total 61 | 62 | 63 | - metric_name: ccp_pg_stat_statements_top_max_exec_time_ms 64 | type: gauge 65 | help: "Maximum time spent in the statement in milliseconds" 66 | values: [exec_time_ms] 67 | key_labels: 68 | - role 69 | - dbname 70 | - queryid 71 | - query 72 | query_ref: ccp_pg_stat_statements_top_max 73 | 74 | 75 | - metric_name: ccp_pg_stat_statements_top_wal_records 76 | type: gauge 77 | help: "Total number of WAL records generated by the statement" 78 | values: [records] 79 | key_labels: 80 | - role 81 | - dbname 82 | - queryid 83 | - query 84 | query_ref: ccp_pg_stat_statements_top_wal 85 | 86 | - metric_name: ccp_pg_stat_statements_top_wal_fpi 87 | type: gauge 88 | help: "Total number of WAL full page images generated by the statement" 89 | values: [fpi] 90 | key_labels: 91 | - role 92 | - dbname 93 | - queryid 94 | - query 95 | query_ref: ccp_pg_stat_statements_top_wal 96 | 97 | - metric_name: ccp_pg_stat_statements_top_wal_bytes 98 | type: gauge 99 | help: "Total amount of WAL generated by the statement in bytes" 100 | values: [bytes] 101 | key_labels: 102 | - role 103 | - dbname 104 | - queryid 105 | - query 106 | query_ref: ccp_pg_stat_statements_top_wal 107 | 108 | 109 | ########## QUERIES ########## 110 | queries: 111 | - query_name: ccp_pg_stat_statements_top_total 112 | query: | 113 | SELECT role 114 | , dbname 115 | , queryid 116 | , query 117 | , total_exec_time exec_time_ms 118 | FROM pgmonitor_ext.pg_stat_statements_func() 119 | ORDER BY 5 DESC 120 | LIMIT 20 121 | 122 | - query_name: ccp_pg_stat_statements_top_mean 123 | query: | 124 | SELECT role 125 | , dbname 126 | , queryid 127 | , query 128 | , max(mean_exec_time) exec_time_ms 129 | FROM pgmonitor_ext.pg_stat_statements_func() 130 | GROUP BY 1,2,3,4 131 | ORDER BY 5 DESC 132 | LIMIT 20 133 | 134 | - query_name: ccp_pg_stat_statements_total 135 | query: | 136 | SELECT role 137 | , dbname 138 | , sum(calls) AS calls_count 139 | , sum(total_exec_time) AS exec_time_ms 140 | , avg(mean_exec_time) AS mean_exec_time_ms 141 | , sum(rows) AS row_count 142 | FROM pgmonitor_ext.pg_stat_statements_func() 143 | GROUP BY 1,2 144 | 145 | - query_name: ccp_pg_stat_statements_top_max 146 | query: | 147 | SELECT role 148 | , dbname 149 | , queryid 150 | , query 151 | , max_exec_time AS exec_time_ms 152 | FROM pgmonitor_ext.pg_stat_statements_func() 153 | ORDER BY 5 DESC 154 | LIMIT 20 155 | 156 | - query_name: ccp_pg_stat_statements_top_wal 157 | query: | 158 | SELECT role 159 | , dbname 160 | , queryid 161 | , query 162 | , wal_records AS records 163 | , wal_fpi AS fpi 164 | , wal_bytes AS bytes 165 | FROM pgmonitor_ext.pg_stat_statements_func() 166 | ORDER BY wal_bytes DESC 167 | LIMIT 20 168 | -------------------------------------------------------------------------------- /sql_exporter/common/crunchy_pg_stat_statements_reset_collector.yml: -------------------------------------------------------------------------------- 1 | 2 | collector_name: crunchy_pg_stat_statements_reset 3 | 4 | metrics: 5 | - metric_name: crunchy_pg_stat_statements_reset_time 6 | type: gauge 7 | help: "Epoch time since pg_stat_statements was last reset" 8 | values: [time] 9 | query: | 10 | SELECT time FROM pgmonitor_ext.ccp_pg_stat_statements_reset; 11 | -------------------------------------------------------------------------------- /sql_exporter/common/crunchy_pgbouncer_121_collector.yml: -------------------------------------------------------------------------------- 1 | collector_name: crunchy_pgbouncer_121 2 | # Collector for PgBouncer minimum version of 1.21 3 | 4 | metrics: 5 | - metric_name: ccp_pgbouncer_clients_wait_seconds 6 | type: gauge 7 | help: "Current waiting time in seconds" 8 | values: [wait] 9 | key_labels: 10 | - database 11 | - user 12 | - state 13 | - application_name 14 | - link 15 | query_ref: ccp_pgbouncer_clients 16 | 17 | 18 | - metric_name: ccp_pgbouncer_databases_pool_size 19 | type: gauge 20 | help: "Maximum number of server connections" 21 | values: [pool_size] 22 | key_labels: 23 | - name 24 | - host 25 | - port 26 | - database 27 | - force_user 28 | - pool_mode 29 | query_ref: ccp_pgbouncer_databases 30 | - metric_name: ccp_pgbouncer_databases_min_pool_size 31 | type: gauge 32 | help: "Minimum number of server connections" 33 | values: [min_pool_size] 34 | key_labels: 35 | - name 36 | - host 37 | - port 38 | - database 39 | - force_user 40 | - pool_mode 41 | query_ref: ccp_pgbouncer_databases 42 | - metric_name: ccp_pgbouncer_databases_reserve_pool 43 | type: gauge 44 | help: "Maximum number of additional connections for this database" 45 | values: [reserve_pool] 46 | key_labels: 47 | - name 48 | - host 49 | - port 50 | - database 51 | - force_user 52 | - pool_mode 53 | query_ref: ccp_pgbouncer_databases 54 | - metric_name: ccp_pgbouncer_databases_max_connections 55 | type: gauge 56 | help: "Maximum number of allowed connections for this database, as set by max_db_connections, either globally or per database" 57 | values: [max_connections] 58 | key_labels: 59 | - name 60 | - host 61 | - port 62 | - database 63 | - force_user 64 | - pool_mode 65 | query_ref: ccp_pgbouncer_databases 66 | - metric_name: ccp_pgbouncer_databases_current_connections 67 | type: gauge 68 | help: "Current number of connections for this database" 69 | values: [current_connections] 70 | key_labels: 71 | - name 72 | - host 73 | - port 74 | - database 75 | - force_user 76 | - pool_mode 77 | query_ref: ccp_pgbouncer_databases 78 | - metric_name: ccp_pgbouncer_databases_paused 79 | type: gauge 80 | help: "1 if this database is currently paused, else 0" 81 | values: [paused] 82 | key_labels: 83 | - name 84 | - host 85 | - port 86 | - database 87 | - force_user 88 | - pool_mode 89 | query_ref: ccp_pgbouncer_databases 90 | - metric_name: ccp_pgbouncer_databases_disabled 91 | type: gauge 92 | help: "1 if this database is currently disabled, else 0" 93 | values: [disabled] 94 | key_labels: 95 | - name 96 | - host 97 | - port 98 | - database 99 | - force_user 100 | - pool_mode 101 | query_ref: ccp_pgbouncer_databases 102 | 103 | 104 | - metric_name: ccp_pgbouncer_lists_item_count 105 | type: gauge 106 | help: "Count of items registered with pgBouncer" 107 | values: [items] 108 | key_labels: 109 | - list 110 | query_ref: ccp_pgbouncer_lists 111 | 112 | 113 | - metric_name: ccp_pgbouncer_pools_client_active 114 | type: gauge 115 | help: "Client connections that are either linked to server connections or are idle with no queries waiting to be processed" 116 | values: [cl_active] 117 | key_labels: 118 | - database 119 | - user 120 | query_ref: ccp_pgbouncer_pools 121 | - metric_name: ccp_pgbouncer_pools_client_waiting 122 | type: gauge 123 | help: "Client connections that have sent queries but have not yet got a server connection" 124 | values: [cl_waiting] 125 | key_labels: 126 | - database 127 | - user 128 | query_ref: ccp_pgbouncer_pools 129 | - metric_name: ccp_pgbouncer_pools_server_active 130 | type: gauge 131 | help: "Server connections that are linked to a client" 132 | values: [sv_active] 133 | key_labels: 134 | - database 135 | - user 136 | query_ref: ccp_pgbouncer_pools 137 | - metric_name: ccp_pgbouncer_pools_server_idle 138 | type: gauge 139 | help: "Server connections that are unused and immediately usable for client queries" 140 | values: [sv_idle] 141 | key_labels: 142 | - database 143 | - user 144 | query_ref: ccp_pgbouncer_pools 145 | - metric_name: ccp_pgbouncer_pools_server_used 146 | type: gauge 147 | help: "Server connections that have been idle for more than server_check_delay, so they need server_check_query to run on them before they can be used again" 148 | values: [sv_used] 149 | key_labels: 150 | - database 151 | - user 152 | query_ref: ccp_pgbouncer_pools 153 | 154 | 155 | - metric_name: ccp_pgbouncer_servers_close_needed 156 | type: gauge 157 | help: "1 if the connection will be closed as soon as possible, because a configuration file reload or DNS update changed the connection information or RECONNECT was issued" 158 | values: [close_needed] 159 | key_labels: 160 | - database 161 | - user 162 | - state 163 | - application_name 164 | - link 165 | query_ref: ccp_pgbouncer_servers 166 | 167 | 168 | ########## QUERIES ########## 169 | queries: 170 | - query_name: ccp_pgbouncer_clients 171 | no_prepared_statement: true 172 | query: | 173 | SHOW CLIENTS; 174 | 175 | - query_name: ccp_pgbouncer_databases 176 | no_prepared_statement: true 177 | query: | 178 | SHOW DATABASES; 179 | 180 | - query_name: ccp_pgbouncer_lists 181 | no_prepared_statement: true 182 | query: | 183 | SHOW LISTS; 184 | 185 | - query_name: ccp_pgbouncer_pools 186 | no_prepared_statement: true 187 | query: | 188 | SHOW POOLS; 189 | 190 | - query_name: ccp_pgbouncer_servers 191 | no_prepared_statement: true 192 | query: | 193 | SHOW SERVERS; 194 | 195 | # Add later if needed 196 | # - query_name: ccp_pgbouncer_stats 197 | # no_prepared_statement: true 198 | # query: | 199 | # SHOW STATS; 200 | -------------------------------------------------------------------------------- /sql_exporter/common/crunchy_pgbouncer_124_collector.yml: -------------------------------------------------------------------------------- 1 | collector_name: crunchy_pgbouncer_124 2 | # Collector for PgBouncer minimum version of 1.24 3 | 4 | metrics: 5 | - metric_name: ccp_pgbouncer_clients_wait_seconds 6 | type: gauge 7 | help: "Current waiting time in seconds" 8 | values: [wait] 9 | key_labels: 10 | - database 11 | - user 12 | - state 13 | - application_name 14 | - link 15 | query_ref: ccp_pgbouncer_clients 16 | 17 | 18 | - metric_name: ccp_pgbouncer_databases_pool_size 19 | type: gauge 20 | help: "Maximum number of server connections" 21 | values: [pool_size] 22 | key_labels: 23 | - name 24 | - host 25 | - port 26 | - database 27 | - force_user 28 | - pool_mode 29 | query_ref: ccp_pgbouncer_databases 30 | - metric_name: ccp_pgbouncer_databases_min_pool_size 31 | type: gauge 32 | help: "Minimum number of server connections" 33 | values: [min_pool_size] 34 | key_labels: 35 | - name 36 | - host 37 | - port 38 | - database 39 | - force_user 40 | - pool_mode 41 | query_ref: ccp_pgbouncer_databases 42 | - metric_name: ccp_pgbouncer_databases_reserve_pool_size 43 | type: gauge 44 | help: "Maximum number of additional connections for this database" 45 | values: [reserve_pool_size] 46 | key_labels: 47 | - name 48 | - host 49 | - port 50 | - database 51 | - force_user 52 | - pool_mode 53 | query_ref: ccp_pgbouncer_databases 54 | - metric_name: ccp_pgbouncer_databases_max_connections 55 | type: gauge 56 | help: "Maximum number of allowed connections for this database, as set by max_db_connections, either globally or per database" 57 | values: [max_connections] 58 | key_labels: 59 | - name 60 | - host 61 | - port 62 | - database 63 | - force_user 64 | - pool_mode 65 | query_ref: ccp_pgbouncer_databases 66 | - metric_name: ccp_pgbouncer_databases_current_connections 67 | type: gauge 68 | help: "Current number of connections for this database" 69 | values: [current_connections] 70 | key_labels: 71 | - name 72 | - host 73 | - port 74 | - database 75 | - force_user 76 | - pool_mode 77 | query_ref: ccp_pgbouncer_databases 78 | - metric_name: ccp_pgbouncer_databases_paused 79 | type: gauge 80 | help: "1 if this database is currently paused, else 0" 81 | values: [paused] 82 | key_labels: 83 | - name 84 | - host 85 | - port 86 | - database 87 | - force_user 88 | - pool_mode 89 | query_ref: ccp_pgbouncer_databases 90 | - metric_name: ccp_pgbouncer_databases_disabled 91 | type: gauge 92 | help: "1 if this database is currently disabled, else 0" 93 | values: [disabled] 94 | key_labels: 95 | - name 96 | - host 97 | - port 98 | - database 99 | - force_user 100 | - pool_mode 101 | query_ref: ccp_pgbouncer_databases 102 | 103 | 104 | - metric_name: ccp_pgbouncer_lists_item_count 105 | type: gauge 106 | help: "Count of items registered with pgBouncer" 107 | values: [items] 108 | key_labels: 109 | - list 110 | query_ref: ccp_pgbouncer_lists 111 | 112 | 113 | - metric_name: ccp_pgbouncer_pools_client_active 114 | type: gauge 115 | help: "Client connections that are either linked to server connections or are idle with no queries waiting to be processed" 116 | values: [cl_active] 117 | key_labels: 118 | - database 119 | - user 120 | query_ref: ccp_pgbouncer_pools 121 | - metric_name: ccp_pgbouncer_pools_client_waiting 122 | type: gauge 123 | help: "Client connections that have sent queries but have not yet got a server connection" 124 | values: [cl_waiting] 125 | key_labels: 126 | - database 127 | - user 128 | query_ref: ccp_pgbouncer_pools 129 | - metric_name: ccp_pgbouncer_pools_server_active 130 | type: gauge 131 | help: "Server connections that are linked to a client" 132 | values: [sv_active] 133 | key_labels: 134 | - database 135 | - user 136 | query_ref: ccp_pgbouncer_pools 137 | - metric_name: ccp_pgbouncer_pools_server_idle 138 | type: gauge 139 | help: "Server connections that are unused and immediately usable for client queries" 140 | values: [sv_idle] 141 | key_labels: 142 | - database 143 | - user 144 | query_ref: ccp_pgbouncer_pools 145 | - metric_name: ccp_pgbouncer_pools_server_used 146 | type: gauge 147 | help: "Server connections that have been idle for more than server_check_delay, so they need server_check_query to run on them before they can be used again" 148 | values: [sv_used] 149 | key_labels: 150 | - database 151 | - user 152 | query_ref: ccp_pgbouncer_pools 153 | 154 | 155 | - metric_name: ccp_pgbouncer_servers_close_needed 156 | type: gauge 157 | help: "1 if the connection will be closed as soon as possible, because a configuration file reload or DNS update changed the connection information or RECONNECT was issued" 158 | values: [close_needed] 159 | key_labels: 160 | - database 161 | - user 162 | - state 163 | - application_name 164 | - link 165 | query_ref: ccp_pgbouncer_servers 166 | 167 | 168 | ########## QUERIES ########## 169 | queries: 170 | - query_name: ccp_pgbouncer_clients 171 | no_prepared_statement: true 172 | query: | 173 | SHOW CLIENTS; 174 | 175 | - query_name: ccp_pgbouncer_databases 176 | no_prepared_statement: true 177 | query: | 178 | SHOW DATABASES; 179 | 180 | - query_name: ccp_pgbouncer_lists 181 | no_prepared_statement: true 182 | query: | 183 | SHOW LISTS; 184 | 185 | - query_name: ccp_pgbouncer_pools 186 | no_prepared_statement: true 187 | query: | 188 | SHOW POOLS; 189 | 190 | - query_name: ccp_pgbouncer_servers 191 | no_prepared_statement: true 192 | query: | 193 | SHOW SERVERS; 194 | 195 | # Add later if needed 196 | # - query_name: ccp_pgbouncer_stats 197 | # no_prepared_statement: true 198 | # query: | 199 | # SHOW STATS; 200 | -------------------------------------------------------------------------------- /sql_exporter/common/crunchy_pgbouncer_fdw_collector.yml: -------------------------------------------------------------------------------- 1 | collector_name: crunchy_pgbouncer_fdw 2 | 3 | metrics: 4 | - metric_name: ccp_pgbouncer_pools_client_active 5 | type: gauge 6 | help: "Client connections that are linked to server connection and can process queries." 7 | values: [client_active] 8 | key_labels: 9 | - pgbouncer_target_host 10 | - conn_pool 11 | query_ref: ccp_pgbouncer_pools 12 | - metric_name: ccp_pgbouncer_pools_client_waiting 13 | type: gauge 14 | help: "Client connections that have sent queries but have not yet gotten a server connection." 15 | values: [client_waiting] 16 | key_labels: 17 | - pgbouncer_target_host 18 | - conn_pool 19 | query_ref: ccp_pgbouncer_pools 20 | - metric_name: ccp_pgbouncer_pools_server_active 21 | type: gauge 22 | help: "Server connections that are linked to a client." 23 | values: [server_active] 24 | key_labels: 25 | - pgbouncer_target_host 26 | - conn_pool 27 | query_ref: ccp_pgbouncer_pools 28 | - metric_name: ccp_pgbouncer_pools_server_idle 29 | type: gauge 30 | help: "Server connections that unused and immediately usable for client queries." 31 | values: [server_idle] 32 | key_labels: 33 | - pgbouncer_target_host 34 | - conn_pool 35 | query_ref: ccp_pgbouncer_pools 36 | - metric_name: ccp_pgbouncer_pools_server_used 37 | type: gauge 38 | help: "Server connections that have been idle more than server_check_delay, so they need server_check_query to run on it before it can be used." 39 | values: [server_used] 40 | key_labels: 41 | - pgbouncer_target_host 42 | - conn_pool 43 | query_ref: ccp_pgbouncer_pools 44 | 45 | 46 | - metric_name: ccp_pgbouncer_databases_db_conn_perc_used 47 | type: gauge 48 | help: "Percentage of available pooler connections for this database that are in use" 49 | values: [db_conn_perc_used] 50 | key_labels: 51 | - pgbouncer_target_host 52 | - pool_db 53 | query_ref: ccp_pgbouncer_databases 54 | - metric_name: ccp_pgbouncer_databases_paused 55 | type: gauge 56 | help: "Pooler connections to this database are currently paused" 57 | values: [paused] 58 | key_labels: 59 | - pgbouncer_target_host 60 | - pool_db 61 | query_ref: ccp_pgbouncer_databases 62 | - metric_name: ccp_pgbouncer_databases_disabled 63 | type: gauge 64 | help: "Pooler connections to this database are currently disabled" 65 | values: [disabled] 66 | key_labels: 67 | - pgbouncer_target_host 68 | - pool_db 69 | query_ref: ccp_pgbouncer_databases 70 | 71 | 72 | - metric_name: ccp_pgbouncer_clients_client_state_count 73 | type: gauge 74 | help: "Count of the client connections with this status" 75 | values: [client_state_count] 76 | key_labels: 77 | - pgbouncer_target_host 78 | - conn_pool 79 | - client_state 80 | query_ref: ccp_pgbouncer_clients 81 | 82 | 83 | - metric_name: ccp_pgbouncer_servers_server_state_count 84 | type: gauge 85 | help: "Count of the server connections with this status" 86 | values: [server_state_count] 87 | key_labels: 88 | - pgbouncer_target_host 89 | - conn_pool 90 | - server_state 91 | query_ref: ccp_pgbouncer_servers 92 | 93 | 94 | - metric_name: ccp_pgbouncer_lists_item_count 95 | type: gauge 96 | help: "Count of items registered with pgBouncer" 97 | values: [item_count] 98 | key_labels: 99 | - pgbouncer_target_host 100 | - item 101 | query_ref: ccp_pgbouncer_lists 102 | 103 | 104 | ########## QUERIES ########## 105 | queries: 106 | - query_name: ccp_pgbouncer_databases 107 | query: | 108 | SELECT pgbouncer_target_host 109 | , name AS pool_db 110 | , CASE WHEN max_connections != 0 111 | THEN ((current_connections::float / max_connections::float) * 100)::int 112 | ELSE ((current_connections::float / pool_size::float) * 100)::int 113 | END AS db_conn_perc_used 114 | , paused 115 | , disabled 116 | FROM pgbouncer_databases 117 | 118 | 119 | - query_name: ccp_pgbouncer_pools 120 | query: | 121 | SELECT pgbouncer_target_host 122 | , database || '.' || p.user as conn_pool 123 | , sum(cl_active) AS client_active 124 | , sum(cl_waiting) AS client_waiting 125 | , sum(sv_active) AS server_active 126 | , sum(sv_idle) AS server_idle 127 | , sum(sv_used) AS server_used 128 | FROM pgbouncer_pools as p 129 | GROUP BY 1,2 130 | 131 | 132 | - query_name: ccp_pgbouncer_clients 133 | query: | 134 | SELECT pgbouncer_target_host 135 | , database || '.' || p.user as conn_pool 136 | , state AS client_state 137 | , count(*) AS client_state_count 138 | FROM pgbouncer_clients as p 139 | GROUP BY 1,2,3 140 | 141 | 142 | - query_name: ccp_pgbouncer_servers 143 | query: | 144 | SELECT pgbouncer_target_host 145 | , database || '.' || p.user as conn_pool 146 | , state as server_state 147 | , count(*) AS server_state_count 148 | FROM pgbouncer_servers as p 149 | GROUP BY 1,2,3 150 | 151 | 152 | - query_name: ccp_pgbouncer_lists 153 | query: | 154 | SELECT pgbouncer_target_host 155 | , list AS item 156 | , items AS item_count 157 | FROM pgbouncer_lists 158 | WHERE list IN ('databases', 'pools', 'free_clients', 'free_servers', 'used_servers') 159 | -------------------------------------------------------------------------------- /sql_exporter/common/setup_db.sql: -------------------------------------------------------------------------------- 1 | -- pgMonitor Setup 2 | -- 3 | -- Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | -- 5 | 6 | DO $$ 7 | BEGIN 8 | IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'ccp_monitoring') THEN 9 | CREATE ROLE ccp_monitoring WITH LOGIN; 10 | END IF; 11 | END 12 | $$; 13 | 14 | GRANT pg_monitor to ccp_monitoring; 15 | GRANT pg_execute_server_program TO ccp_monitoring; 16 | 17 | ALTER ROLE ccp_monitoring SET lock_timeout TO '2min'; 18 | ALTER ROLE ccp_monitoring SET jit TO 'off'; 19 | 20 | CREATE SCHEMA IF NOT EXISTS pgmonitor_ext AUTHORIZATION ccp_monitoring; 21 | 22 | CREATE EXTENSION pgmonitor SCHEMA pgmonitor_ext; 23 | 24 | GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA pgmonitor_ext TO ccp_monitoring; 25 | GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA pgmonitor_ext TO ccp_monitoring; 26 | GRANT ALL ON ALL TABLES IN SCHEMA pgmonitor_ext TO ccp_monitoring; 27 | -------------------------------------------------------------------------------- /sql_exporter/common/sql_exporter.yml.example: -------------------------------------------------------------------------------- 1 | # Global settings and defaults. 2 | global: 3 | # Subtracted from Prometheus' scrape_timeout to give us some headroom and prevent Prometheus from 4 | # timing out first. 5 | scrape_timeout_offset: 500ms 6 | # Minimum interval between collector runs: by default (0s) collectors are executed on every scrape. 7 | min_interval: 0s 8 | # Maximum number of open connections to any one target. Metric queries will run concurrently on 9 | # multiple connections. 10 | max_connections: 3 11 | # Maximum number of idle connections to any one target. 12 | max_idle_connections: 3 13 | # Maximum amount of time a connection may be reused to any one target. Infinite by default. 14 | max_connection_lifetime: 10m 15 | # If scrape errors are corrected, how long until the scrape error metric is dropped from the metric output 16 | scrape_error_drop_interval: 5m 17 | 18 | # The target(s) to monitor and the list of collectors to execute 19 | # 20 | jobs: 21 | - job_name: global_targets 22 | collectors: [crunchy_global] 23 | static_configs: 24 | - targets: 25 | pg1: 'pg://ccp_monitoring@127.0.0.1:5432/postgres?sslmode=disable' 26 | - job_name: per_db_targets 27 | collectors: [crunchy_per_db] 28 | static_configs: 29 | - targets: 30 | pg1: 'pg://ccp_monitoring@127.0.0.1:5432/postgres?sslmode=disable' 31 | # pg2: 'pg://ccp_monitoring@127.0.0.1:5432/testdb?sslmode=disable' 32 | # - job_name: pgbouncer_targets 33 | # collectors: [crunchy_pgbouncer] 34 | # enable_ping: false 35 | # static_configs: 36 | # - targets: 37 | # pgbouncer: 'pg://ccp_monitoring@127.0.0.1:6432/pgbouncer?sslmode=disable' 38 | 39 | 40 | # Collector definition files. 41 | # Glob patterns are supported (see for syntax). 42 | collector_files: 43 | - "/etc/sql_exporter/crunchy_global_collector.yml" 44 | - "/etc/sql_exporter/crunchy_per_db_collector.yml" 45 | # - "/etc/sql_exporter/crunchy_pgbouncer_collector.yml" 46 | -------------------------------------------------------------------------------- /sql_exporter/linux/crontab.txt: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | # The below script must be run as a user with the pg_read_all_data role or a superuser. You may have to adjust your pg_hba.conf to allow this and/or use a .pgpass file 7 | # By default only scans and stores statistics for objects that are at least 1GB in size (--min_size). Setting --quiet twice, as shown, suppresses all output. 8 | # 08 03 * * 0 /usr/bin/pg_bloat_check.py --quiet --quiet -c "dbname=postgres user=ccp_monitoring" --min_size=1073741824 9 | -------------------------------------------------------------------------------- /sql_exporter/linux/crunchy-sql-exporter@.service: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | [Unit] 8 | Description=SQL Exporter for Prometheus 9 | Documentation=https://github.com/burningalchemist/sql_exporter 10 | Wants=network-online.target 11 | After=network-online.target 12 | 13 | [Service] 14 | User=ccp_monitoring 15 | EnvironmentFile=/etc/sysconfig/%i 16 | ExecStart=/usr/bin/sql_exporter $OPT 17 | Restart=on-failure 18 | # Reload not working as expected - https://github.com/burningalchemist/sql_exporter/issues/297 19 | #ExecReload=curl http://127.0.0.1:9399/reload 20 | 21 | 22 | 23 | [Install] 24 | WantedBy=multi-user.target 25 | -------------------------------------------------------------------------------- /sql_exporter/linux/sql_exporter.sysconfig: -------------------------------------------------------------------------------- 1 | ### 2 | # 3 | # Copyright © 2017-2025 Crunchy Data Solutions, Inc. All Rights Reserved. 4 | # 5 | ### 6 | 7 | OPT=-config.file=/etc/sql_exporter/sql_exporter.yml -web.listen-address=0.0.0.0:9399 -log.level=info -web.enable-reload=true 8 | --------------------------------------------------------------------------------