sensu-plugins-postgres-mrtrotl 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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