├── .bonsai.yml ├── .github ├── PULL_REQUEST_TEMPLATE.md └── dependabot.yml ├── .gitignore ├── .kitchen.yml ├── .rubocop.yml ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── asset_build_scripts ├── Dockerfile.alpine ├── Dockerfile.alpine3.8 ├── Dockerfile.centos ├── Dockerfile.centos6 ├── Dockerfile.centos7 ├── Dockerfile.centos8 ├── Dockerfile.debian └── Dockerfile.debian9 ├── bin ├── check-postgres-alive.rb ├── check-postgres-connections.rb ├── check-postgres-query.rb ├── check-postgres-replication.rb ├── metric-postgres-connections.rb ├── metric-postgres-dbsize.rb ├── metric-postgres-graphite.rb ├── metric-postgres-locks.rb ├── metric-postgres-relation-size.rb ├── metric-postgres-statsbgwriter.rb ├── metric-postgres-statsdb.rb ├── metric-postgres-statsio.rb ├── metric-postgres-statstable.rb ├── metric-postgres-vaccum.rb └── metrics-postgres-query.rb ├── lib ├── sensu-plugins-postgres.rb └── sensu-plugins-postgres │ ├── pgpass.rb │ ├── pgutil.rb │ └── version.rb ├── sensu-plugins-postgres.gemspec └── test ├── fixtures └── bootstrap.sh ├── integration ├── helpers │ └── serverspec │ │ ├── check-postgres-alive-shared_spec.rb │ │ ├── shared_spec.rb │ │ └── spec_helper.rb ├── ruby-21 │ └── serverspec │ │ └── default_spec.rb ├── ruby-22 │ └── serverspec │ │ └── default_spec.rb ├── ruby-230 │ └── serverspec │ │ └── default_spec.rb └── ruby-241 │ └── serverspec │ └── default_spec.rb └── spec_helper.rb /.bonsai.yml: -------------------------------------------------------------------------------- 1 | --- 2 | description: "#{repo}" 3 | builds: 4 | - platform: "alpine" 5 | arch: "amd64" 6 | asset_filename: "#{repo}_#{version}_alpine_linux_amd64.tar.gz" 7 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 8 | filter: 9 | - "entity.system.os == 'linux'" 10 | - "entity.system.arch == 'amd64'" 11 | - "entity.system.platform == 'alpine'" 12 | - "entity.system.platform_version.split('.')[0] == '3'" 13 | - platform: "alpine3.8" 14 | arch: "amd64" 15 | asset_filename: "#{repo}_#{version}_alpine3.8_linux_amd64.tar.gz" 16 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 17 | filter: 18 | - "entity.system.os == 'linux'" 19 | - "entity.system.arch == 'amd64'" 20 | - "entity.system.platform == 'alpine'" 21 | - platform: "centos6" 22 | arch: "amd64" 23 | asset_filename: "#{repo}_#{version}_centos6_linux_amd64.tar.gz" 24 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 25 | filter: 26 | - "entity.system.os == 'linux'" 27 | - "entity.system.arch == 'amd64'" 28 | - "entity.system.platform_family == 'rhel'" 29 | - "entity.system.platform_version.split('.')[0] == '6'" 30 | - platform: "centos7" 31 | arch: "amd64" 32 | asset_filename: "#{repo}_#{version}_centos7_linux_amd64.tar.gz" 33 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 34 | filter: 35 | - "entity.system.os == 'linux'" 36 | - "entity.system.arch == 'amd64'" 37 | - "entity.system.platform_family == 'rhel'" 38 | - "entity.system.platform_version.split('.')[0] == '7'" 39 | - platform: "debian7" 40 | arch: "amd64" 41 | asset_filename: "#{repo}_#{version}_debian_linux_amd64.tar.gz" 42 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 43 | filter: 44 | - "entity.system.os == 'linux'" 45 | - "entity.system.arch == 'amd64'" 46 | - "entity.system.platform_family == 'debian'" 47 | - "entity.system.platform_version.split('.')[0] == '7'" 48 | - platform: "debian8" 49 | arch: "amd64" 50 | asset_filename: "#{repo}_#{version}_debian_linux_amd64.tar.gz" 51 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 52 | filter: 53 | - "entity.system.os == 'linux'" 54 | - "entity.system.arch == 'amd64'" 55 | - "entity.system.platform_family == 'debian'" 56 | - "entity.system.platform_version.split('.')[0] == '8'" 57 | - platform: "debian9" 58 | arch: "amd64" 59 | asset_filename: "#{repo}_#{version}_debian9_linux_amd64.tar.gz" 60 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 61 | filter: 62 | - "entity.system.os == 'linux'" 63 | - "entity.system.arch == 'amd64'" 64 | - "entity.system.platform_family == 'debian'" 65 | - "entity.system.platform_version.split('.')[0] == '9'" 66 | - platform: "debian" 67 | arch: "amd64" 68 | asset_filename: "#{repo}_#{version}_debian_linux_amd64.tar.gz" 69 | sha_filename: "#{repo}_#{version}_sha512-checksums.txt" 70 | filter: 71 | - "entity.system.os == 'linux'" 72 | - "entity.system.arch == 'amd64'" 73 | - "entity.system.platform_family == 'debian'" 74 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Pull Request Checklist 2 | 3 | **Is this in reference to an existing issue?** 4 | 5 | #### General 6 | 7 | - [ ] Update Changelog following the conventions laid out [here](https://github.com/sensu-plugins/community/blob/master/HOW_WE_CHANGELOG.md) 8 | 9 | - [ ] Update README with any necessary configuration snippets 10 | 11 | - [ ] Binstubs are created if needed 12 | 13 | - [ ] RuboCop passes 14 | 15 | - [ ] Existing tests pass 16 | 17 | #### New Plugins 18 | 19 | - [ ] Tests 20 | 21 | - [ ] Add the plugin to the README 22 | 23 | - [ ] Does it have a complete header as outlined [here](http://sensu-plugins.io/docs/developer_guidelines.html#coding-style) 24 | 25 | #### Purpose 26 | 27 | #### Known Compatibility Issues 28 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | ignore: 8 | - dependency-name: rubocop 9 | versions: 10 | - 1.10.0 11 | - 1.11.0 12 | - 1.12.0 13 | - 1.9.0 14 | - 1.9.1 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.bundle 11 | *.so 12 | *.o 13 | *.a 14 | mkmf.log 15 | .vagrant/* 16 | .DS_Store 17 | .idea/* 18 | *.gem 19 | .kitchen/* 20 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: docker 4 | use_sudo: false 5 | links: 6 | # TODO: multiple versions at some point 7 | - sensu-postgres-10:sensu-postgres-10 8 | 9 | provisioner: 10 | name: shell 11 | data_path: . 12 | script: test/fixtures/bootstrap.sh 13 | 14 | # verifier: 15 | # ruby_bindir: <%= ENV['MY_RUBY_HOME'] || '/opt/sensu/embedded' %>/bin 16 | verifier: 17 | ruby_bindir: /usr/local/bin 18 | 19 | platforms: 20 | - name: debian-8 21 | 22 | suites: 23 | - name: ruby-21 24 | driver: 25 | image: ruby:2.1-slim 26 | - name: ruby-22 27 | driver: 28 | image: ruby:2.2-slim 29 | - name: ruby-230 30 | driver: 31 | image: ruby:2.3.0-slim 32 | - name: ruby-241 33 | driver: 34 | image: ruby:2.4.1-slim 35 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | TargetRubyVersion: 2.4 3 | 4 | MethodLength: 5 | Max: 200 6 | 7 | LineLength: 8 | Max: 160 9 | 10 | AbcSize: 11 | Max: 100 12 | 13 | FileName: 14 | Enabled: false 15 | 16 | PerceivedComplexity: 17 | Enabled: false 18 | 19 | CyclomaticComplexity: 20 | Enabled: false 21 | 22 | ClassLength: 23 | Enabled: false 24 | 25 | IfUnlessModifier: 26 | Enabled: false 27 | 28 | RegexpLiteral: 29 | Enabled: false 30 | 31 | Style/Documentation: 32 | Enabled: false 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: true 2 | service: docker 3 | language: ruby 4 | cache: 5 | - bundler 6 | before_install: 7 | - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) 8 | install: 9 | - bundle install 10 | rvm: 11 | - 2.4.1 12 | notifications: 13 | email: 14 | recipients: 15 | - sensu-plugin@sensu-plugins.io 16 | on_success: change 17 | on_failure: always 18 | before_script: 19 | - docker run --name sensu-postgres-10 -e POSTGRES_PASSWORD='' -d postgres 20 | 21 | script: 22 | - bundle exec rake quick 23 | - bundle exec rake kitchen:ruby-`echo $TRAVIS_RUBY_VERSION | sed -e "s/\.//g"`-debian-8 24 | - gem build sensu-plugins-postgres.gemspec 25 | - gem install sensu-plugins-postgres-*.gem 26 | before_deploy: 27 | - bash -c "[ ! -d bonsai/ ] && git clone https://github.com/sensu/sensu-go-bonsai-asset.git bonsai || echo 'bonsai/ exists, skipping git clone' ; cp asset_build_scripts/Dockerfile.* bonsai/ruby-runtime/" 28 | deploy: 29 | - provider: rubygems 30 | api_key: 31 | secure: L3ot3q90Sz+1dhi1Lxg4rvxZ0AEUCq2dL55Gzau48wou72T3GYSDBoqVGnZPmQcS9miNy4J7NZMxUgfoycnceqUkkue8+ss4c42NtrYs+SLU+rnmB/cwLTBQJ1ERRNXqgOYTwWt8EuIy6Dong1oCu8voFSj7NH4sXxTTO7RFho8= 32 | gem: sensu-plugins-postgres 33 | on: 34 | tags: true 35 | all_branches: true 36 | rvm: 2.4.1 37 | repo: sensu-plugins/sensu-plugins-postgres 38 | - provider: script 39 | script: bonsai/ruby-runtime/travis-build-ruby-plugin-assets.sh sensu-plugins-postgres 40 | skip_cleanup: true 41 | on: 42 | tags: true 43 | all_branches: true 44 | rvm: 2.4.1 45 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | This project adheres to [Semantic Versioning](http://semver.org/). 3 | 4 | This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins/community/blob/master/HOW_WE_CHANGELOG.md). 5 | 6 | ## [Unreleased] 7 | ## [4.3.0] - 2021-09-15 8 | 9 | ### Added 10 | - asset for generic debian build (including ubuntu) (@VeselaHouba) 11 | 12 | ### Fixed 13 | - Fixing asset build directive for centos6, using package repository archive now that centos6 is EOL 14 | 15 | ## [4.2.0] - 2020-11-29 16 | ### Added 17 | - new `bin/metric-postgres-relation-size.rb` find largest tables (@phumpal) 18 | 19 | ## [4.1.0] - 2020-06-04 20 | ### Added 21 | - new `metric-postgres-vaccum.rb` metric gathering script for postgres vacuum process (@phumpal) 22 | 23 | ## [4.0.2] - 2020-06-02 24 | - Fixed `# frozen_string_literal: true` does not play nicely with mixlib-cli. 25 | 26 | ## [4.0.1] - 2020-04-20 27 | ### Fixed 28 | - Fixing asset build directives. 29 | 30 | ## [4.0.0] - 2020-01-09 31 | 32 | ### Breaking Changes 33 | - Update `sensu-plugin` dependency from `~> 1.2` to `~> 4.0` you can read the changelog entries for [4.0](https://github.com/sensu-plugins/sensu-plugin/blob/master/CHANGELOG.md#400---2018-02-17), [3.0](https://github.com/sensu-plugins/sensu-plugin/blob/master/CHANGELOG.md#300---2018-12-04), and [2.0](https://github.com/sensu-plugins/sensu-plugin/blob/master/CHANGELOG.md#v200---2017-03-29) 34 | - `check-postgres-replication.rb`: both `--slave-host` and `master-host` arguments are now required flags where previously they had localhost defaults (@phumpal) 35 | 36 | ### Fixed 37 | - `check-postgres-replication.rb`: fix condition where connection timeout is considered a boolean rather than an integer value (@majormoses) (@phumpal) (@VeselaHouba) 38 | - `check-postgres-replication.rb`: critical if the master and slave are same (@phumpal) 39 | 40 | ### Added 41 | - `check-postgres-query.rb`: Add `-r`, `--regex-pattern` to match query result against (@jindraj) 42 | 43 | ### Changes 44 | - Updated development dependency to bundler ~> 2.1 45 | - Updated development dependency to rake ~> 13.0 46 | - Updated development dependency to test-kitchen ~> 1.25.0 47 | - Updated runtime dependency to 'pg' '1.2.1' from 1.1 48 | - Updated runtime dependency 'dentaku' '3.3.4' from 2.04 49 | 50 | ## [3.0.0] - 2019-11-20 51 | ### Breaking Changes 52 | - Removed ruby < 2.4 since these Rubies are EOL (@phumpal) 53 | 54 | ## [2.4.0] - 2019-10-04 55 | ### Added 56 | - Support comments in pgpass file. Keeps previous behavior and adds support for ignoring leading comments (@phumpal) 57 | 58 | ## [2.3.2] - 2019-03-12 59 | ### Fixed 60 | - Support for PostgreSQL v10+ replication function names fixed in `bin/metric-postgres-graphite.rb` (@jfineberg) 61 | 62 | ## [2.3.1] - 2018-12-16 63 | ### Fixed 64 | - metric-postgres-statsdb.rb: Change `Array` method from `append` to `push` to maintain compatibility w/ non-EOL Rubies (@phumpal) 65 | 66 | ## [2.3.0] - 2018-12-08 67 | ### Added 68 | - metric-postgres-statsdb.rb: Add --all-databases option. (@cyrilgdn) 69 | 70 | ## [2.2.2] - 2018-10-27 71 | ### Fixed 72 | - Remove unexplicit dependency on ActiveSupport (@multani) 73 | 74 | ## [2.2.1] - 2018-10-16 75 | ### Security 76 | - updated yard dependency to `~> 0.9.11` per: https://nvd.nist.gov/vuln/detail/CVE-2017-17042 (@majormoses) 77 | 78 | ## [2.2.0] - 2018-10-16 79 | ### Added 80 | - metric-postgres-statsbgwriter.rb: additional metrics (@phumpal) 81 | - metric-postgres-statsdb.rb additional metrics (@phumpal) 82 | 83 | ## [2.1.0] - 2018-10-16 84 | ### Added 85 | - Moves check_vsn and compute_lag to library method (@phumpal) 86 | 87 | ## [2.0.0] - 2018-10-15 88 | ### Breaking Changes 89 | - Remove unsupported Rubies: `< 2.3.0` (@phumpal) 90 | 91 | ## [1.4.6] - 2018-05-03 92 | ### Fixed 93 | - version number check for build strings such as `10.3 (Ubuntu 10.3-1.pgdg16.04+1)` (@jfineberg) 94 | 95 | ### Added 96 | - tests for connecting with a pgpass file (@majormoses) 97 | 98 | ## [1.4.5] - 2018-02-15 99 | ### Fixed 100 | - metric-postgres-graphite.rb: use the custom defined port when connecting to slave (@henkjan) 101 | 102 | ### Added 103 | - basic skel for integration testing with postgres (@majormoses) 104 | - added test for `./bin/check-postgres-alive.rb` 105 | 106 | ## [1.4.4] - 2017-11-08 107 | ### Fixed 108 | - check-postgres-replication.rb: fix 9.x compatibility 109 | 110 | ## [1.4.3] - 2017-11-06 111 | ### Fixed 112 | - check-postgres-replication.rb: maintains backwards compatibility with <= 9.6 and adds compatibility for >= 10 113 | 114 | ## [1.4.2] - 2017-09-27 115 | ### Fixed 116 | - metric-postgres-locks.rb: Fix lock count collection (@madboxkr) 117 | 118 | ## [1.4.1] - 2017-09-26 119 | ### Fixed 120 | - metrics-postgres-query.rb: Add a nil check to avoid failure when the query result is empty (@eheydrick) 121 | - PR template spelling (@majormoses) 122 | 123 | ### Changed 124 | - updated CHANGELOG guidelines location (@majormoses) 125 | 126 | ## [1.4.0] - 2017-08-04 127 | ### Added 128 | - all checks now support using the pgpass file and is backwards compatible with the previous versions (@ahes) 129 | 130 | ## [1.3.0] - 2017-07-25 131 | ### Fixed 132 | - Take into account reserved superuser connections in check-postgres-connections.rb (@Evesy) 133 | 134 | ### Added 135 | - Ruby 2.4.1 testing 136 | 137 | ## [1.2.0] - 2017-07-12 138 | ### Added 139 | - metric-postgres-statsdb.rb: Adds new metric `numbackends`. (@phumpal) 140 | 141 | ## [1.1.2] - 2017-06-02 142 | ### Fixed 143 | - check-postgresq-replication.rb: Adds missing option for custom port. 144 | 145 | ## [1.1.1] - 2017-04-24 146 | ### Fixed 147 | - metrics-postgres-query.rb: Restored default value to only return first value in query. (@Micasou) 148 | 149 | ## [1.1.0] - 2017-04-20 150 | ### Added 151 | - metrics-postgres-query.rb: Add option to return multi row queries. (@Micasou) 152 | 153 | ### Fixed 154 | - check-postgres-alive.rb: Fix connections using a custom port (#25 via @mickfeech) 155 | - check-postgres-connections.rb: Fix connections using a custom port (#25) 156 | - check-postgres-query.rb: Fix connections using a custom port (#25) 157 | - check-postgres-replication.rb: Fix connections using a custom port (#25) 158 | - metrics-postgres-connections.rb: Fix connections using a custom port (#25) 159 | - metrics-postgres-dbsize.rb: Fix connections using a custom port (#25) 160 | - metrics-postgres-graphite.rb: Fix connections using a custom port (#25) 161 | - metrics-postgres-graphite.rb: Fix connections using password (@teadur) 162 | - metrics-postgres-locks.rb: Fix connections using a custom port (#25) 163 | - metrics-postgres-statsgbwriter.rb: Fix connections using a custom port (#25) 164 | - metrics-postgres-statsdb.rb: Fix connections using a custom port (#25) 165 | - metrics-postgres-statsio.rb: Fix connections using a custom port (#25) 166 | - metrics-postgres-statstable.rb: Fix connections using a custom port (#25) 167 | - metrics-postgres-query.rb: Fix connections using a custom port (#25) 168 | - check-postgres-connections.rb: Fix logic to check critical first then warning (#24 via @nevins-b) 169 | 170 | ## [1.0.1] - 2017-01-04 171 | ### Fixed 172 | - metrics-postgres-query.rb: Fix `count_tuples` option (#23) (@eheydrick) 173 | 174 | ## [1.0.0] - 2016-12-27 175 | ### Fixed 176 | - metric-postgres-connections: Handle postgres version 9.6 and above. 177 | 178 | ### Removed 179 | - Ruby 1.9.3 and 2.0.0 support 180 | 181 | ### Added 182 | - Ruby 2.3.0 support 183 | - Update all the scripts to add an optional timeout setting. 184 | 185 | ## [0.1.1] - 2016-03-24 186 | ### Added 187 | - metric-postgres-connections: Add new metric `total` 188 | 189 | ### Fixed 190 | - metric-postgres-connections: Correctly evaluate and collect metrics for active connections and active connections waiting on backend locks 191 | 192 | ## [0.1.0] - 2016-03-09 193 | ### Added 194 | - Add new plugin `check-postgres-connections` that checks the number of connections to a DB 195 | 196 | ## [0.0.7] - 2015-12-10 197 | ### Changed 198 | - fixed [ -S | -ssl ] short option 199 | 200 | ## [0.0.6] - 2015-10-08 201 | ### Changed 202 | - standardized headers 203 | 204 | ### Added 205 | - added plugins for querying postgres 206 | 207 | ## [0.0.5] - 2015-10-06 208 | ### Changed 209 | - updated pg gem to 0.18.3 210 | - Added port cli option to postgres-graphite.rb. 211 | 212 | ## [0.0.4] - 2015-08-04 213 | ### Changed 214 | - general cleanup, no code changes 215 | 216 | ## [0.0.3] - 2015-07-14 217 | ### Changed 218 | - updated sensu-plugin gem to 1.2.0 219 | 220 | ## [0.0.2] - 2015-06-03 221 | ### Fixed 222 | - added binstubs 223 | 224 | ### Changed 225 | - removed cruft from /lib 226 | 227 | ## 0.0.1 - 2015-04-30 228 | ### Added 229 | - initial release 230 | 231 | [Unreleased]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/4.3.0...HEAD 232 | [4.3.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/4.2.0...4.3.0 233 | [4.2.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/4.1.0...4.2.0 234 | [4.1.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/4.0.2...4.1.0 235 | [4.0.2]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/4.0.1...4.0.2 236 | [4.0.1]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/4.0.0...4.0.1 237 | [4.0.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/3.0.0...4.0.0 238 | [3.0.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.4.0...3.0.0 239 | [2.4.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.3.2...2.4.0 240 | [2.3.2]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.3.1...2.3.2 241 | [2.3.1]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.3.0...2.3.1 242 | [2.3.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.2.2...2.3.0 243 | [2.2.2]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.2.1...2.2.2 244 | [2.2.1]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.2.0...2.2.1 245 | [2.2.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.1.0...2.2.0 246 | [2.1.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/2.0.0...2.1.0 247 | [2.0.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.4.6...2.0.0 248 | [1.4.6]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.4.5...1.4.6 249 | [1.4.5]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.4.4...1.4.5 250 | [1.4.4]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.4.3...1.4.4 251 | [1.4.3]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.4.2...1.4.3 252 | [1.4.2]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.4.1...1.4.2 253 | [1.4.1]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.4.0...1.4.1 254 | [1.4.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.3.0...1.4.0 255 | [1.3.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.2.0...1.3.0 256 | [1.2.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.1.2...1.2.0 257 | [1.1.2]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.1.1...1.1.2 258 | [1.1.1]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.1.0...1.1.1 259 | [1.1.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.0.1...1.1.0 260 | [1.0.1]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/1.0.0...1.0.1 261 | [1.0.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.1.1...1.0.0 262 | [0.1.1]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.1.0...0.1.1 263 | [0.1.0]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.0.7...0.1.0 264 | [0.0.7]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.0.6...0.0.7 265 | [0.0.6]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.0.5...0.0.6 266 | [0.0.5]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.0.4...0.0.5 267 | [0.0.4]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.0.3...0.0.4 268 | [0.0.3]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.0.2...0.0.3 269 | [0.0.2]: https://github.com/sensu-plugins/sensu-plugins-postgres/compare/0.0.1...0.0.2 270 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | [Development Documentation](http://sensu-plugins.io/docs/developer_guidelines.html) 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | # Specify your gem's dependencies in sensu-plugins-postgres.gemspec 6 | gemspec 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Sensu-Plugins 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Sensu-Plugins-postgres 2 | 3 | [![Build Status](https://travis-ci.org/sensu-plugins/sensu-plugins-postgres.svg?branch=master)](https://travis-ci.org/sensu-plugins/sensu-plugins-postgres) 4 | [![Gem Version](https://badge.fury.io/rb/sensu-plugins-postgres.svg)](http://badge.fury.io/rb/sensu-plugins-postgres) 5 | [![Code Climate](https://codeclimate.com/github/sensu-plugins/sensu-plugins-postgres/badges/gpa.svg)](https://codeclimate.com/github/sensu-plugins/sensu-plugins-postgres) 6 | [![Test Coverage](https://codeclimate.com/github/sensu-plugins/sensu-plugins-postgres/badges/coverage.svg)](https://codeclimate.com/github/sensu-plugins/sensu-plugins-postgres) 7 | [![Dependency Status](https://gemnasium.com/sensu-plugins/sensu-plugins-postgres.svg)](https://gemnasium.com/sensu-plugins/sensu-plugins-postgres) 8 | 9 | ## Functionality 10 | 11 | ## Files 12 | * bin/check-postgres-alive.rb 13 | * bin/check-postgres-connections.rb 14 | * bin/metric-postgres-dbsize.rb 15 | * bin/metric-postgres-statsbgwriter.rb 16 | * bin/metric-postgres-statstable.rb 17 | * bin/check-postgres-replication.rb 18 | * bin/metric-postgres-graphite.rb 19 | * bin/metric-postgres-statsdb.rb 20 | * bin/metric-postgres-connections.rb 21 | * bin/metric-postgres-locks.rb 22 | * bin/metric-postgres-statsio.rb 23 | * bin/check-postgres-query.rb 24 | * bin/metrics-postgres-query.rb 25 | * bin/metric-postgres-relation-size.rb 26 | 27 | ## Usage 28 | 29 | Use `--help` to see command arguments. 30 | 31 | ### Sample usage 32 | 33 | #### Check if PostgreSQL is alive 34 | ``` 35 | $ check-postgres-alive.rb -d template1 -f /var/lib/postgresql/.pgpass 36 | CheckPostgres OK: Server version: {"version"=>"PostgreSQL 9.6.3 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit"} 37 | ``` 38 | 39 | ### Check replication status 40 | ``` 41 | $ check-postgres-replication.rb -m psql1.local -s psql2.local -d template1 -w 5 -c 10 42 | CheckPostgresReplicationStatus OK: replication delayed by 0.0MB :: master:B0/B4031000 slave:B0/B4031000 m_segbytes:16777216 43 | ``` 44 | 45 | ### Check number of connections 46 | ``` 47 | $ export PGPASSWORD=this-is-secret-password 48 | $ check-postgres-connections.rb -a -w 80 -c 90 -d template1 -u sensu 49 | CheckPostgresConnections OK: PostgreSQL connections under threshold: 17%, 174 out of 997 connections 50 | ``` 51 | 52 | ### Default values 53 | 54 | | Argument | Env variable | Value | 55 | |----------------|--------------|-----------| 56 | | -f, --pgpass | PGPASSFILE | ~/.pgpass | 57 | | -h, --hostname | PGHOST | localhost | 58 | | -P, --port | PGPORT | 5432 | 59 | | -d, --database | PGDATABASE | postgres | 60 | | -u, --user | PGUSER | postgres | 61 | | -p, --password | PGPASSWORD | | 62 | 63 | Options precedence is following: 64 | 1. command line arguments 65 | 1. pgpass file 66 | 1. env variables 67 | 1. defaults 68 | 69 | ### Pgpass file 70 | 71 | When file `~/.pgpass` is found it is used by default. You can also use `-f, --pgpass` command line argument or set `PGPASSFILE` env variable. 72 | 73 | File format is: 74 | 75 | ``` 76 | hostname:port:database:username:password 77 | ``` 78 | 79 | Only first line is used. If database is set to `*` it is ommited. 80 | 81 | You can ovveride `pgpass` values with command line arguments, e.g. `-h` for hostname. 82 | 83 | ## Installation 84 | 85 | ``` 86 | gem install sensu-plugins-postgres 87 | ``` 88 | 89 | ## Centos installation 90 | 91 | ``` 92 | yum -y install gcc ruby-devel rubygems postgresql-devel 93 | sensu-install -p sensu-plugins-postgres 94 | 95 | ``` 96 | 97 | See [Installation and Setup](http://sensu-plugins.io/docs/installation_instructions.html) for details. 98 | 99 | ### Known issues 100 | 101 | When using Sensu with `EMBEDDED_RUBY=true` and installing Postgres checks with `/usr/bin/sensu-install -p sensu-plugins-postgres` you might get following error: 102 | 103 | ``` 104 | ERROR: Error installing sensu-plugins-postgres: 105 | ERROR: Failed to build gem native extension. 106 | [...] 107 | checking for PQconnectdb() in -lpq... no 108 | checking for PQconnectdb() in -llibpq... no 109 | checking for PQconnectdb() in -lms/libpq... no 110 | Can't find the PostgreSQL client library (libpq) 111 | *** extconf.rb failed *** 112 | ``` 113 | 114 | The reason is that **libssl** library which comes with Sensu is incompatible with **libpq** library installed on your system. There is no easy way to fix it. You might want to install sensu-plugins-postgres globally with `gem install sensu-plugins-postgres`. 115 | 116 | Checks are in `/usr/local/bin` directory. 117 | 118 | ## Notes 119 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'github/markup' 5 | require 'redcarpet' 6 | require 'rspec/core/rake_task' 7 | require 'rubocop/rake_task' 8 | require 'yard' 9 | require 'yard/rake/yardoc_task' 10 | require 'English' 11 | require 'kitchen/rake_tasks' 12 | 13 | YARD::Rake::YardocTask.new do |t| 14 | OTHER_PATHS = %w[].freeze 15 | t.files = ['lib/**/*.rb', 'bin/**/*.rb', OTHER_PATHS] 16 | t.options = %w[--markup-provider=redcarpet --markup=markdown --main=README.md --files CHANGELOG.md] 17 | end 18 | 19 | RuboCop::RakeTask.new 20 | 21 | RSpec::Core::RakeTask.new(:spec) do |r| 22 | r.pattern = FileList['**/**/*_spec.rb'] 23 | end 24 | 25 | desc 'Make all plugins executable' 26 | task :make_bin_executable do 27 | `chmod -R +x bin/*` 28 | end 29 | 30 | desc 'Test for binstubs' 31 | task :check_binstubs do 32 | bin_list = Gem::Specification.load('sensu-plugins-postgres.gemspec').executables 33 | bin_list.each do |b| 34 | `which #{b}` 35 | unless $CHILD_STATUS.success? 36 | puts "#{b} was not a binstub" 37 | exit 38 | end 39 | end 40 | end 41 | 42 | Kitchen::RakeTasks.new 43 | 44 | desc 'Alias for kitchen:all' 45 | task integration: 'kitchen:all' 46 | 47 | task default: %i[spec make_bin_executable yard rubocop check_binstubs integration] 48 | task quick: %i[make_bin_executable yard rubocop check_binstubs] 49 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.alpine: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-alpine:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG RUBY_VERSION=2.4.4 6 | 7 | WORKDIR /assets/build/ 8 | RUN apk del openssl-dev 9 | RUN apk add git 10 | RUN apk add libressl-dev postgresql-client postgresql-dev 11 | RUN \ 12 | gem install --no-ri --no-doc bundler && \ 13 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 14 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 15 | 16 | RUN LIBS=$(find ./ -type f -exec ldd {} 2>/dev/null \;| grep "=>" | grep -v "vdso.so.1" | awk '{print $3}'| sort -u ) && \ 17 | for f in $LIBS; do if [ -e $f ] && [ ! -e /opt/rubies/ruby-${RUBY_VERSION}/lib/$f ] ; then echo "Copying Library: $f" && cp $f ./lib/; fi; done 18 | 19 | 20 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 21 | 22 | FROM scratch 23 | ARG ASSET_GEM 24 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 25 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.alpine3.8: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-alpine3.8:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG RUBY_VERSION=2.4.4 6 | 7 | WORKDIR /assets/build/ 8 | RUN apk del openssl-dev 9 | RUN apk add git 10 | RUN apk add libressl-dev postgresql-client postgresql-dev 11 | RUN \ 12 | gem install --no-ri --no-doc bundler && \ 13 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 14 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 15 | 16 | RUN LIBS=$(find ./ -type f -exec ldd {} 2>/dev/null \;| grep "=>" | grep -v "vdso.so.1" | awk '{print $3}'| sort -u ) && \ 17 | for f in $LIBS; do if [ -e $f ] && [ ! -e /opt/rubies/ruby-${RUBY_VERSION}/lib/$f ] ; then echo "Copying Library: $f" && cp $f ./lib/; fi; done 18 | 19 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 20 | 21 | FROM scratch 22 | ARG ASSET_GEM 23 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 24 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.centos: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-centos:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG GREP_EXCLUDE='(ld.so|ld-linux-x86-64.so|libBrokenLocale.so|libSegFault.so|libanl.so|libc.so|libdl.so|libm.so|libmvec.so|libnss_compat.so|libnss_dns.so|libnss_files.so|libpthread.so|libresolv.so|librt.so|libthread_db.so|libutil.so|vdso.so)' 6 | ARG RUBY_VERSION=2.4.4 7 | 8 | WORKDIR /assets/build/ 9 | RUN yum install -y git 10 | RUN yum install -y https://download.postgresql.org/pub/repos/yum/9.5/redhat/rhel-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm 11 | RUN yum install -y postgresql95 postgresql95-libs postgresql95-devel 12 | ENV CONFIGURE_ARGS="with-pg-config=/usr/pgsql-9.5/bin/pg_config" 13 | RUN \ 14 | gem install --no-ri --no-doc bundler && \ 15 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 16 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 17 | 18 | RUN LIBS=$(find ./ -type f -executable -exec ldd {} 2>/dev/null \;| grep "=>" | egrep -v ${GREP_EXCLUDE} | awk '{print $3}'| sort -u ) && \ 19 | for f in $LIBS; do if [ -e $f ] && [ ! -e /opt/rubies/ruby-${RUBY_VERSION}/lib/$f ] ; then echo "Copying Library: $f" && cp $f ./lib/; fi; done 20 | 21 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 22 | 23 | FROM scratch 24 | ARG ASSET_GEM 25 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 26 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.centos6: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-centos6:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG GREP_EXCLUDE='(ld.so|ld-linux-x86-64.so|libBrokenLocale.so|libSegFault.so|libanl.so|libc.so|libdl.so|libm.so|libmvec.so|libnss_compat.so|libnss_dns.so|libnss_files.so|libpthread.so|libresolv.so|librt.so|libthread_db.so|libutil.so|vdso.so)' 6 | ARG RUBY_VERSION=2.4.4 7 | 8 | WORKDIR /assets/build/ 9 | RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo 10 | RUN yum install -y git 11 | RUN yum install -y https://download.postgresql.org/pub/repos/yum/9.5/redhat/rhel-6-x86_64/pgdg-redhat-repo-latest.noarch.rpm 12 | RUN yum install -y postgresql95 postgresql95-libs postgresql95-devel 13 | ENV CONFIGURE_ARGS="with-pg-config=/usr/pgsql-9.5/bin/pg_config" 14 | RUN \ 15 | gem install --no-ri --no-doc bundler && \ 16 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 17 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 18 | 19 | RUN LIBS=$(find ./ -type f -executable -exec ldd {} 2>/dev/null \;| grep "=>" | egrep -v ${GREP_EXCLUDE} | awk '{print $3}'| sort -u ) && \ 20 | for f in $LIBS; do if [ -e $f ] && [ ! -e /opt/rubies/ruby-${RUBY_VERSION}/lib/$f ] ; then echo "Copying Library: $f" && cp $f ./lib/; fi; done 21 | 22 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 23 | 24 | FROM scratch 25 | ARG ASSET_GEM 26 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 27 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.centos7: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-centos7:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG GREP_EXCLUDE='(ld.so|ld-linux-x86-64.so|libBrokenLocale.so|libSegFault.so|libanl.so|libc.so|libdl.so|libm.so|libmvec.so|libnss_compat.so|libnss_dns.so|libnss_files.so|libpthread.so|libresolv.so|librt.so|libthread_db.so|libutil.so|vdso.so)' 6 | ARG RUBY_VERSION=2.4.4 7 | 8 | WORKDIR /assets/build/ 9 | RUN yum install -y git 10 | RUN yum install -y https://download.postgresql.org/pub/repos/yum/9.5/redhat/rhel-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm 11 | RUN yum install -y postgresql95 postgresql95-libs postgresql95-devel 12 | ENV CONFIGURE_ARGS="with-pg-config=/usr/pgsql-9.5/bin/pg_config" 13 | RUN \ 14 | gem install --no-ri --no-doc bundler && \ 15 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 16 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 17 | 18 | RUN LIBS=$(find ./ -type f -executable -exec ldd {} 2>/dev/null \;| grep "=>" | egrep -v ${GREP_EXCLUDE} | awk '{print $3}'| sort -u ) && \ 19 | for f in $LIBS; do if [ -e $f ] && [ ! -e /opt/rubies/ruby-${RUBY_VERSION}/lib/$f ] ; then echo "Copying Library: $f" && cp $f ./lib/; fi; done 20 | 21 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 22 | 23 | FROM scratch 24 | ARG ASSET_GEM 25 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 26 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.centos8: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-centos8:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG GREP_EXCLUDE='(ld.so|ld-linux-x86-64.so|libBrokenLocale.so|libSegFault.so|libanl.so|libc.so|libdl.so|libm.so|libmvec.so|libnss_compat.so|libnss_dns.so|libnss_files.so|libpthread.so|libresolv.so|librt.so|libthread_db.so|libutil.so|vdso.so)' 6 | ARG RUBY_VERSION=2.4.4 7 | 8 | WORKDIR /assets/build/ 9 | RUN yum install -y git 10 | RUN yum install -y https://download.postgresql.org/pub/repos/yum/9.5/redhat/rhel-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm 11 | RUN yum config-manager --disable pgdg* 12 | RUN yum config-manager --enable pgdg95 13 | RUN yum list "postgresql95*" 14 | RUN yum install --disablerepo=appstream -y postgresql95 postgresql95-libs postgresql95-devel 15 | ENV CONFIGURE_ARGS="with-pg-config=/usr/pgsql-9.5/bin/pg_config" 16 | 17 | RUN \ 18 | gem install --no-ri --no-doc bundler && \ 19 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 20 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 21 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 22 | 23 | FROM scratch 24 | ARG ASSET_GEM 25 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 26 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.debian: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-debian:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG GREP_EXCLUDE='(ld.so|ld-linux-x86-64.so|libBrokenLocale.so|libSegFault.so|libanl.so|libc.so|libdl.so|libm.so|libmvec.so|libnss_compat.so|libnss_dns.so|libnss_files.so|libpthread.so|libresolv.so|librt.so|libthread_db.so|libutil.so|vdso.so)' 6 | ARG RUBY_VERSION=2.4.4 7 | 8 | WORKDIR /assets/build/ 9 | RUN apt-get update && apt-get install -y git 10 | RUN apt-get install -y libpq-dev 11 | RUN \ 12 | gem install --no-ri --no-doc bundler && \ 13 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 14 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 15 | 16 | RUN LIBS=$(find ./ -type f -executable -exec ldd {} 2>/dev/null \;| grep "=>" | egrep -v ${GREP_EXCLUDE} | awk '{print $3}'| sort -u ) && \ 17 | for f in $LIBS; do if [ -e $f ] && [ ! -e /opt/rubies/ruby-${RUBY_VERSION}/lib/$f ] ; then echo "Copying Library: $f" && cp $f ./lib/; fi; done 18 | 19 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 20 | 21 | FROM scratch 22 | ARG ASSET_GEM 23 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 24 | -------------------------------------------------------------------------------- /asset_build_scripts/Dockerfile.debian9: -------------------------------------------------------------------------------- 1 | FROM sensu/sensu-ruby-runtime-2.4.4-debian9:latest as builder 2 | ARG ASSET_GEM 3 | ARG GIT_REF 4 | ARG GIT_REPO 5 | ARG GREP_EXCLUDE='(ld.so|ld-linux-x86-64.so|libBrokenLocale.so|libSegFault.so|libanl.so|libc.so|libdl.so|libm.so|libmvec.so|libnss_compat.so|libnss_dns.so|libnss_files.so|libpthread.so|libresolv.so|librt.so|libthread_db.so|libutil.so|vdso.so)' 6 | ARG RUBY_VERSION=2.4.4 7 | 8 | WORKDIR /assets/build/ 9 | RUN apt-get update && apt-get install -y git 10 | RUN apt-get install -y libpq-dev 11 | RUN \ 12 | gem install --no-ri --no-doc bundler && \ 13 | printf "source 'https://rubygems.org'\n\ngem \"%s\", :git => \"%s\" , :ref => \"%s\"\n" ${ASSET_GEM} ${GIT_REPO} ${GIT_REF}| tee Gemfile 14 | RUN bundle install --path=lib/ --binstubs=bin/ --standalone 15 | 16 | RUN LIBS=$(find ./ -type f -executable -exec ldd {} 2>/dev/null \;| grep "=>" | egrep -v ${GREP_EXCLUDE} | awk '{print $3}'| sort -u ) && \ 17 | for f in $LIBS; do if [ -e $f ] && [ ! -e /opt/rubies/ruby-${RUBY_VERSION}/lib/$f ] ; then echo "Copying Library: $f" && cp $f ./lib/; fi; done 18 | 19 | RUN tar -czf /assets/${ASSET_GEM}.tar.gz -C /assets/build/ . 20 | 21 | FROM scratch 22 | ARG ASSET_GEM 23 | COPY --from=builder /assets/${ASSET_GEM}.tar.gz / 24 | -------------------------------------------------------------------------------- /bin/check-postgres-alive.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # check-postgres-alive 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin attempts to login to postgres with provided credentials. 10 | # 11 | # OUTPUT: 12 | # plain text 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./check-postgres-alive.rb -u db_user -p db_pass -h db_host -d db 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Copyright (c) 2012 Lewis Preson & Tom Bassindale 28 | # Released under the same terms as Sensu (the MIT license); see LICENSE 29 | # for details. 30 | # 31 | 32 | require 'sensu-plugins-postgres/pgpass' 33 | require 'sensu-plugin/check/cli' 34 | require 'pg' 35 | 36 | class CheckPostgres < Sensu::Plugin::Check::CLI 37 | option :pgpass, 38 | description: 'Pgpass file', 39 | short: '-f FILE', 40 | long: '--pgpass', 41 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 42 | 43 | option :user, 44 | description: 'Postgres User', 45 | short: '-u USER', 46 | long: '--user USER' 47 | 48 | option :password, 49 | description: 'Postgres Password', 50 | short: '-p PASS', 51 | long: '--password PASS' 52 | 53 | option :hostname, 54 | description: 'Hostname to login to', 55 | short: '-h HOST', 56 | long: '--hostname HOST' 57 | 58 | option :database, 59 | description: 'Database schema to connect to', 60 | short: '-d DATABASE', 61 | long: '--database DATABASE' 62 | 63 | option :port, 64 | description: 'Database port', 65 | short: '-P PORT', 66 | long: '--port PORT' 67 | 68 | option :timeout, 69 | description: 'Connection timeout (seconds)', 70 | short: '-T TIMEOUT', 71 | long: '--timeout TIMEOUT', 72 | default: nil 73 | 74 | include Pgpass 75 | 76 | def run 77 | pgpass 78 | con = PG.connect(host: config[:hostname], 79 | dbname: config[:database], 80 | user: config[:user], 81 | password: config[:password], 82 | port: config[:port], 83 | connect_timeout: config[:timeout]) 84 | res = con.exec('select version();') 85 | info = res.first 86 | 87 | ok "Server version: #{info}" 88 | rescue PG::Error => e 89 | critical "Error message: #{e.error.split("\n").first}" 90 | ensure 91 | con&.close 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /bin/check-postgres-connections.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # check-postgres-connections 6 | # 7 | # DESCRIPTION: 8 | # This plugin checks the number of connections to a postgresql database and 9 | # alerts when the number or percent crosses a threshold. Defaults to checking 10 | # number of connections unless the --percentage flag is used in which case the 11 | # percentage of max connections is checked. 12 | # 13 | # OUTPUT: 14 | # plain-text 15 | # 16 | # PLATFORMS: 17 | # Linux 18 | # 19 | # DEPENDENCIES: 20 | # gem: pg 21 | # gem: sensu-plugin 22 | # 23 | # USAGE: 24 | # # warn when connections hit 250, critical when 400 25 | # check-postgres-connections.rb -u db_user -p db_pass -h db_host -d db -w 250 -c 400 26 | # # warn when connections hit 80%, critical when 95% 27 | # check-postgres-connections.rb -u db_user -p db_pass -h db_host -d db -w 80 -c 95 --percentage 28 | # 29 | # NOTES: 30 | # 31 | # LICENSE: 32 | # Copyright 2016, Eric Heydrick 33 | # Released under the same terms as Sensu (the MIT license); see LICENSE 34 | # for details. 35 | # 36 | 37 | require 'sensu-plugins-postgres/pgpass' 38 | require 'sensu-plugin/check/cli' 39 | require 'pg' 40 | 41 | class CheckPostgresConnections < Sensu::Plugin::Check::CLI 42 | option :pgpass, 43 | description: 'Pgpass file', 44 | short: '-f FILE', 45 | long: '--pgpass', 46 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 47 | 48 | option :user, 49 | description: 'Postgres User', 50 | short: '-u USER', 51 | long: '--user USER' 52 | 53 | option :password, 54 | description: 'Postgres Password', 55 | short: '-p PASS', 56 | long: '--password PASS' 57 | 58 | option :hostname, 59 | description: 'Hostname to login to', 60 | short: '-h HOST', 61 | long: '--hostname HOST' 62 | 63 | option :port, 64 | description: 'Database port', 65 | short: '-P PORT', 66 | long: '--port PORT' 67 | 68 | option :database, 69 | description: 'Database name', 70 | short: '-d DB', 71 | long: '--db DB' 72 | 73 | option :warning, 74 | description: 'Warning threshold number or % of connections. (default: 200 connections)', 75 | short: '-w WARNING', 76 | long: '--warning WARNING', 77 | default: 200, 78 | proc: proc(&:to_i) 79 | 80 | option :critical, 81 | description: 'Critical threshold number or % of connections. (default: 250 connections)', 82 | short: '-c CRITICAL', 83 | long: '--critical CRITICAL', 84 | default: 250, 85 | proc: proc(&:to_i) 86 | 87 | option :use_percentage, 88 | description: 'Use percentage of max connections used instead of the absolute number of connections', 89 | short: '-a', 90 | long: '--percentage', 91 | boolean: true, 92 | default: false 93 | 94 | option :timeout, 95 | description: 'Connection timeout (seconds)', 96 | short: '-T TIMEOUT', 97 | long: '--timeout TIMEOUT', 98 | default: nil 99 | 100 | include Pgpass 101 | 102 | def run 103 | begin 104 | pgpass 105 | con = PG.connect(host: config[:hostname], 106 | dbname: config[:database], 107 | user: config[:user], 108 | password: config[:password], 109 | port: config[:port], 110 | connect_timeout: config[:timeout]) 111 | max_conns = con.exec('SHOW max_connections').getvalue(0, 0).to_i 112 | superuser_conns = con.exec('SHOW superuser_reserved_connections').getvalue(0, 0).to_i 113 | available_conns = max_conns - superuser_conns 114 | current_conns = con.exec('SELECT count(*) from pg_stat_activity').getvalue(0, 0).to_i 115 | rescue PG::Error => e 116 | unknown "Unable to query PostgreSQL: #{e.message}" 117 | end 118 | 119 | percent = (current_conns / max_conns.to_f * 100).to_i 120 | 121 | if config[:use_percentage] 122 | message = "PostgreSQL connections at #{percent}%, #{current_conns} out of #{available_conns} connections" 123 | if percent >= config[:critical] 124 | critical message 125 | elsif percent >= config[:warning] 126 | warning message 127 | else 128 | ok "PostgreSQL connections under threshold: #{percent}%, #{current_conns} out of #{available_conns} connections" 129 | end 130 | else 131 | message = "PostgreSQL connections at #{current_conns} out of #{available_conns} connections" 132 | if current_conns >= config[:critical] 133 | critical message 134 | elsif current_conns >= config[:warning] 135 | warning message 136 | else 137 | ok "PostgreSQL connections under threshold: #{current_conns} out of #{available_conns} connections" 138 | end 139 | end 140 | end 141 | end 142 | -------------------------------------------------------------------------------- /bin/check-postgres-query.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # check-postgres-query 6 | # 7 | # DESCRIPTION: 8 | # This plugin queries a PostgreSQL database. It alerts when the numeric 9 | # result hits a threshold. Can optionally alert on the number of tuples 10 | # (rows) returned by the query. 11 | # 12 | # OUTPUT: 13 | # plain-text 14 | # 15 | # PLATFORMS: 16 | # Linux 17 | # 18 | # DEPENDENCIES: 19 | # gem: pg 20 | # gem: sensu-plugin 21 | # gem: dentaku 22 | # 23 | # USAGE: 24 | # check-postgres-query.rb -u db_user -p db_pass -h db_host -d db -q 'select foo from bar' -w 'value > 5' -c 'value > 10' 25 | # 26 | # NOTES: 27 | # 28 | # LICENSE: 29 | # Copyright 2015, Eric Heydrick 30 | # Released under the same terms as Sensu (the MIT license); see LICENSE 31 | # for details. 32 | # 33 | 34 | require 'sensu-plugins-postgres/pgpass' 35 | require 'sensu-plugin/check/cli' 36 | require 'pg' 37 | require 'dentaku' 38 | 39 | # Check PostgresSQL Query 40 | class CheckPostgresQuery < Sensu::Plugin::Check::CLI 41 | option :pgpass, 42 | description: 'Pgpass file', 43 | short: '-f FILE', 44 | long: '--pgpass', 45 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 46 | 47 | option :user, 48 | description: 'Postgres User', 49 | short: '-u USER', 50 | long: '--user USER' 51 | 52 | option :password, 53 | description: 'Postgres Password', 54 | short: '-p PASS', 55 | long: '--password PASS' 56 | 57 | option :hostname, 58 | description: 'Hostname to login to', 59 | short: '-h HOST', 60 | long: '--hostname HOST' 61 | 62 | option :port, 63 | description: 'Database port', 64 | short: '-P PORT', 65 | long: '--port PORT' 66 | 67 | option :database, 68 | description: 'Database name', 69 | short: '-d DB', 70 | long: '--db DB' 71 | 72 | option :query, 73 | description: 'Database query to execute', 74 | short: '-q QUERY', 75 | long: '--query QUERY', 76 | required: true 77 | 78 | option :regex_pattern, 79 | description: 'Regex pattern to match on query results and alert on if it does not match', 80 | short: '-r REGEX', 81 | long: '--regex-pattern REGEX' 82 | 83 | option :check_tuples, 84 | description: 'Check against the number of tuples (rows) returned by the query', 85 | short: '-t', 86 | long: '--tuples', 87 | boolean: true, 88 | default: false 89 | 90 | option :warning, 91 | description: 'Warning threshold expression', 92 | short: '-w WARNING', 93 | long: '--warning WARNING', 94 | default: nil 95 | 96 | option :critical, 97 | description: 'Critical threshold expression', 98 | short: '-c CRITICAL', 99 | long: '--critical CRITICAL', 100 | default: nil 101 | 102 | option :timeout, 103 | description: 'Connection timeout (seconds)', 104 | short: '-T TIMEOUT', 105 | long: '--timeout TIMEOUT', 106 | default: nil 107 | 108 | include Pgpass 109 | 110 | def run 111 | begin 112 | pgpass 113 | con = PG.connect(host: config[:hostname], 114 | dbname: config[:database], 115 | user: config[:user], 116 | password: config[:password], 117 | port: config[:port], 118 | connect_timeout: config[:timeout]) 119 | res = con.exec(config[:query].to_s) 120 | rescue PG::Error => e 121 | unknown "Unable to query PostgreSQL: #{e.message}" 122 | end 123 | 124 | value = if config[:check_tuples] 125 | res.ntuples 126 | else 127 | res.first.values.first.to_f 128 | end 129 | 130 | calc = Dentaku::Calculator.new 131 | if config[:critical] && calc.evaluate(config[:critical], value: value) 132 | critical "Results: #{res.values}" 133 | elsif config[:warning] && calc.evaluate(config[:warning], value: value) 134 | warning "Results: #{res.values}" 135 | elsif config[:regex_pattern] && (res.getvalue(0, 0) !~ /#{config[:regex_pattern]}/) 136 | critical "Query result #{res.getvalue(0, 0)} doesn't match configured regex #{config[:regex_pattern]}" 137 | else 138 | ok 'Query OK' 139 | end 140 | end 141 | end 142 | -------------------------------------------------------------------------------- /bin/check-postgres-replication.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # check-postgres-replication 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin checks postgresql replication lag 10 | # 11 | # OUTPUT: 12 | # plain text 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./check-postgres-replication.rb -m master_host -s slave_host -P port -d db -u db_user -p db_pass -w warn_threshold -c crit_threshold 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Released under the same terms as Sensu (the MIT license); see LICENSE 28 | # for details. 29 | # 30 | 31 | require 'sensu-plugins-postgres/pgpass' 32 | require 'sensu-plugins-postgres/pgutil' 33 | require 'sensu-plugin/check/cli' 34 | require 'pg' 35 | 36 | class CheckPostgresReplicationStatus < Sensu::Plugin::Check::CLI 37 | option :pgpass, 38 | description: 'Pgpass file', 39 | short: '-f FILE', 40 | long: '--pgpass', 41 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 42 | 43 | option(:master_host, 44 | short: '-m', 45 | long: '--master-host=HOST', 46 | required: true, 47 | description: 'PostgreSQL master HOST') 48 | 49 | option(:slave_host, 50 | short: '-s', 51 | long: '--slave-host=HOST', 52 | required: true, 53 | description: 'PostgreSQL slave HOST') 54 | 55 | option(:port, 56 | short: '-P', 57 | long: '--port=PORT', 58 | description: 'PostgreSQL port') 59 | 60 | option(:database, 61 | short: '-d', 62 | long: '--database=NAME', 63 | description: 'Database NAME') 64 | 65 | option(:user, 66 | short: '-u', 67 | long: '--user=USER', 68 | description: 'Database USER') 69 | 70 | option(:password, 71 | short: '-p', 72 | long: '--password=PASSWORD', 73 | description: 'Database PASSWORD') 74 | 75 | option(:ssl, 76 | short: '-S', 77 | long: '--ssl', 78 | boolean: true, 79 | description: 'Require SSL') 80 | 81 | option(:warn, 82 | short: '-w', 83 | long: '--warning=VALUE', 84 | description: 'Warning threshold for replication lag (in MB)', 85 | default: 900, 86 | # #YELLOW 87 | proc: lambda { |s| s.to_i }) # rubocop:disable Lambda 88 | 89 | option(:crit, 90 | short: '-c', 91 | long: '--critical=VALUE', 92 | description: 'Critical threshold for replication lag (in MB)', 93 | default: 1800, 94 | # #YELLOW 95 | proc: lambda { |s| s.to_i }) # rubocop:disable Lambda 96 | 97 | option(:timeout, 98 | short: '-T TIMEOUT', 99 | long: '--timeout=TIMEOUT', 100 | default: 2, 101 | description: 'Connection timeout (seconds)', 102 | proc: proc(&:to_i)) 103 | 104 | include Pgpass 105 | include PgUtil 106 | 107 | def run 108 | ssl_mode = config[:ssl] ? 'require' : 'prefer' 109 | 110 | critical 'Master and slave cannot be the same host' if config[:master_host] == config[:slave_host] 111 | 112 | # Establishing connection to the master 113 | pgpass 114 | conn_master = PG.connect(host: config[:master_host], 115 | dbname: config[:database], 116 | user: config[:user], 117 | password: config[:password], 118 | port: config[:port], 119 | sslmode: ssl_mode, 120 | connect_timeout: config[:timeout]) 121 | 122 | master = if check_vsn_newer_than_postgres9(conn_master) 123 | conn_master.exec('SELECT pg_current_xlog_location()').getvalue(0, 0) 124 | else 125 | conn_master.exec('SELECT pg_current_wal_lsn()').getvalue(0, 0) 126 | end 127 | m_segbytes = conn_master.exec('SHOW wal_segment_size').getvalue(0, 0).sub(/\D+/, '').to_i << 20 128 | conn_master.close 129 | 130 | # Establishing connection to the slave 131 | conn_slave = PG.connect(host: config[:slave_host], 132 | dbname: config[:database], 133 | user: config[:user], 134 | password: config[:password], 135 | port: config[:port], 136 | sslmode: ssl_mode, 137 | connect_timeout: config[:timeout]) 138 | 139 | slave = if check_vsn_newer_than_postgres9(conn_slave) 140 | conn_slave.exec('SELECT pg_last_xlog_receive_location()').getvalue(0, 0) 141 | else 142 | conn_slave.exec('SELECT pg_last_wal_replay_lsn()').getvalue(0, 0) 143 | end 144 | conn_slave.close 145 | 146 | # Computing lag 147 | lag = compute_lag(master, slave, m_segbytes) 148 | lag_in_mb = (lag.to_f / 1024 / 1024).abs 149 | 150 | message = "replication delayed by #{lag_in_mb}MB :: master:#{master} slave:#{slave} m_segbytes:#{m_segbytes}" 151 | 152 | if lag_in_mb >= config[:crit] 153 | critical message 154 | elsif lag_in_mb >= config[:warn] 155 | warning message 156 | else 157 | ok message 158 | end 159 | end 160 | end 161 | -------------------------------------------------------------------------------- /bin/metric-postgres-connections.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-connections 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres connection metrics 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-connections.rb -u db_user -p db_pass -h db_host -d db 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Copyright (c) 2012 Kwarter, Inc 28 | # Author Gilles Devaux 29 | # Released under the same terms as Sensu (the MIT license); see LICENSE 30 | # for details. 31 | # 32 | 33 | require 'sensu-plugins-postgres/pgpass' 34 | require 'sensu-plugin/metric/cli' 35 | require 'pg' 36 | require 'socket' 37 | 38 | class PostgresStatsDBMetrics < Sensu::Plugin::Metric::CLI::Graphite 39 | option :pgpass, 40 | description: 'Pgpass file', 41 | short: '-f FILE', 42 | long: '--pgpass', 43 | default: "#{ENV['HOME']}/.pgpass" 44 | 45 | option :user, 46 | description: 'Postgres User', 47 | short: '-u USER', 48 | long: '--user USER' 49 | 50 | option :password, 51 | description: 'Postgres Password', 52 | short: '-p PASS', 53 | long: '--password PASS' 54 | 55 | option :hostname, 56 | description: 'Hostname to login to', 57 | short: '-h HOST', 58 | long: '--hostname HOST' 59 | 60 | option :port, 61 | description: 'Database port', 62 | short: '-P PORT', 63 | long: '--port PORT' 64 | 65 | option :database, 66 | description: 'Database name', 67 | short: '-d DB', 68 | long: '--db DB' 69 | 70 | option :scheme, 71 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 72 | long: '--scheme SCHEME', 73 | default: "#{Socket.gethostname}.postgresql" 74 | 75 | option :timeout, 76 | description: 'Connection timeout (seconds)', 77 | short: '-T TIMEOUT', 78 | long: '--timeout TIMEOUT', 79 | default: nil 80 | 81 | include Pgpass 82 | 83 | def run 84 | timestamp = Time.now.to_i 85 | pgpass 86 | con = PG.connect(host: config[:hostname], 87 | dbname: config[:database], 88 | user: config[:user], 89 | password: config[:password], 90 | port: config[:port], 91 | connect_timeout: config[:timeout]) 92 | request = [ 93 | "select case when count(*) = 1 then 'waiting' else", 94 | "'case when wait_event_type is null then false else true end' end as wait_col", 95 | 'from information_schema.columns', 96 | "where table_name = 'pg_stat_activity' and table_schema = 'pg_catalog'", 97 | "and column_name = 'waiting'" 98 | ] 99 | wait_col = con.exec(request.join(' ')).first['wait_col'] 100 | 101 | request = [ 102 | "select count(*), #{wait_col} as waiting from pg_stat_activity", 103 | "where datname = '#{config[:database]}' group by #{wait_col}" 104 | ] 105 | 106 | metrics = { 107 | active: 0, 108 | waiting: 0, 109 | total: 0 110 | } 111 | con.exec(request.join(' ')) do |result| 112 | result.each do |row| 113 | if row['waiting'] == 't' 114 | metrics[:waiting] = row['count'] 115 | elsif row['waiting'] == 'f' 116 | metrics[:active] = row['count'] 117 | end 118 | end 119 | end 120 | 121 | metrics[:total] = (metrics[:waiting].to_i + metrics[:active].to_i) 122 | 123 | metrics.each do |metric, value| 124 | output "#{config[:scheme]}.connections.#{config[:database]}.#{metric}", value, timestamp 125 | end 126 | 127 | ok 128 | end 129 | end 130 | -------------------------------------------------------------------------------- /bin/metric-postgres-dbsize.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-dbsize 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres database size metrics 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-dbsize.rb -u db_user -p db_pass -h db_host -d db 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Copyright (c) 2012 Kwarter, Inc 28 | # Author Gilles Devaux 29 | # Released under the same terms as Sensu (the MIT license); see LICENSE 30 | # for details. 31 | # 32 | 33 | require 'sensu-plugins-postgres/pgpass' 34 | require 'sensu-plugin/metric/cli' 35 | require 'pg' 36 | require 'socket' 37 | 38 | class PostgresStatsDBMetrics < Sensu::Plugin::Metric::CLI::Graphite 39 | option :pgpass, 40 | description: 'Pgpass file', 41 | short: '-f FILE', 42 | long: '--pgpass', 43 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 44 | 45 | option :user, 46 | description: 'Postgres User', 47 | short: '-u USER', 48 | long: '--user USER' 49 | 50 | option :password, 51 | description: 'Postgres Password', 52 | short: '-p PASS', 53 | long: '--password PASS' 54 | 55 | option :hostname, 56 | description: 'Hostname to login to', 57 | short: '-h HOST', 58 | long: '--hostname HOST' 59 | 60 | option :port, 61 | description: 'Database port', 62 | short: '-P PORT', 63 | long: '--port PORT' 64 | 65 | option :database, 66 | description: 'Database name', 67 | short: '-d DB', 68 | long: '--db DB' 69 | 70 | option :scheme, 71 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 72 | long: '--scheme SCHEME', 73 | default: "#{Socket.gethostname}.postgresql" 74 | 75 | option :timeout, 76 | description: 'Connection timeout (seconds)', 77 | short: '-T TIMEOUT', 78 | long: '--timeout TIMEOUT', 79 | default: nil 80 | 81 | include Pgpass 82 | 83 | def run 84 | timestamp = Time.now.to_i 85 | pgpass 86 | con = PG.connect(host: config[:hostname], 87 | dbname: config[:database], 88 | user: config[:user], 89 | password: config[:password], 90 | port: config[:port], 91 | connect_timeout: config[:timeout]) 92 | request = [ 93 | "select pg_database_size('#{config[:database]}')" 94 | ] 95 | 96 | con.exec(request.join(' ')) do |result| 97 | result.each do |row| 98 | output "#{config[:scheme]}.size.#{config[:database]}", row['pg_database_size'], timestamp 99 | end 100 | end 101 | 102 | ok 103 | end 104 | end 105 | -------------------------------------------------------------------------------- /bin/metric-postgres-graphite.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-graphite 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres replication lag metrics 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-graphite.rb -m master_host -s slave_host -d db -u db_user -p db_pass 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Released under the same terms as Sensu (the MIT license); see LICENSE 28 | # for details. 29 | # 30 | 31 | require 'sensu-plugins-postgres/pgpass' 32 | require 'sensu-plugins-postgres/pgutil' 33 | require 'sensu-plugin/metric/cli' 34 | require 'pg' 35 | require 'socket' 36 | 37 | class CheckpostgresReplicationStatus < Sensu::Plugin::Metric::CLI::Graphite 38 | option :pgpass, 39 | description: 'Pgpass file', 40 | short: '-f FILE', 41 | long: '--pgpass', 42 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 43 | 44 | option :master_host, 45 | short: '-m', 46 | long: '--master=HOST', 47 | description: 'PostgreSQL master HOST' 48 | 49 | option :slave_host, 50 | short: '-s', 51 | long: '--slave=HOST', 52 | description: 'PostgreSQL slave HOST', 53 | default: 'localhost' 54 | 55 | option :database, 56 | short: '-d', 57 | long: '--database=NAME', 58 | description: 'Database NAME' 59 | 60 | option :user, 61 | short: '-u', 62 | long: '--username=VALUE', 63 | description: 'Database username' 64 | 65 | option :password, 66 | short: '-p', 67 | long: '--password=VALUE', 68 | description: 'Database password' 69 | 70 | option :ssl, 71 | short: '-S', 72 | long: '--ssl', 73 | boolean: true, 74 | description: 'Require SSL' 75 | 76 | option :scheme, 77 | description: 'Metric naming scheme, text to prepend to metric', 78 | short: '-g SCHEME', 79 | long: '--scheme SCHEME', 80 | default: "#{Socket.gethostname}.postgres.replication_lag" 81 | 82 | option :port, 83 | description: 'Database port', 84 | short: '-P PORT', 85 | long: '--port PORT' 86 | 87 | option :timeout, 88 | description: 'Connection timeout (seconds)', 89 | short: '-T TIMEOUT', 90 | long: '--timeout TIMEOUT', 91 | default: nil 92 | 93 | include Pgpass 94 | include PgUtil 95 | 96 | def run 97 | ssl_mode = config[:ssl] ? 'require' : 'prefer' 98 | 99 | # Establishing connections to the master 100 | pgpass 101 | conn_master = PG.connect(host: config[:master_host], 102 | dbname: config[:database], 103 | user: config[:user], 104 | password: config[:password], 105 | port: config[:port], 106 | sslmode: ssl_mode, 107 | connect_timeout: config[:timeout]) 108 | 109 | master = if check_vsn_newer_than_postgres9(conn_master) 110 | conn_master.exec('SELECT pg_current_xlog_location()').getvalue(0, 0) 111 | else 112 | conn_master.exec('SELECT pg_current_wal_lsn()').getvalue(0, 0) 113 | end 114 | m_segbytes = conn_master.exec('SHOW wal_segment_size').getvalue(0, 0).sub(/\D+/, '').to_i << 20 115 | conn_master.close 116 | 117 | # Establishing connections to the slave 118 | conn_slave = PG.connect(host: config[:slave_host], 119 | dbname: config[:database], 120 | user: config[:user], 121 | password: config[:password], 122 | port: config[:port], 123 | sslmode: ssl_mode, 124 | connect_timeout: config[:timeout]) 125 | 126 | slave = if check_vsn_newer_than_postgres9(conn_slave) 127 | conn_slave.exec('SELECT pg_last_xlog_receive_location()').getvalue(0, 0) 128 | else 129 | conn_slave.exec('SELECT pg_last_wal_replay_lsn()').getvalue(0, 0) 130 | end 131 | conn_slave.close 132 | 133 | # Compute lag 134 | lag = compute_lag(master, slave, m_segbytes) 135 | output config[:scheme].to_s, lag 136 | 137 | ok 138 | end 139 | end 140 | -------------------------------------------------------------------------------- /bin/metric-postgres-locks.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-locks 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres database lock metrics 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-locks.rb -u db_user -p db_pass -h db_host -d db 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Copyright (c) 2012 Kwarter, Inc 28 | # Author Gilles Devaux 29 | # Released under the same terms as Sensu (the MIT license); see LICENSE 30 | # for details. 31 | # 32 | 33 | require 'sensu-plugins-postgres/pgpass' 34 | require 'sensu-plugin/metric/cli' 35 | require 'pg' 36 | require 'socket' 37 | 38 | class PostgresStatsDBMetrics < Sensu::Plugin::Metric::CLI::Graphite 39 | option :pgpass, 40 | description: 'Pgpass file', 41 | short: '-f FILE', 42 | long: '--pgpass', 43 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 44 | 45 | option :user, 46 | description: 'Postgres User', 47 | short: '-u USER', 48 | long: '--user USER' 49 | 50 | option :password, 51 | description: 'Postgres Password', 52 | short: '-p PASS', 53 | long: '--password PASS' 54 | 55 | option :hostname, 56 | description: 'Hostname to login to', 57 | short: '-h HOST', 58 | long: '--hostname HOST' 59 | 60 | option :port, 61 | description: 'Database port', 62 | short: '-P PORT', 63 | long: '--port PORT' 64 | 65 | option :database, 66 | description: 'Database name', 67 | short: '-d DB', 68 | long: '--db DB' 69 | 70 | option :scheme, 71 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 72 | long: '--scheme SCHEME', 73 | default: "#{Socket.gethostname}.postgresql" 74 | 75 | option :timeout, 76 | description: 'Connection timeout (seconds)', 77 | short: '-T TIMEOUT', 78 | long: '--timeout TIMEOUT', 79 | default: nil 80 | 81 | include Pgpass 82 | 83 | def run 84 | timestamp = Time.now.to_i 85 | 86 | locks_per_type = Hash.new(0) 87 | pgpass 88 | con = PG.connect(host: config[:hostname], 89 | dbname: config[:database], 90 | user: config[:user], 91 | password: config[:password], 92 | port: config[:port], 93 | connect_timeout: config[:timeout]) 94 | request = [ 95 | 'SELECT mode, count(mode) AS count FROM pg_locks', 96 | "WHERE database = (SELECT oid FROM pg_database WHERE datname = '#{config[:database]}')", 97 | 'GROUP BY mode' 98 | ] 99 | 100 | con.exec(request.join(' ')) do |result| 101 | result.each do |row| 102 | lock_name = row['mode'].downcase.to_sym 103 | locks_per_type[lock_name] = row['count'] 104 | end 105 | end 106 | 107 | locks_per_type.each do |lock_type, count| 108 | output "#{config[:scheme]}.locks.#{config[:database]}.#{lock_type}", count, timestamp 109 | end 110 | 111 | ok 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /bin/metric-postgres-relation-size.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # metrics-postgres-relation-size.rb 5 | # DESCRIPTION: 6 | # 7 | # This plugin finds the total size of the largest tables. 8 | # 9 | # https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-relation-size.rb -u db_user -p db_pass -h db_host -d db 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Copyright (c) 2020 Airbrake Technologies, Inc 28 | # Author Patrick Humpal 29 | # Released under the same terms as Sensu (the MIT license); see LICENSE 30 | # for details. 31 | # 32 | 33 | require 'sensu-plugins-postgres/pgpass' 34 | require 'sensu-plugin/metric/cli' 35 | require 'pg' 36 | require 'socket' 37 | 38 | class PostgresStatsDBMetrics < Sensu::Plugin::Metric::CLI::Graphite 39 | option :pgpass, 40 | description: 'Pgpass file', 41 | short: '-f FILE', 42 | long: '--pgpass', 43 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 44 | 45 | option :user, 46 | description: 'Postgres User', 47 | short: '-u USER', 48 | long: '--user USER' 49 | 50 | option :password, 51 | description: 'Postgres Password', 52 | short: '-p PASS', 53 | long: '--password PASS' 54 | 55 | option :hostname, 56 | description: 'Hostname to login to', 57 | short: '-h HOST', 58 | long: '--hostname HOST' 59 | 60 | option :port, 61 | description: 'Database port', 62 | short: '-P PORT', 63 | long: '--port PORT' 64 | 65 | option :database, 66 | description: 'Database name', 67 | short: '-d DB', 68 | long: '--db DB' 69 | 70 | option :scheme, 71 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 72 | long: '--scheme SCHEME', 73 | default: "#{Socket.gethostname}.postgresql" 74 | 75 | option :timeout, 76 | description: 'Connection timeout (seconds)', 77 | short: '-T TIMEOUT', 78 | long: '--timeout TIMEOUT', 79 | default: nil 80 | 81 | option :limit, 82 | description: 'Limit query to this many results', 83 | short: '-L LIMIT', 84 | login: '--limit LIMIT', 85 | default: 25 86 | 87 | include Pgpass 88 | 89 | def run 90 | timestamp = Time.now.to_i 91 | pgpass 92 | con = PG.connect(host: config[:hostname], 93 | dbname: config[:database], 94 | user: config[:user], 95 | password: config[:password], 96 | port: config[:port], 97 | connect_timeout: config[:timeout]) 98 | 99 | # https://wiki.postgresql.org/wiki/Disk_Usage 100 | request = [ 101 | "SELECT nspname || '.' || relname AS relation, 102 | pg_total_relation_size(C.oid) AS total_size 103 | FROM pg_class C 104 | LEFT JOIN pg_namespace N on (N.oid = C.relnamespace) 105 | WHERE nspname NOT IN ('pg_catalog', 'information_schema') 106 | ORDER BY pg_total_relation_size(C.oid) DESC 107 | LIMIT '#{config[:limit]}'" 108 | ] 109 | 110 | con.exec(request.join(' ')) do |result| 111 | result.each do |row| 112 | output "#{config[:scheme]}.size.#{config[:database]}.#{row['relation']}", row['total_size'], timestamp 113 | end 114 | end 115 | 116 | ok 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /bin/metric-postgres-statsbgwriter.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-statsbgwriter 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres database bgwriter metrics 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-statsbgwriter.rb -u db_user -p db_pass -h db_host -d db 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Copyright (c) 2012 Kwarter, Inc 28 | # Author Gilles Devaux 29 | # Released under the same terms as Sensu (the MIT license); see LICENSE 30 | # for details. 31 | # 32 | 33 | require 'sensu-plugins-postgres/pgpass' 34 | require 'sensu-plugin/metric/cli' 35 | require 'pg' 36 | require 'socket' 37 | 38 | class PostgresStatsDBMetrics < Sensu::Plugin::Metric::CLI::Graphite 39 | option :pgpass, 40 | description: 'Pgpass file', 41 | short: '-f FILE', 42 | long: '--pgpass', 43 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 44 | 45 | option :user, 46 | description: 'Postgres User', 47 | short: '-u USER', 48 | long: '--user USER' 49 | 50 | option :password, 51 | description: 'Postgres Password', 52 | short: '-p PASS', 53 | long: '--password PASS' 54 | 55 | option :hostname, 56 | description: 'Hostname to login to', 57 | short: '-h HOST', 58 | long: '--hostname HOST' 59 | 60 | option :port, 61 | description: 'Database port', 62 | short: '-P PORT', 63 | long: '--port PORT' 64 | 65 | option :scheme, 66 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 67 | long: '--scheme SCHEME', 68 | default: "#{Socket.gethostname}.postgresql" 69 | 70 | option :timeout, 71 | description: 'Connection timeout (seconds)', 72 | short: '-T TIMEOUT', 73 | long: '--timeout TIMEOUT', 74 | default: nil 75 | 76 | include Pgpass 77 | 78 | def run 79 | timestamp = Time.now.to_i 80 | pgpass 81 | con = PG.connect(host: config[:hostname], 82 | dbname: 'postgres', 83 | user: config[:user], 84 | password: config[:password], 85 | port: config[:port], 86 | connect_timeout: config[:timeout]) 87 | request = [ 88 | 'select checkpoints_timed, checkpoints_req,', 89 | 'checkpoint_write_time, checkpoint_sync_time,', 90 | 'buffers_checkpoint, buffers_clean,', 91 | 'maxwritten_clean, buffers_backend, buffers_backend_fsync', 92 | 'buffers_alloc', 93 | 'from pg_stat_bgwriter' 94 | ] 95 | con.exec(request.join(' ')) do |result| 96 | result.each do |row| 97 | output "#{config[:scheme]}.bgwriter.checkpoints_timed", row['checkpoints_timed'], timestamp 98 | output "#{config[:scheme]}.bgwriter.checkpoints_req", row['checkpoints_req'], timestamp 99 | output "#{config[:scheme]}.bgwriter.checkpoints_write_time", row['checkpoint_write_time'], timestamp 100 | output "#{config[:scheme]}.bgwriter.checkpoints_sync_time", row['checkpoint_sync_time'], timestamp 101 | output "#{config[:scheme]}.bgwriter.buffers_checkpoint", row['buffers_checkpoint'], timestamp 102 | output "#{config[:scheme]}.bgwriter.buffers_clean", row['buffers_clean'], timestamp 103 | output "#{config[:scheme]}.bgwriter.maxwritten_clean", row['maxwritten_clean'], timestamp 104 | output "#{config[:scheme]}.bgwriter.buffers_backend", row['buffers_backend'], timestamp 105 | output "#{config[:scheme]}.bgwriter.buffers_backend_fsync", row['buffers_backend_fsync'], timestamp 106 | output "#{config[:scheme]}.bgwriter.buffers_alloc", row['buffers_alloc'], timestamp 107 | end 108 | end 109 | 110 | ok 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /bin/metric-postgres-statsdb.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-statsdb 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres database metrics from the pg_stat_database table 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-statsdb.rb -u db_user -p db_pass -h db_host -d db 23 | # 24 | # NOTES: 25 | # Requires PSQL `track_counts` `track_io_timing` for some metrics enabled 26 | # 27 | # LICENSE: 28 | # Copyright (c) 2012 Kwarter, Inc 29 | # Author Gilles Devaux 30 | # Released under the same terms as Sensu (the MIT license); see LICENSE 31 | # for details. 32 | # 33 | 34 | require 'sensu-plugins-postgres/pgpass' 35 | require 'sensu-plugin/metric/cli' 36 | require 'pg' 37 | require 'socket' 38 | 39 | class PostgresStatsDBMetrics < Sensu::Plugin::Metric::CLI::Graphite 40 | option :pgpass, 41 | description: 'Pgpass file', 42 | short: '-f FILE', 43 | long: '--pgpass', 44 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 45 | 46 | option :user, 47 | description: 'Postgres User', 48 | short: '-u USER', 49 | long: '--user USER' 50 | 51 | option :password, 52 | description: 'Postgres Password', 53 | short: '-p PASS', 54 | long: '--password PASS' 55 | 56 | option :hostname, 57 | description: 'Hostname to login to', 58 | short: '-h HOST', 59 | long: '--hostname HOST' 60 | 61 | option :port, 62 | description: 'Database port', 63 | short: '-P PORT', 64 | long: '--port PORT' 65 | 66 | option :database, 67 | description: 'Database to connect on', 68 | short: '-d DB', 69 | long: '--db DB', 70 | default: 'postgres' 71 | 72 | option :all_databases, 73 | description: 'Get stats for all available databases', 74 | short: '-a', 75 | long: '--all-databases', 76 | boolean: true, 77 | default: false 78 | 79 | option :scheme, 80 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 81 | long: '--scheme SCHEME', 82 | default: "#{Socket.gethostname}.postgresql" 83 | 84 | option :timeout, 85 | description: 'Connection timeout (seconds)', 86 | short: '-T TIMEOUT', 87 | long: '--timeout TIMEOUT', 88 | default: nil 89 | 90 | include Pgpass 91 | 92 | def run 93 | timestamp = Time.now.to_i 94 | pgpass 95 | con = PG.connect(host: config[:hostname], 96 | dbname: config[:database], 97 | user: config[:user], 98 | password: config[:password], 99 | port: config[:port], 100 | connect_timeout: config[:timeout]) 101 | 102 | query = 'SELECT * FROM pg_stat_database' 103 | params = [] 104 | unless config[:all_databases] 105 | query += ' WHERE datname = $1' 106 | params.push config[:database] 107 | end 108 | 109 | con.exec_params(query, params) do |result| 110 | result.each do |row| 111 | database = row['datname'] 112 | 113 | row.each do |key, value| 114 | next if %w[datid datname stats_reset].include?(key) 115 | 116 | output "#{config[:scheme]}.statsdb.#{database}.#{key}", value.to_s, timestamp 117 | end 118 | end 119 | end 120 | 121 | ok 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /bin/metric-postgres-statsio.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-statsio 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres database IO metrics 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-statsio.rb -u db_user -p db_pass -h db_host -d db -s scope 23 | # 24 | # NOTES: 25 | # Requires PSQL `track_io_timing` enabled 26 | # 27 | # LICENSE: 28 | # Copyright (c) 2012 Kwarter, Inc 29 | # Author Gilles Devaux 30 | # Released under the same terms as Sensu (the MIT license); see LICENSE 31 | # for details. 32 | # 33 | 34 | require 'sensu-plugins-postgres/pgpass' 35 | require 'sensu-plugin/metric/cli' 36 | require 'pg' 37 | require 'socket' 38 | 39 | class PostgresStatsIOMetrics < Sensu::Plugin::Metric::CLI::Graphite 40 | option :pgpass, 41 | description: 'Pgpass file', 42 | short: '-f FILE', 43 | long: '--pgpass', 44 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 45 | 46 | option :user, 47 | description: 'Postgres User', 48 | short: '-u USER', 49 | long: '--user USER' 50 | 51 | option :password, 52 | description: 'Postgres Password', 53 | short: '-p PASS', 54 | long: '--password PASS' 55 | 56 | option :hostname, 57 | description: 'Hostname to login to', 58 | short: '-h HOST', 59 | long: '--hostname HOST' 60 | 61 | option :port, 62 | description: 'Database port', 63 | short: '-P PORT', 64 | long: '--port PORT' 65 | 66 | option :database, 67 | description: 'Database name', 68 | short: '-d DB', 69 | long: '--db DB' 70 | 71 | option :scope, 72 | description: 'Scope, see http://www.postgresql.org/docs/9.2/static/monitoring-stats.html', 73 | short: '-s SCOPE', 74 | long: '--scope SCOPE', 75 | default: 'user' 76 | 77 | option :scheme, 78 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 79 | long: '--scheme SCHEME', 80 | default: "#{Socket.gethostname}.postgresql" 81 | 82 | option :timeout, 83 | description: 'Connection timeout (seconds)', 84 | short: '-T TIMEOUT', 85 | long: '--timeout TIMEOUT', 86 | default: nil 87 | 88 | include Pgpass 89 | 90 | def run 91 | timestamp = Time.now.to_i 92 | pgpass 93 | con = PG.connect(host: config[:hostname], 94 | dbname: config[:database], 95 | user: config[:user], 96 | password: config[:password], 97 | port: config[:port], 98 | connect_timeout: config[:timeout]) 99 | request = [ 100 | 'select sum(heap_blks_read) as heap_blks_read, sum(heap_blks_hit) as heap_blks_hit,', 101 | 'sum(idx_blks_read) as idx_blks_read, sum(idx_blks_hit) as idx_blks_hit,', 102 | 'sum(toast_blks_read) as toast_blks_read, sum(toast_blks_hit) as toast_blks_hit,', 103 | 'sum(tidx_blks_read) as tidx_blks_read, sum(tidx_blks_hit) as tidx_blks_hit', 104 | "from pg_statio_#{config[:scope]}_tables" 105 | ] 106 | con.exec(request.join(' ')) do |result| 107 | result.each do |row| 108 | output "#{config[:scheme]}.statsio.#{config[:database]}.heap_blks_read", row['heap_blks_read'], timestamp 109 | output "#{config[:scheme]}.statsio.#{config[:database]}.heap_blks_hit", row['heap_blks_hit'], timestamp 110 | output "#{config[:scheme]}.statsio.#{config[:database]}.idx_blks_read", row['idx_blks_read'], timestamp 111 | output "#{config[:scheme]}.statsio.#{config[:database]}.idx_blks_hit", row['idx_blks_hit'], timestamp 112 | output "#{config[:scheme]}.statsio.#{config[:database]}.toast_blks_read", row['toast_blks_read'], timestamp 113 | output "#{config[:scheme]}.statsio.#{config[:database]}.toast_blks_hit", row['toast_blks_hit'], timestamp 114 | output "#{config[:scheme]}.statsio.#{config[:database]}.tidx_blks_read", row['tidx_blks_read'], timestamp 115 | output "#{config[:scheme]}.statsio.#{config[:database]}.tidx_blks_hit", row['tidx_blks_hit'], timestamp 116 | end 117 | end 118 | 119 | ok 120 | end 121 | end 122 | -------------------------------------------------------------------------------- /bin/metric-postgres-statstable.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metric-postgres-statstable 6 | # 7 | # DESCRIPTION: 8 | # 9 | # This plugin collects postgres database metrics from the pg_stat tables 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: sensu-plugin 19 | # gem: pg 20 | # 21 | # USAGE: 22 | # ./metric-postgres-statstable.rb -u db_user -p db_pass -h db_host -d db -s scope 23 | # 24 | # NOTES: 25 | # Requires PSQL `track_counts` enabled 26 | # 27 | # LICENSE: 28 | # Copyright (c) 2012 Kwarter, Inc 29 | # Author Gilles Devaux 30 | # Released under the same terms as Sensu (the MIT license); see LICENSE 31 | # for details. 32 | # 33 | 34 | require 'sensu-plugins-postgres/pgpass' 35 | require 'sensu-plugin/metric/cli' 36 | require 'pg' 37 | require 'socket' 38 | 39 | class PostgresStatsTableMetrics < Sensu::Plugin::Metric::CLI::Graphite 40 | option :pgpass, 41 | description: 'Pgpass file', 42 | short: '-f FILE', 43 | long: '--pgpass', 44 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 45 | 46 | option :user, 47 | description: 'Postgres User', 48 | short: '-u USER', 49 | long: '--user USER' 50 | 51 | option :password, 52 | description: 'Postgres Password', 53 | short: '-p PASS', 54 | long: '--password PASS' 55 | 56 | option :hostname, 57 | description: 'Hostname to login to', 58 | short: '-h HOST', 59 | long: '--hostname HOST' 60 | 61 | option :port, 62 | description: 'Database port', 63 | short: '-P PORT', 64 | long: '--port PORT' 65 | 66 | option :database, 67 | description: 'Database name', 68 | short: '-d DB', 69 | long: '--db DB' 70 | 71 | option :scope, 72 | description: 'Scope, see http://www.postgresql.org/docs/9.2/static/monitoring-stats.html', 73 | short: '-s SCOPE', 74 | long: '--scope SCOPE', 75 | default: 'user' 76 | 77 | option :scheme, 78 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 79 | long: '--scheme SCHEME', 80 | default: "#{Socket.gethostname}.postgresql" 81 | 82 | option :timeout, 83 | description: 'Connection timeout (seconds)', 84 | short: '-T TIMEOUT', 85 | long: '--timeout TIMEOUT', 86 | default: nil 87 | 88 | include Pgpass 89 | 90 | def run 91 | timestamp = Time.now.to_i 92 | pgpass 93 | con = PG.connect(host: config[:hostname], 94 | dbname: config[:database], 95 | user: config[:user], 96 | password: config[:password], 97 | port: config[:port], 98 | connect_timeout: config[:timeout]) 99 | request = [ 100 | 'select sum(seq_scan) as seq_scan, sum(seq_tup_read) as seq_tup_read,', 101 | 'sum(idx_scan) as idx_scan, sum(idx_tup_fetch) as idx_tup_fetch,', 102 | 'sum(n_tup_ins) as n_tup_ins, sum(n_tup_upd) as n_tup_upd, sum(n_tup_del) as n_tup_del,', 103 | 'sum(n_tup_hot_upd) as n_tup_hot_upd, sum(n_live_tup) as n_live_tup, sum(n_dead_tup) as n_dead_tup', 104 | "from pg_stat_#{config[:scope]}_tables" 105 | ] 106 | con.exec(request.join(' ')) do |result| 107 | result.each do |row| 108 | output "#{config[:scheme]}.statstable.#{config[:database]}.seq_scan", row['seq_scan'], timestamp 109 | output "#{config[:scheme]}.statstable.#{config[:database]}.seq_tup_read", row['seq_tup_read'], timestamp 110 | output "#{config[:scheme]}.statstable.#{config[:database]}.idx_scan", row['idx_scan'], timestamp 111 | output "#{config[:scheme]}.statstable.#{config[:database]}.idx_tup_fetch", row['idx_tup_fetch'], timestamp 112 | output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_ins", row['n_tup_ins'], timestamp 113 | output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_upd", row['n_tup_upd'], timestamp 114 | output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_del", row['n_tup_del'], timestamp 115 | output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_hot_upd", row['n_tup_hot_upd'], timestamp 116 | output "#{config[:scheme]}.statstable.#{config[:database]}.n_live_tup", row['n_live_tup'], timestamp 117 | output "#{config[:scheme]}.statstable.#{config[:database]}.n_dead_tup", row['n_dead_tup'], timestamp 118 | end 119 | end 120 | 121 | ok 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /bin/metric-postgres-vaccum.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # DEPENDENCIES: 5 | # gem: sensu-plugin 6 | # gem: pg 7 | # 8 | # USAGE: 9 | # ./metric-postgres-vaccum.rb -u db_user -p db_pass -h db_host -d db 10 | # 11 | # NOTES: 12 | # Requires PSQL `track_counts` `track_io_timing` for some metrics enabled 13 | # 14 | # LICENSE: 15 | # Copyright (c) 2020 Airbrake Technologies, Inc 16 | # Author Patrick Humpal 17 | # Released under the same terms as Sensu (the MIT license); see LICENSE 18 | # for details. 19 | # 20 | 21 | require 'sensu-plugins-postgres/pgpass' 22 | require 'sensu-plugin/metric/cli' 23 | require 'pg' 24 | require 'socket' 25 | 26 | class PostgresVacuumDBMetrics < Sensu::Plugin::Metric::CLI::Graphite 27 | option :pgpass, 28 | description: 'Pgpass file', 29 | short: '-f FILE', 30 | long: '--pgpass', 31 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 32 | 33 | option :user, 34 | description: 'Postgres User', 35 | short: '-u USER', 36 | long: '--user USER' 37 | 38 | option :password, 39 | description: 'Postgres Password', 40 | short: '-p PASS', 41 | long: '--password PASS' 42 | 43 | option :hostname, 44 | description: 'Hostname to login to', 45 | short: '-h HOST', 46 | long: '--hostname HOST' 47 | 48 | option :port, 49 | description: 'Database port', 50 | short: '-P PORT', 51 | long: '--port PORT' 52 | 53 | option :database, 54 | description: 'Database to connect on', 55 | short: '-d DB', 56 | long: '--db DB', 57 | default: 'postgres' 58 | 59 | option :all_databases, 60 | description: 'Get stats for all available databases', 61 | short: '-a', 62 | long: '--all-databases', 63 | boolean: true, 64 | default: false 65 | 66 | option :scheme, 67 | description: 'Metric naming scheme, text to prepend to $queue_name.$metric', 68 | long: '--scheme SCHEME', 69 | default: "#{Socket.gethostname}.postgresql" 70 | 71 | option :timeout, 72 | description: 'Connection timeout (seconds)', 73 | short: '-T TIMEOUT', 74 | long: '--timeout TIMEOUT', 75 | default: nil 76 | 77 | include Pgpass 78 | 79 | def phase_mapping(vacuum_phase) 80 | ['initializing', 81 | 'scanning heap', 82 | 'vacuuming indexes', 83 | 'vacuuming heap', 84 | 'cleaning up indexes', 85 | 'truncating heap', 86 | 'performing final cleanup'].find_index(vacuum_phase) 87 | end 88 | 89 | def run 90 | timestamp = Time.now.to_i 91 | pgpass 92 | con = PG.connect(host: config[:hostname], 93 | dbname: config[:database], 94 | user: config[:user], 95 | password: config[:password], 96 | port: config[:port], 97 | connect_timeout: config[:timeout]) 98 | 99 | query = 'SELECT * FROM pg_stat_progress_vacuum' 100 | params = [] 101 | unless config[:all_databases] 102 | query += ' WHERE datname = $1' 103 | params.push config[:database] 104 | end 105 | 106 | con.exec_params(query, params) do |result| 107 | result.each do |row| 108 | database = row['datname'] 109 | 110 | row.each do |key, value| 111 | next if %w[datid datname].include?(key) 112 | 113 | if key == 'phase' 114 | output "#{config[:scheme]}.vacuum.#{database}.phase", phase_mapping(value).to_s, timestamp 115 | else 116 | output "#{config[:scheme]}.vacuum.#{database}.#{key}", value.to_s, timestamp 117 | end 118 | end 119 | end 120 | end 121 | 122 | ok 123 | end 124 | end 125 | -------------------------------------------------------------------------------- /bin/metrics-postgres-query.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | # frozen_string_literal: false 3 | 4 | # 5 | # metrics-postgres-query 6 | # 7 | # DESCRIPTION: 8 | # This plugin collects metrics from the results of a postgres query. Can optionally 9 | # count the number of tuples (rows) returned by the query. 10 | # 11 | # OUTPUT: 12 | # metric data 13 | # 14 | # PLATFORMS: 15 | # Linux 16 | # 17 | # DEPENDENCIES: 18 | # gem: pg 19 | # gem: sensu-plugin 20 | # 21 | # USAGE: 22 | # metrics-postgres-query.rb -u db_user -p db_pass -h db_server -d db -q 'select foo from bar' 23 | # 24 | # NOTES: 25 | # 26 | # LICENSE: 27 | # Copyright 2015, Eric Heydrick 28 | # Released under the same terms as Sensu (the MIT license); see LICENSE 29 | # for details. 30 | # 31 | 32 | require 'sensu-plugins-postgres/pgpass' 33 | require 'sensu-plugin/metric/cli' 34 | require 'pg' 35 | 36 | class MetricsPostgresQuery < Sensu::Plugin::Metric::CLI::Graphite 37 | option :pgpass, 38 | description: 'Pgpass file', 39 | short: '-f FILE', 40 | long: '--pgpass', 41 | default: ENV['PGPASSFILE'] || "#{ENV['HOME']}/.pgpass" 42 | 43 | option :user, 44 | description: 'Postgres User', 45 | short: '-u USER', 46 | long: '--user USER' 47 | 48 | option :password, 49 | description: 'Postgres Password', 50 | short: '-p PASS', 51 | long: '--password PASS' 52 | 53 | option :hostname, 54 | description: 'Hostname to login to', 55 | short: '-h HOST', 56 | long: '--hostname HOST' 57 | 58 | option :port, 59 | description: 'Database port', 60 | short: '-P PORT', 61 | long: '--port PORT' 62 | 63 | option :database, 64 | description: 'Database name', 65 | short: '-d DB', 66 | long: '--db DB' 67 | 68 | option :query, 69 | description: 'Database query to execute', 70 | short: '-q QUERY', 71 | long: '--query QUERY', 72 | required: true 73 | 74 | option :count_tuples, 75 | description: 'Count the number of tuples (rows) returned by the query', 76 | short: '-t', 77 | long: '--tuples', 78 | boolean: true, 79 | default: false 80 | 81 | option :scheme, 82 | description: 'Metric naming scheme, text to prepend to metric', 83 | short: '-s SCHEME', 84 | long: '--scheme SCHEME', 85 | default: 'postgres' 86 | 87 | option :multirow, 88 | description: 'Determines if we return first row or all rows', 89 | short: '-m', 90 | long: '--multirow', 91 | boolean: true, 92 | default: false 93 | 94 | option :timeout, 95 | description: 'Connection timeout (seconds)', 96 | short: '-T TIMEOUT', 97 | long: '--timeout TIMEOUT', 98 | default: nil 99 | 100 | include Pgpass 101 | 102 | def run 103 | begin 104 | pgpass 105 | con = PG.connect(host: config[:hostname], 106 | dbname: config[:database], 107 | user: config[:user], 108 | password: config[:password], 109 | port: config[:port], 110 | connect_timeout: config[:timeout]) 111 | res = con.exec(config[:query].to_s) 112 | rescue PG::Error => e 113 | unknown "Unable to query PostgreSQL: #{e.message}" 114 | end 115 | 116 | value = if config[:count_tuples] 117 | res.ntuples 118 | else 119 | res.first&.values&.first 120 | end 121 | 122 | if config[:multirow] && !config[:count_tuples] 123 | res.values.each do |row| 124 | output "#{config[:scheme]}.#{row[0]}", row[1] 125 | end 126 | else 127 | output config[:scheme], value 128 | end 129 | ok 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /lib/sensu-plugins-postgres.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'sensu-plugins-postgres/version' 4 | require 'sensu-plugins-postgres/pgpass' 5 | -------------------------------------------------------------------------------- /lib/sensu-plugins-postgres/pgpass.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpass 4 | def read_pgpass(pg_pass_file) 5 | File.readlines(pg_pass_file).each do |line| 6 | return line.strip.split(':') unless line.start_with?('#') 7 | 8 | next 9 | end 10 | end 11 | 12 | def pgpass 13 | if File.file?(config[:pgpass]) 14 | pgpass = Hash[%i[hostname port database user password].zip(read_pgpass(config[:pgpass]))] 15 | pgpass[:database] = nil if pgpass[:database] == '*' 16 | pgpass.each do |k, v| 17 | config[k] ||= v 18 | end 19 | else 20 | config[:hostname] ||= ENV['PGHOST'] || 'localhost' 21 | config[:port] ||= ENV['PGPORT'] || 5432 22 | config[:database] ||= ENV['PGDATABASE'] || 'postgres' 23 | config[:user] ||= ENV['PGUSER'] || 'postgres' 24 | config[:password] ||= ENV['PGPASSWORD'] 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/sensu-plugins-postgres/pgutil.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module PgUtil 4 | def check_vsn_newer_than_postgres9(conn) 5 | pg_vsn = conn.exec("SELECT current_setting('server_version')").getvalue(0, 0) 6 | pg_vsn = pg_vsn.split(' ')[0] 7 | Gem::Version.new(pg_vsn) < Gem::Version.new('10.0') && Gem::Version.new(pg_vsn) >= Gem::Version.new('9.0') 8 | end 9 | 10 | def compute_lag(master, slave, m_segbytes) 11 | m_segment, m_offset = master.split('/') 12 | s_segment, s_offset = slave.split('/') 13 | ((m_segment.hex - s_segment.hex) * m_segbytes) + (m_offset.hex - s_offset.hex) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/sensu-plugins-postgres/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module SensuPluginsPostgres 4 | module Version 5 | MAJOR = 4 6 | MINOR = 3 7 | PATCH = 0 8 | 9 | VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.') 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /sensu-plugins-postgres.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | 6 | require 'date' 7 | require_relative 'lib/sensu-plugins-postgres' 8 | 9 | Gem::Specification.new do |s| 10 | s.authors = ['Sensu-Plugins and contributors'] 11 | 12 | s.date = Date.today.to_s 13 | s.description = 'This plugin provides native PostgreSQL 14 | instrumentation for monitoring and metrics 15 | collection, including: service health, database 16 | connectivity, database locks, replication status, 17 | database size, `pg_stat_bgwriter` metrics, and 18 | more.' 19 | s.email = '' 20 | s.executables = Dir.glob('bin/**/*.rb').map { |file| File.basename(file) } 21 | s.files = Dir.glob('{bin,lib}/**/*') + %w[LICENSE README.md CHANGELOG.md] 22 | s.homepage = 'https://github.com/sensu-plugins/sensu-plugins-postgres' 23 | s.license = 'MIT' 24 | s.metadata = { 'maintainer' => 'sensu-plugin', 25 | 'development_status' => 'active', 26 | 'production_status' => 'unstable - testing recommended', 27 | 'release_draft' => 'false', 28 | 'release_prerelease' => 'false' } 29 | s.name = 'sensu-plugins-postgres' 30 | s.platform = Gem::Platform::RUBY 31 | s.post_install_message = 'You can use the embedded Ruby by setting EMBEDDED_RUBY=true in /etc/default/sensu' 32 | s.require_paths = ['lib'] 33 | s.required_ruby_version = '>= 2.4.0' 34 | 35 | s.summary = 'Sensu plugins for postgres' 36 | s.test_files = s.files.grep(%r{^(test|spec|features)/}) 37 | s.version = SensuPluginsPostgres::Version::VER_STRING 38 | 39 | s.add_runtime_dependency 'sensu-plugin', '~> 4.0' 40 | 41 | s.add_runtime_dependency 'dentaku', '3.4.2' 42 | s.add_runtime_dependency 'pg', '1.2.3' 43 | 44 | s.add_development_dependency 'bundler', '~> 2.1' 45 | s.add_development_dependency 'codeclimate-test-reporter', '~> 1.0' 46 | s.add_development_dependency 'github-markup', '~> 4.0' 47 | s.add_development_dependency 'kitchen-docker', '~> 2.6' 48 | s.add_development_dependency 'kitchen-localhost', '~> 0.3' 49 | s.add_development_dependency 'mixlib-shellout', '~> 2.4' 50 | s.add_development_dependency 'pry', '~> 0.10' 51 | s.add_development_dependency 'rake', '~> 13.0' 52 | s.add_development_dependency 'redcarpet', '~> 3.2' 53 | s.add_development_dependency 'rspec', '~> 3.1' 54 | s.add_development_dependency 'rubocop', '~> 0.79.0' 55 | s.add_development_dependency 'serverspec', '~> 2.41.5' 56 | s.add_development_dependency 'test-kitchen', '~> 1.25.0' 57 | s.add_development_dependency 'yard', '~> 0.9.11' 58 | end 59 | -------------------------------------------------------------------------------- /test/fixtures/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Set up a super simple web server and make it accept GET and POST requests 4 | # for Sensu plugin testing. 5 | # 6 | 7 | set -e 8 | 9 | # base utilities that need to exist to start bootatraping 10 | apt-get update 11 | apt-get install -y wget 12 | 13 | # setup the rubies 14 | source /etc/profile 15 | DATA_DIR=/tmp/kitchen/data 16 | RUBY_HOME=${MY_RUBY_HOME} 17 | 18 | # setup a .pgpass file 19 | cat << EOF > /tmp/.pgpass 20 | # This is a comment 21 | *:5432:*:postgres: 22 | EOF 23 | 24 | # Start bootatraping 25 | 26 | ## install some required deps for pg_gem to install 27 | apt-get install -y libpq-dev build-essential 28 | 29 | # setup postgres server 30 | ## TODO: multiple postgres versions and replication the versions should probably 31 | ## be matrixed but wanted to start as small as possible initially. 32 | 33 | 34 | # End of Actual bootatrap 35 | 36 | # Install gems 37 | cd $DATA_DIR 38 | SIGN_GEM=false gem build sensu-plugins-postgres.gemspec 39 | gem install sensu-plugins-postgres-*.gem 40 | -------------------------------------------------------------------------------- /test/integration/helpers/serverspec/check-postgres-alive-shared_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'shared_spec' 5 | 6 | gem_path = '/usr/local/bin' 7 | check_name = 'check-postgres-alive.rb' 8 | check = "#{gem_path}/#{check_name}" 9 | pg_user = 'postgres' 10 | pg_password = '' 11 | # TODO: fix up the hostname to be pulled in via the suite based on the version being tested 12 | pg_host = 'sensu-postgres-10' 13 | 14 | describe 'ruby environment' do 15 | it_behaves_like 'ruby checks', check 16 | end 17 | 18 | # NOTE: This ia a TERRIBLE idea and you should never specify a cleartext 19 | # password on the cli like this. you should use the pgpass or sensu tokens: 20 | # https://sensuapp.org/docs/1.1/reference/checks.html#check-token-substitution 21 | # do not use this method for anything but testing. 22 | describe command("#{check} --user #{pg_user} --password \'#{pg_password}\' --hostname #{pg_host}") do 23 | its(:exit_status) { should eq 0 } 24 | its(:stdout) { should match(/CheckPostgres OK: Server version: {"version"=>"PostgreSQL/) } 25 | end 26 | 27 | describe command("#{check} --hostname #{pg_host} --pgpass /tmp/.pgpass") do 28 | its(:exit_status) { should eq 0 } 29 | its(:stdout) { should match(/CheckPostgres OK: Server version: {"version"=>"PostgreSQL/) } 30 | end 31 | -------------------------------------------------------------------------------- /test/integration/helpers/serverspec/shared_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | shared_examples_for 'ruby checks' do |check| 6 | describe command('which ruby') do 7 | its(:exit_status) { should eq 0 } 8 | its(:stdout) { should match(/\/usr\/local\/bin\/ruby/) } 9 | end 10 | 11 | describe command('which gem') do 12 | its(:exit_status) { should eq 0 } 13 | its(:stdout) { should match(/\/usr\/local\/bin\/gem/) } 14 | end 15 | 16 | describe command("which #{check}") do 17 | its(:exit_status) { should eq 0 } 18 | its(:stdout) { should match(Regexp.new(Regexp.escape(check))) } 19 | end 20 | 21 | describe file(check) do 22 | it { should be_file } 23 | it { should be_executable } 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /test/integration/helpers/serverspec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'serverspec' 4 | 5 | set :backend, :exec 6 | -------------------------------------------------------------------------------- /test/integration/ruby-21/serverspec/default_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'shared_spec' 5 | -------------------------------------------------------------------------------- /test/integration/ruby-22/serverspec/default_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'shared_spec' 5 | -------------------------------------------------------------------------------- /test/integration/ruby-230/serverspec/default_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'shared_spec' 5 | -------------------------------------------------------------------------------- /test/integration/ruby-241/serverspec/default_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'shared_spec' 5 | -------------------------------------------------------------------------------- /test/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'codeclimate-test-reporter' 4 | CodeClimate::TestReporter.start 5 | 6 | RSpec.configure do |c| 7 | c.formatter = :documentation 8 | c.color = true 9 | end 10 | --------------------------------------------------------------------------------