newrelic_postgres_plugin 0.1.10 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +5 -9
- data/README.md +6 -6
- data/lib/newrelic_postgres_plugin/agent.rb +84 -72
- data/lib/newrelic_postgres_plugin/version.rb +1 -1
- data/newrelic_postgres_plugin.gemspec +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42e010eea7c25bffabade08f52c80b7d30d97c93
|
4
|
+
data.tar.gz: 7483bf38fad8a1843f1cd0e8b3e78f1b52e00eb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2f5837b91fa26beae34557ecaf5e933d67daf122ce6591d64284c8dd1e51471dd66822b61afbc5c4071cf1d142a9999f923ae9c7c47473596453eb75d13812e
|
7
|
+
data.tar.gz: b9506081e2b0fdf1ec3e0a1ae5b19d4f52b383213197012514f55bc1517312d2dcd877cabf26db35231988bc487508fdbd5967bec8963b7cc68f6bc3fda5cec3
|
data/Gemfile.lock
CHANGED
@@ -1,21 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
newrelic_postgres_plugin (0.1.
|
5
|
-
newrelic_plugin (~> 1.
|
4
|
+
newrelic_postgres_plugin (0.1.10)
|
5
|
+
newrelic_plugin (~> 1.3)
|
6
6
|
pg (>= 0.15.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
|
12
|
-
|
13
|
-
json (1.8.0)
|
14
|
-
multipart-post (1.2.0)
|
15
|
-
newrelic_plugin (1.0.3)
|
16
|
-
faraday (>= 0.8.1)
|
11
|
+
json (1.8.1)
|
12
|
+
newrelic_plugin (1.3.1)
|
17
13
|
json
|
18
|
-
pg (0.
|
14
|
+
pg (0.17.1)
|
19
15
|
|
20
16
|
PLATFORMS
|
21
17
|
ruby
|
data/README.md
CHANGED
@@ -5,8 +5,8 @@ A NewRelic Platform Postgres Plugin
|
|
5
5
|
|
6
6
|
The New Relic Postgres Plugin enables integrated monitoring of your Postgres database in a custom NewRelic dashboard. Currently the following metrics are recorded:
|
7
7
|
|
8
|
-
* Index size,
|
9
|
-
* Cache
|
8
|
+
* Index size, miss rate, and count
|
9
|
+
* Cache miss rate
|
10
10
|
* Idle and active connection counts
|
11
11
|
* BGWriter metrics
|
12
12
|
* Tuple metrics
|
@@ -17,14 +17,14 @@ The New Relic Postgres Plugin enables integrated monitoring of your Postgres dat
|
|
17
17
|
### Proxy host
|
18
18
|
|
19
19
|
You need a host to install the plugin on that is able to poll the desired Postgres database. That
|
20
|
-
host also needs Ruby (tested with 2.0.0), and support for rubygems.
|
20
|
+
host also needs Ruby (tested with 2.0.0), and support for rubygems. Heroku is a great choice for this. A fully deployable example app is provided.
|
21
21
|
|
22
|
+
https://github.com/GoBoundless/heroku_postgres_monitor
|
22
23
|
|
23
24
|
### Postgres
|
24
25
|
|
25
26
|
This plugin has been tested with with a few different Postgres version and should work with any version compatible with the pg gem.
|
26
27
|
|
27
|
-
|
28
28
|
## Installation and Running
|
29
29
|
|
30
30
|
1. Install this gem from RubyGems:
|
@@ -37,7 +37,7 @@ This plugin has been tested with with a few different Postgres version and shoul
|
|
37
37
|
```pg_monitor install -l LICENSE_KEY```
|
38
38
|
|
39
39
|
using the license key from your New Relic account.
|
40
|
-
4. Edit the
|
40
|
+
4. Edit the `config/newrelic_plugin.yml` file generated in step 4. Setup host/port/user/password/dbname for your postgres connection.
|
41
41
|
5. Execute
|
42
42
|
|
43
43
|
```pg_monitor run```
|
@@ -61,4 +61,4 @@ Please use Github issue for support. We will do our best to address issues in a
|
|
61
61
|
|
62
62
|
```bundle install```
|
63
63
|
|
64
|
-
3. Run
|
64
|
+
3. Run `rake -T` to see rake options, including tests.
|
@@ -76,7 +76,6 @@ module NewRelic::PostgresPlugin
|
|
76
76
|
@previous_metrics[name] = value
|
77
77
|
end
|
78
78
|
|
79
|
-
|
80
79
|
def report_backend_metrics
|
81
80
|
@connection.exec(backend_query) do |result|
|
82
81
|
report_metric "Backends/Active", 'connections', result[0]['backends_active']
|
@@ -87,22 +86,23 @@ module NewRelic::PostgresPlugin
|
|
87
86
|
def report_database_metrics
|
88
87
|
@connection.exec(database_query) do |result|
|
89
88
|
result.each do |row|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
report_derived_metric "Database/Tuples/Writes/Inserts", '', row['tup_inserted'].to_i
|
100
|
-
report_derived_metric "Database/Tuples/Writes/Updates", '', row['tup_updated'].to_i
|
101
|
-
report_derived_metric "Database/Tuples/Writes/Deletes", '', row['tup_deleted'].to_i
|
102
|
-
report_derived_metric "Database/Conflicts", '', row['conflicts'].to_i
|
103
|
-
end
|
89
|
+
report_metric "Database/Backends", '', row['numbackends'].to_i
|
90
|
+
report_derived_metric "Database/Transactions/Committed", '', row['xact_commit'].to_i
|
91
|
+
report_derived_metric "Database/Transactions/Rolled Back", '', row['xact_rollback'].to_i
|
92
|
+
report_derived_metric "Database/Tuples/Returned/From Sequential", '', row['tup_returned'].to_i
|
93
|
+
report_derived_metric "Database/Tuples/Returned/From Bitmap", '', row['tup_fetched'].to_i
|
94
|
+
report_derived_metric "Database/Tuples/Writes/Inserts", '', row['tup_inserted'].to_i
|
95
|
+
report_derived_metric "Database/Tuples/Writes/Updates", '', row['tup_updated'].to_i
|
96
|
+
report_derived_metric "Database/Tuples/Writes/Deletes", '', row['tup_deleted'].to_i
|
97
|
+
report_derived_metric "Database/Conflicts", '', row['conflicts'].to_i
|
104
98
|
end
|
105
99
|
end
|
100
|
+
@connection.exec(index_count_query) do |result|
|
101
|
+
report_metric "Database/Indexes/Count", 'indexes', result[0]['indexes'].to_i
|
102
|
+
end
|
103
|
+
@connection.exec(index_size_query) do |result|
|
104
|
+
report_metric "Databases/Indexes/Size", 'bytes', result[0]['size'].to_i
|
105
|
+
end
|
106
106
|
end
|
107
107
|
|
108
108
|
def report_bgwriter_metrics
|
@@ -113,71 +113,83 @@ module NewRelic::PostgresPlugin
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def report_index_metrics
|
116
|
-
|
117
|
-
report_metric "Indexes/Number of Indexes", 'indexes', result[0]['indexes'].to_i
|
118
|
-
end
|
119
|
-
@connection.exec(index_hit_rate_query) do |result|
|
120
|
-
report_metric "Indexes/Index Hit Rate", '%', result[0]['ratio'].to_f * 100.0
|
121
|
-
report_metric "Indexes/Cache Hit Rate", '%', result[1]['ratio'].to_f * 100.0
|
122
|
-
end
|
123
|
-
@connection.exec(index_size_query) do |result|
|
124
|
-
report_metric "Indexes/Size on Disk", 'bytes', result[0]['size'].to_i
|
125
|
-
end
|
116
|
+
report_metric "Indexes/Miss Ratio", '%', calculate_miss_ratio(%Q{SELECT SUM(idx_blks_hit) AS hits, SUM(idx_blks_read) AS reads FROM pg_statio_user_indexes})
|
126
117
|
end
|
127
118
|
|
128
|
-
def
|
129
|
-
%Q(
|
130
|
-
SELECT ( SELECT count(*) FROM pg_stat_activity WHERE
|
131
|
-
#{
|
132
|
-
if nine_two?
|
133
|
-
"state <> 'idle'"
|
134
|
-
else
|
135
|
-
"current_query <> '<IDLE>'"
|
136
|
-
end
|
137
|
-
}
|
138
|
-
) AS backends_active, ( SELECT count(*) FROM pg_stat_activity WHERE
|
139
|
-
#{
|
140
|
-
if nine_two?
|
141
|
-
"state = 'idle'"
|
142
|
-
else
|
143
|
-
"current_query = '<IDLE>'"
|
144
|
-
end
|
145
|
-
}
|
146
|
-
) AS backends_idle FROM pg_stat_activity;
|
147
|
-
)
|
119
|
+
def report_cache_metrics
|
120
|
+
report_metric "Cache/Miss Ratio", '%', calculate_miss_ratio(%Q{SELECT SUM(heap_blks_hit) AS hits, SUM(heap_blks_read) AS reads FROM pg_statio_user_tables})
|
148
121
|
end
|
149
122
|
|
150
|
-
|
151
|
-
"SELECT * FROM pg_stat_database;"
|
152
|
-
end
|
123
|
+
private
|
153
124
|
|
154
|
-
|
155
|
-
|
156
|
-
|
125
|
+
# This assumes the query returns a single row with two columns: hits and reads.
|
126
|
+
def calculate_miss_ratio(query)
|
127
|
+
sample = @connection.exec(query)[0]
|
128
|
+
sample.each { |k,v| sample[k] = v.to_i }
|
129
|
+
@previous_result_for_query ||= {}
|
130
|
+
miss_ratio = if check_samples(@previous_result_for_query[query], sample)
|
157
131
|
|
158
|
-
|
159
|
-
|
160
|
-
|
132
|
+
hits = sample["hits"] - @previous_result_for_query[query]["hits"]
|
133
|
+
reads = sample["reads"] - @previous_result_for_query[query]["reads"]
|
134
|
+
|
135
|
+
if (hits + reads) == 0
|
136
|
+
0.0
|
137
|
+
else
|
138
|
+
reads.to_f / (hits + reads) * 100.0
|
139
|
+
end
|
140
|
+
else
|
141
|
+
0.0
|
142
|
+
end
|
143
|
+
|
144
|
+
@previous_result_for_query[query] = sample
|
145
|
+
return miss_ratio
|
146
|
+
end
|
147
|
+
|
148
|
+
# Check if we don't have a time dimension yet or metrics have decreased in value.
|
149
|
+
def check_samples(last, current)
|
150
|
+
return false if last.nil? # First sample?
|
151
|
+
return false unless current.find { |k,v| last[k] > v }.nil? # Values have gone down?
|
152
|
+
return true
|
153
|
+
end
|
161
154
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
155
|
+
def backend_query
|
156
|
+
%Q(
|
157
|
+
SELECT ( SELECT count(*) FROM pg_stat_activity WHERE
|
158
|
+
#{
|
159
|
+
if nine_two?
|
160
|
+
"state <> 'idle'"
|
161
|
+
else
|
162
|
+
"current_query <> '<IDLE>'"
|
163
|
+
end
|
164
|
+
}
|
165
|
+
) AS backends_active, ( SELECT count(*) FROM pg_stat_activity WHERE
|
166
|
+
#{
|
167
|
+
if nine_two?
|
168
|
+
"state = 'idle'"
|
169
|
+
else
|
170
|
+
"current_query = '<IDLE>'"
|
171
|
+
end
|
172
|
+
}
|
173
|
+
) AS backends_idle FROM pg_stat_activity;
|
174
|
+
)
|
175
|
+
end
|
177
176
|
|
178
|
-
|
179
|
-
|
180
|
-
|
177
|
+
def database_query
|
178
|
+
"SELECT * FROM pg_stat_database WHERE datname='#{dbname}';"
|
179
|
+
end
|
180
|
+
|
181
|
+
def bgwriter_query
|
182
|
+
"SELECT * FROM pg_stat_bgwriter;"
|
183
|
+
end
|
184
|
+
|
185
|
+
def index_count_query
|
186
|
+
"SELECT count(1) as indexes FROM pg_class WHERE relkind = 'i';"
|
187
|
+
end
|
188
|
+
|
189
|
+
def index_size_query
|
190
|
+
"SELECT sum(relpages::bigint*8192) AS size FROM pg_class WHERE reltype = 0;"
|
191
|
+
end
|
181
192
|
|
182
193
|
end
|
194
|
+
|
183
195
|
end
|
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
|
|
13
13
|
## If your rubyforge_project name is different, then edit it and comment out
|
14
14
|
## the sub! line in the Rakefile
|
15
15
|
s.name = 'newrelic_postgres_plugin'
|
16
|
-
s.version = '0.
|
17
|
-
s.date = '2014-
|
16
|
+
s.version = '0.2.0'
|
17
|
+
s.date = '2014-08-05'
|
18
18
|
s.rubyforge_project = 'newrelic_postgres_plugin'
|
19
19
|
|
20
20
|
## Make sure your summary is short. The description may be as long
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newrelic_postgres_plugin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Hodgson
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-08-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: newrelic_plugin
|
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
86
|
version: '0'
|
87
87
|
requirements: []
|
88
88
|
rubyforge_project: newrelic_postgres_plugin
|
89
|
-
rubygems_version: 2.
|
89
|
+
rubygems_version: 2.4.1
|
90
90
|
signing_key:
|
91
91
|
specification_version: 2
|
92
92
|
summary: New Relic Postgres plugin
|