newrelic_postgres_plugin 0.1.10 → 0.2.0
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.
- 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
|