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,124 @@
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 <platforms@kwarter.com>
29
+ # Author Gilles Devaux <gilles.devaux@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/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: 10,
87
+ proc: proc(&:to_i)
88
+
89
+ include Pgpass
90
+
91
+ def run
92
+ timestamp = Time.now.to_i
93
+ pgpass
94
+ con = PG.connect(host: config[:hostname],
95
+ dbname: config[:database],
96
+ user: config[:user],
97
+ password: config[:password],
98
+ port: config[:port],
99
+ connect_timeout: config[:timeout])
100
+ request = [
101
+ 'select sum(seq_scan) as seq_scan, sum(seq_tup_read) as seq_tup_read,',
102
+ 'sum(idx_scan) as idx_scan, sum(idx_tup_fetch) as idx_tup_fetch,',
103
+ 'sum(n_tup_ins) as n_tup_ins, sum(n_tup_upd) as n_tup_upd, sum(n_tup_del) as n_tup_del,',
104
+ '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',
105
+ "from pg_stat_#{config[:scope]}_tables"
106
+ ]
107
+ con.exec(request.join(' ')) do |result|
108
+ result.each do |row|
109
+ output "#{config[:scheme]}.statstable.#{config[:database]}.seq_scan", row['seq_scan'], timestamp
110
+ output "#{config[:scheme]}.statstable.#{config[:database]}.seq_tup_read", row['seq_tup_read'], timestamp
111
+ output "#{config[:scheme]}.statstable.#{config[:database]}.idx_scan", row['idx_scan'], timestamp
112
+ output "#{config[:scheme]}.statstable.#{config[:database]}.idx_tup_fetch", row['idx_tup_fetch'], timestamp
113
+ output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_ins", row['n_tup_ins'], timestamp
114
+ output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_upd", row['n_tup_upd'], timestamp
115
+ output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_del", row['n_tup_del'], timestamp
116
+ output "#{config[:scheme]}.statstable.#{config[:database]}.n_tup_hot_upd", row['n_tup_hot_upd'], timestamp
117
+ output "#{config[:scheme]}.statstable.#{config[:database]}.n_live_tup", row['n_live_tup'], timestamp
118
+ output "#{config[:scheme]}.statstable.#{config[:database]}.n_dead_tup", row['n_dead_tup'], timestamp
119
+ end
120
+ end
121
+
122
+ ok
123
+ end
124
+ end
@@ -0,0 +1,125 @@
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 <support@airbrake.io>
16
+ # Author Patrick Humpal <patrick@netvilla.net>
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: 10,
76
+ proc: proc(&:to_i)
77
+
78
+ include Pgpass
79
+
80
+ def phase_mapping(vacuum_phase)
81
+ ['initializing',
82
+ 'scanning heap',
83
+ 'vacuuming indexes',
84
+ 'vacuuming heap',
85
+ 'cleaning up indexes',
86
+ 'truncating heap',
87
+ 'performing final cleanup'].find_index(vacuum_phase)
88
+ end
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
+
100
+ query = 'SELECT * FROM pg_stat_progress_vacuum'
101
+ params = []
102
+ unless config[:all_databases]
103
+ query += ' WHERE datname = $1'
104
+ params.push config[:database]
105
+ end
106
+
107
+ con.exec_params(query, params) do |result|
108
+ result.each do |row|
109
+ database = row['datname']
110
+
111
+ row.each do |key, value|
112
+ next if %w[datid datname].include?(key)
113
+
114
+ if key == 'phase'
115
+ output "#{config[:scheme]}.vacuum.#{database}.phase", phase_mapping(value).to_s, timestamp
116
+ else
117
+ output "#{config[:scheme]}.vacuum.#{database}.#{key}", value.to_s, timestamp
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ ok
124
+ end
125
+ end
@@ -0,0 +1,132 @@
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 <eheydrick@gmail.com>
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: 10,
99
+ proc: proc(&:to_i)
100
+
101
+ include Pgpass
102
+
103
+ def run
104
+ begin
105
+ pgpass
106
+ con = PG.connect(host: config[:hostname],
107
+ dbname: config[:database],
108
+ user: config[:user],
109
+ password: config[:password],
110
+ port: config[:port],
111
+ connect_timeout: config[:timeout])
112
+ res = con.exec(config[:query].to_s)
113
+ rescue PG::Error => e
114
+ unknown "Unable to query PostgreSQL: #{e.message}"
115
+ end
116
+
117
+ value = if config[:count_tuples]
118
+ res.ntuples
119
+ else
120
+ res.first&.values&.first
121
+ end
122
+
123
+ if config[:multirow] && !config[:count_tuples]
124
+ res.values.each do |row|
125
+ output "#{config[:scheme]}.#{row[0]}", row[1]
126
+ end
127
+ else
128
+ output config[:scheme], value
129
+ end
130
+ ok
131
+ end
132
+ end
@@ -0,0 +1,27 @@
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
@@ -0,0 +1,15 @@
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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SensuPluginsPostgres
4
+ module Version
5
+ MAJOR = 4
6
+ MINOR = 3
7
+ PATCH = 1
8
+
9
+ VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sensu-plugins-postgres/version'
4
+ require 'sensu-plugins-postgres/pgpass'