sensu-plugins-postgres-mrtrotl 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,142 @@
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 <eheydrick@gmail.com>
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: 10,
107
+ proc: proc(&:to_i)
108
+
109
+ include Pgpass
110
+
111
+ def run
112
+ begin
113
+ pgpass
114
+ con = PG.connect(host: config[:hostname],
115
+ dbname: config[:database],
116
+ user: config[:user],
117
+ password: config[:password],
118
+ port: config[:port],
119
+ connect_timeout: config[:timeout])
120
+ res = con.exec(config[:query].to_s)
121
+ rescue PG::Error => e
122
+ unknown "Unable to query PostgreSQL: #{e.message}"
123
+ end
124
+
125
+ value = if config[:check_tuples]
126
+ res.ntuples
127
+ else
128
+ res.first.values.first.to_f
129
+ end
130
+
131
+ calc = Dentaku::Calculator.new
132
+ if config[:critical] && calc.evaluate(config[:critical], value: value)
133
+ critical "Results: #{res.values}"
134
+ elsif config[:warning] && calc.evaluate(config[:warning], value: value)
135
+ warning "Results: #{res.values}"
136
+ elsif config[:regex_pattern] && (res.getvalue(0, 0) !~ /#{config[:regex_pattern]}/)
137
+ critical "Query result #{res.getvalue(0, 0)} doesn't match configured regex #{config[:regex_pattern]}"
138
+ else
139
+ ok 'Query OK'
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,160 @@
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: 10,
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
@@ -0,0 +1,130 @@
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 <platforms@kwarter.com>
28
+ # Author Gilles Devaux <gilles.devaux@gmail.com>
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: 10,
80
+ proc: proc(&:to_i)
81
+
82
+ include Pgpass
83
+
84
+ def run
85
+ timestamp = Time.now.to_i
86
+ pgpass
87
+ con = PG.connect(host: config[:hostname],
88
+ dbname: config[:database],
89
+ user: config[:user],
90
+ password: config[:password],
91
+ port: config[:port],
92
+ connect_timeout: config[:timeout])
93
+ request = [
94
+ "select case when count(*) = 1 then 'waiting' else",
95
+ "'case when wait_event_type is null then false else true end' end as wait_col",
96
+ 'from information_schema.columns',
97
+ "where table_name = 'pg_stat_activity' and table_schema = 'pg_catalog'",
98
+ "and column_name = 'waiting'"
99
+ ]
100
+ wait_col = con.exec(request.join(' ')).first['wait_col']
101
+
102
+ request = [
103
+ "select count(*), #{wait_col} as waiting from pg_stat_activity",
104
+ "where datname = '#{config[:database]}' group by #{wait_col}"
105
+ ]
106
+
107
+ metrics = {
108
+ active: 0,
109
+ waiting: 0,
110
+ total: 0
111
+ }
112
+ con.exec(request.join(' ')) do |result|
113
+ result.each do |row|
114
+ if row['waiting'] == 't'
115
+ metrics[:waiting] = row['count']
116
+ elsif row['waiting'] == 'f'
117
+ metrics[:active] = row['count']
118
+ end
119
+ end
120
+ end
121
+
122
+ metrics[:total] = (metrics[:waiting].to_i + metrics[:active].to_i)
123
+
124
+ metrics.each do |metric, value|
125
+ output "#{config[:scheme]}.connections.#{config[:database]}.#{metric}", value, timestamp
126
+ end
127
+
128
+ ok
129
+ end
130
+ end
@@ -0,0 +1,105 @@
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 <platforms@kwarter.com>
28
+ # Author Gilles Devaux <gilles.devaux@gmail.com>
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: 10,
80
+ proc: proc(&:to_i)
81
+
82
+ include Pgpass
83
+
84
+ def run
85
+ timestamp = Time.now.to_i
86
+ pgpass
87
+ con = PG.connect(host: config[:hostname],
88
+ dbname: config[:database],
89
+ user: config[:user],
90
+ password: config[:password],
91
+ port: config[:port],
92
+ connect_timeout: config[:timeout])
93
+ request = [
94
+ "select pg_database_size('#{config[:database]}')"
95
+ ]
96
+
97
+ con.exec(request.join(' ')) do |result|
98
+ result.each do |row|
99
+ output "#{config[:scheme]}.size.#{config[:database]}", row['pg_database_size'], timestamp
100
+ end
101
+ end
102
+
103
+ ok
104
+ end
105
+ end
@@ -0,0 +1,140 @@
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: 10,
92
+ proc: proc(&:to_i)
93
+
94
+ include Pgpass
95
+ include PgUtil
96
+
97
+ def run
98
+ ssl_mode = config[:ssl] ? 'require' : 'prefer'
99
+
100
+ # Establishing connections to the master
101
+ pgpass
102
+ conn_master = PG.connect(host: config[:master_host],
103
+ dbname: config[:database],
104
+ user: config[:user],
105
+ password: config[:password],
106
+ port: config[:port],
107
+ sslmode: ssl_mode,
108
+ connect_timeout: config[:timeout])
109
+
110
+ master = if check_vsn_newer_than_postgres9(conn_master)
111
+ conn_master.exec('SELECT pg_current_xlog_location()').getvalue(0, 0)
112
+ else
113
+ conn_master.exec('SELECT pg_current_wal_lsn()').getvalue(0, 0)
114
+ end
115
+ m_segbytes = conn_master.exec('SHOW wal_segment_size').getvalue(0, 0).sub(/\D+/, '').to_i << 20
116
+ conn_master.close
117
+
118
+ # Establishing connections to the slave
119
+ conn_slave = PG.connect(host: config[:slave_host],
120
+ dbname: config[:database],
121
+ user: config[:user],
122
+ password: config[:password],
123
+ port: config[:port],
124
+ sslmode: ssl_mode,
125
+ connect_timeout: config[:timeout])
126
+
127
+ slave = if check_vsn_newer_than_postgres9(conn_slave)
128
+ conn_slave.exec('SELECT pg_last_xlog_receive_location()').getvalue(0, 0)
129
+ else
130
+ conn_slave.exec('SELECT pg_last_wal_replay_lsn()').getvalue(0, 0)
131
+ end
132
+ conn_slave.close
133
+
134
+ # Compute lag
135
+ lag = compute_lag(master, slave, m_segbytes)
136
+ output config[:scheme].to_s, lag
137
+
138
+ ok
139
+ end
140
+ end