newrelic_f5_plugin 1.0.9 → 1.0.10
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.
- data/CHANGES +9 -0
- data/README.rdoc +12 -0
- data/lib/newrelic_f5_plugin/agent.rb +86 -37
- data/lib/newrelic_f5_plugin/rules.rb +134 -0
- data/lib/newrelic_f5_plugin.rb +1 -0
- data/newrelic_f5_plugin.gemspec +3 -2
- metadata +3 -2
data/CHANGES
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
* 1.0.10
|
2
|
+
- Add iRule statistics:
|
3
|
+
- Executions per second
|
4
|
+
- Failures per second
|
5
|
+
- Aborts per second
|
6
|
+
- Average cycles taken (requires timing to be enabled)
|
7
|
+
- Updated SNMP connection logic to skip devices that are unreachable
|
8
|
+
- Skip collecting metrics if we can not get list of names for them
|
9
|
+
|
1
10
|
* 1.0.9
|
2
11
|
- Add SNAT Pools statistics:
|
3
12
|
- Current Connections
|
data/README.rdoc
CHANGED
@@ -27,6 +27,12 @@ Pool Statistics
|
|
27
27
|
* Connections per Second
|
28
28
|
* Inbound and Outbound Throughput
|
29
29
|
|
30
|
+
iRule Statistics
|
31
|
+
* Executions per Second
|
32
|
+
* Failures per Second
|
33
|
+
* Aborts per Second
|
34
|
+
* Average cycles (requires timing enabled on the iRule)
|
35
|
+
|
30
36
|
|
31
37
|
== Requirements
|
32
38
|
|
@@ -62,6 +68,12 @@ SNMP version 2c is supported.
|
|
62
68
|
|
63
69
|
f5_monitor run
|
64
70
|
|
71
|
+
== Installation with Chef/Puppet
|
72
|
+
|
73
|
+
The F5 plugin can also be installed with {Chef}[http://www.getchef.com] and {Puppet}[http://puppetlabs.com]. For Chef and Puppet support see the New Relic plugin's {Chef Cookbook}[http://community.opscode.com/cookbooks/newrelic_plugins] and {Puppet Module}[https://forge.puppetlabs.com/newrelic/newrelic_plugins].
|
74
|
+
|
75
|
+
Additional information on using Chef and Puppet with New Relic is available in New Relic's {documentation}[https://docs.newrelic.com/docs/plugins/plugin-installation-with-chef-and-puppet].
|
76
|
+
|
65
77
|
== Developer Instructions
|
66
78
|
|
67
79
|
1. Fork/Clone the repository
|
@@ -4,7 +4,7 @@ require 'newrelic_plugin'
|
|
4
4
|
require 'snmp'
|
5
5
|
|
6
6
|
module NewRelic::F5Plugin
|
7
|
-
VERSION = '1.0.
|
7
|
+
VERSION = '1.0.10'
|
8
8
|
|
9
9
|
# Register and run the agent
|
10
10
|
def self.run
|
@@ -50,9 +50,27 @@ module NewRelic::F5Plugin
|
|
50
50
|
# This is called on every polling cycle
|
51
51
|
#
|
52
52
|
def poll_cycle
|
53
|
+
NewRelic::PlatformLogger.debug("Starting poll cycle for '#{hostname}'")
|
54
|
+
|
53
55
|
# SNMP Stuff here
|
54
56
|
snmp = SNMP::Manager.new(:host => hostname, :port => port, :community => snmp_community)
|
55
57
|
|
58
|
+
#
|
59
|
+
# Test our SNMP connection, return if we fail to connect so the entire agent doesn't quit
|
60
|
+
#
|
61
|
+
begin
|
62
|
+
product_name = snmp.get_value(["1.3.6.1.4.1.3375.2.1.4.1.0"]).first
|
63
|
+
NewRelic::PlatformLogger.debug("Found F5 device of type: '#{product_name}'")
|
64
|
+
rescue SNMP::RequestTimeout
|
65
|
+
NewRelic::PlatformLogger.error("Unable to connect to device: '#{hostname}', skipping...")
|
66
|
+
snmp.close
|
67
|
+
return
|
68
|
+
rescue => e
|
69
|
+
NewRelic::PlatformLogger.error(e)
|
70
|
+
snmp.close
|
71
|
+
return
|
72
|
+
end
|
73
|
+
|
56
74
|
|
57
75
|
#
|
58
76
|
# Device wide metrics
|
@@ -108,43 +126,71 @@ module NewRelic::F5Plugin
|
|
108
126
|
#
|
109
127
|
NewRelic::PlatformLogger.debug("Collecting Virtual Server stats")
|
110
128
|
vs = NewRelic::F5Plugin::Virtuals.new snmp
|
111
|
-
virtual_requests = vs.get_requests
|
112
|
-
virtual_requests.each_key { |m| report_counter_metric m, "req/sec", virtual_requests[m] } unless virtual_requests.nil?
|
113
129
|
|
114
|
-
|
115
|
-
|
130
|
+
if vs.get_names
|
131
|
+
virtual_requests = vs.get_requests
|
132
|
+
virtual_requests.each_key { |m| report_counter_metric m, "req/sec", virtual_requests[m] } unless virtual_requests.nil?
|
116
133
|
|
117
|
-
|
118
|
-
|
134
|
+
virtual_conns_current = vs.get_conns_current
|
135
|
+
virtual_conns_current.each_key { |m| report_metric m, "conns", virtual_conns_current[m] } unless virtual_conns_current.nil?
|
119
136
|
|
120
|
-
|
121
|
-
|
137
|
+
virtual_conns_total = vs.get_conns_total
|
138
|
+
virtual_conns_total.each_key { |m| report_counter_metric m, "conn/sec", virtual_conns_total[m] } unless virtual_conns_total.nil?
|
122
139
|
|
123
|
-
|
124
|
-
|
140
|
+
virtual_throughput_in = vs.get_throughput_in
|
141
|
+
virtual_throughput_in.each_key { |m| report_counter_metric m, "bits/sec", virtual_throughput_in[m] } unless virtual_throughput_in.nil?
|
125
142
|
|
126
|
-
|
127
|
-
|
143
|
+
virtual_throughput_out = vs.get_throughput_out
|
144
|
+
virtual_throughput_out.each_key { |m| report_counter_metric m, "bits/sec", virtual_throughput_out[m] } unless virtual_throughput_out.nil?
|
145
|
+
|
146
|
+
virtual_cpu_usage_1m = vs.get_cpu_usage_1m
|
147
|
+
virtual_cpu_usage_1m.each_key { |m| report_metric m, "%", virtual_cpu_usage_1m[m] } unless virtual_cpu_usage_1m.nil?
|
148
|
+
end
|
128
149
|
|
129
150
|
#
|
130
151
|
# Collect pool statistics
|
131
152
|
#
|
132
153
|
NewRelic::PlatformLogger.debug("Collecting Pool stats")
|
133
154
|
pool = NewRelic::F5Plugin::Pools.new snmp
|
134
|
-
pool_requests = pool.get_requests
|
135
|
-
pool_requests.each_key { |m| report_counter_metric m, "req/sec", pool_requests[m] } unless pool_requests.nil?
|
136
155
|
|
137
|
-
|
138
|
-
|
156
|
+
if pool.get_names
|
157
|
+
pool_requests = pool.get_requests
|
158
|
+
pool_requests.each_key { |m| report_counter_metric m, "req/sec", pool_requests[m] } unless pool_requests.nil?
|
159
|
+
|
160
|
+
pool_conns_current = pool.get_conns_current
|
161
|
+
pool_conns_current.each_key { |m| report_metric m, "conns", pool_conns_current[m] } unless pool_conns_current.nil?
|
139
162
|
|
140
|
-
|
141
|
-
|
163
|
+
pool_conns_total = pool.get_conns_total
|
164
|
+
pool_conns_total.each_key { |m| report_counter_metric m, "conn/sec", pool_conns_total[m] } unless pool_conns_total.nil?
|
142
165
|
|
143
|
-
|
144
|
-
|
166
|
+
pool_throughput_in = pool.get_throughput_in
|
167
|
+
pool_throughput_in.each_key { |m| report_counter_metric m, "bits/sec", pool_throughput_in[m] } unless pool_throughput_in.nil?
|
168
|
+
|
169
|
+
pool_throughput_out = pool.get_throughput_out
|
170
|
+
pool_throughput_out.each_key { |m| report_counter_metric m, "bits/sec", pool_throughput_out[m] } unless pool_throughput_out.nil?
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
#
|
175
|
+
# iRule statistics
|
176
|
+
#
|
177
|
+
NewRelic::PlatformLogger.debug("Collecting iRule stats")
|
178
|
+
rule = NewRelic::F5Plugin::Rules.new snmp
|
179
|
+
|
180
|
+
if rule.get_names
|
181
|
+
rule_execs = rule.get_executions
|
182
|
+
rule_execs.each_key { |m| report_counter_metric m, "execs/sec", rule_execs[m] } unless rule_execs.nil?
|
183
|
+
|
184
|
+
rule_failures = rule.get_failures
|
185
|
+
rule_failures.each_key { |m| report_counter_metric m, "failures/sec", rule_failures[m] } unless rule_failures.nil?
|
186
|
+
|
187
|
+
rule_aborts = rule.get_aborts
|
188
|
+
rule_aborts.each_key { |m| report_counter_metric m, "aborts/sec", rule_aborts[m] } unless rule_aborts.nil?
|
189
|
+
|
190
|
+
rule_cycles = rule.get_average_cycles
|
191
|
+
rule_cycles.each_key { |m| report_metric m, "cycles", rule_cycles[m] } unless rule_cycles.nil?
|
192
|
+
end
|
145
193
|
|
146
|
-
pool_throughput_out = pool.get_throughput_out
|
147
|
-
pool_throughput_out.each_key { |m| report_counter_metric m, "bits/sec", pool_throughput_out[m] } unless pool_throughput_out.nil?
|
148
194
|
|
149
195
|
#
|
150
196
|
# Collect snat pool statistics
|
@@ -152,26 +198,29 @@ module NewRelic::F5Plugin
|
|
152
198
|
NewRelic::PlatformLogger.debug("Collecting SNAT Pool stats")
|
153
199
|
snatpool = NewRelic::F5Plugin::SnatPools.new snmp
|
154
200
|
|
155
|
-
|
156
|
-
|
201
|
+
if snatpool.get_names
|
202
|
+
snatpool_conns_max = snatpool.get_conns_max
|
203
|
+
snatpool_conns_max.each_key { |m| report_metric m, "conns", snatpool_conns_max[m] } unless snatpool_conns_max.nil?
|
157
204
|
|
158
|
-
|
159
|
-
|
205
|
+
snatpool_conns_current = snatpool.get_conns_current
|
206
|
+
snatpool_conns_current.each_key { |m| report_metric m, "conns", snatpool_conns_current[m] } unless snatpool_conns_current.nil?
|
160
207
|
|
161
|
-
|
162
|
-
|
208
|
+
snatpool_conns_total = snatpool.get_conns_total
|
209
|
+
snatpool_conns_total.each_key { |m| report_counter_metric m, "conn/sec", snatpool_conns_total[m] } unless snatpool_conns_total.nil?
|
163
210
|
|
164
|
-
|
165
|
-
|
211
|
+
snatpool_throughput_in = snatpool.get_throughput_in
|
212
|
+
snatpool_throughput_in.each_key { |m| report_counter_metric m, "bits/sec", snatpool_throughput_in[m] } unless snatpool_throughput_in.nil?
|
166
213
|
|
167
|
-
|
168
|
-
|
214
|
+
snatpool_throughput_out = snatpool.get_throughput_out
|
215
|
+
snatpool_throughput_out.each_key { |m| report_counter_metric m, "bits/sec", snatpool_throughput_out[m] } unless snatpool_throughput_out.nil?
|
169
216
|
|
170
|
-
|
171
|
-
|
217
|
+
snatpool_packets_in = snatpool.get_packets_in
|
218
|
+
snatpool_packets_in.each_key { |m| report_counter_metric m, "pkts/sec", snatpool_packets_in[m] } unless snatpool_packets_in.nil?
|
219
|
+
|
220
|
+
snatpool_packets_out = snatpool.get_packets_out
|
221
|
+
snatpool_packets_out.each_key { |m| report_counter_metric m, "pkts/sec", snatpool_packets_out[m] } unless snatpool_packets_out.nil?
|
222
|
+
end
|
172
223
|
|
173
|
-
snatpool_packets_out = snatpool.get_packets_out
|
174
|
-
snatpool_packets_out.each_key { |m| report_counter_metric m, "pkts/sec", snatpool_packets_out[m] } unless snatpool_packets_out.nil?
|
175
224
|
|
176
225
|
#
|
177
226
|
# Cleanup snmp connection
|
@@ -0,0 +1,134 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'newrelic_plugin'
|
4
|
+
require 'snmp'
|
5
|
+
|
6
|
+
#LtmRuleEventStatEntry
|
7
|
+
# ltmRuleEventStatName LongDisplayString,
|
8
|
+
# ltmRuleEventStatEventType LongDisplayString,
|
9
|
+
# ltmRuleEventStatPriority INTEGER,
|
10
|
+
# ltmRuleEventStatFailures Integer32,
|
11
|
+
# ltmRuleEventStatAborts Integer32,
|
12
|
+
# ltmRuleEventStatTotalExecutions Integer32,
|
13
|
+
# ltmRuleEventStatAvgCycles Integer32,
|
14
|
+
# ltmRuleEventStatMaxCycles Integer32,
|
15
|
+
# ltmRuleEventStatMinCycles Integer32
|
16
|
+
|
17
|
+
|
18
|
+
module NewRelic
|
19
|
+
module F5Plugin
|
20
|
+
|
21
|
+
class Rules
|
22
|
+
attr_accessor :rule_names, :snmp_manager
|
23
|
+
|
24
|
+
OID_LTM_RULES = "1.3.6.1.4.1.3375.2.2.8"
|
25
|
+
OID_LTM_RULE_STAT = "#{OID_LTM_RULES}.3"
|
26
|
+
OID_LTM_RULE_ENTRY = "#{OID_LTM_RULE_STAT}.3.1"
|
27
|
+
OID_LTM_RULE_STAT_NAME = "#{OID_LTM_RULE_ENTRY}.1"
|
28
|
+
OID_LTM_RULE_STAT_TYPE = "#{OID_LTM_RULE_ENTRY}.2"
|
29
|
+
OID_LTM_RULE_STAT_FAILURES = "#{OID_LTM_RULE_ENTRY}.4"
|
30
|
+
OID_LTM_RULE_STAT_ABORTS = "#{OID_LTM_RULE_ENTRY}.5"
|
31
|
+
OID_LTM_RULE_STAT_TOT_EXEC = "#{OID_LTM_RULE_ENTRY}.6"
|
32
|
+
OID_LTM_RULE_STAT_AVG_CYCLES = "#{OID_LTM_RULE_ENTRY}.7"
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
#
|
37
|
+
# Init
|
38
|
+
#
|
39
|
+
def initialize(snmp = nil)
|
40
|
+
@rule_names = [ ]
|
41
|
+
|
42
|
+
if snmp
|
43
|
+
@snmp_manager = snmp
|
44
|
+
else
|
45
|
+
@snmp_manager = nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
#
|
52
|
+
# Get the list of iRule names
|
53
|
+
#
|
54
|
+
def get_names(snmp = nil)
|
55
|
+
snmp = snmp_manager unless snmp
|
56
|
+
|
57
|
+
if snmp
|
58
|
+
@rule_names.clear
|
59
|
+
|
60
|
+
begin
|
61
|
+
snmp.walk([OID_LTM_RULE_STAT_NAME, OID_LTM_RULE_STAT_TYPE]) do |rule, func|
|
62
|
+
@rule_names.push("#{rule.value}/#{func.value}")
|
63
|
+
end
|
64
|
+
rescue Exception => e
|
65
|
+
NewRelic::PlatformLogger.error("Unable to gather iRule names with error: #{e}")
|
66
|
+
end
|
67
|
+
|
68
|
+
NewRelic::PlatformLogger.debug("Rules: Found #{@rule_names.size} iRules")
|
69
|
+
return @rule_names
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
#
|
76
|
+
# Gather Total iRule Executions
|
77
|
+
#
|
78
|
+
def get_executions(snmp = nil)
|
79
|
+
snmp = snmp_manager unless snmp
|
80
|
+
|
81
|
+
get_names(snmp) if @rule_names.empty?
|
82
|
+
res = gather_snmp_metrics_by_name("Rules/Executions", @rule_names, OID_LTM_RULE_STAT_TOT_EXEC, snmp)
|
83
|
+
NewRelic::PlatformLogger.debug("Rules: Got #{res.size}/#{@rule_names.size} Execution metrics")
|
84
|
+
return res
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
#
|
90
|
+
# Gather Total iRule Failures
|
91
|
+
#
|
92
|
+
def get_failures(snmp = nil)
|
93
|
+
snmp = snmp_manager unless snmp
|
94
|
+
|
95
|
+
get_names(snmp) if @rule_names.empty?
|
96
|
+
res = gather_snmp_metrics_by_name("Rules/Failures", @rule_names, OID_LTM_RULE_STAT_FAILURES, snmp)
|
97
|
+
NewRelic::PlatformLogger.debug("Rules: Got #{res.size}/#{@rule_names.size} Failure metrics")
|
98
|
+
return res
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
#
|
104
|
+
# Gather Total iRule Aborts
|
105
|
+
#
|
106
|
+
def get_aborts(snmp = nil)
|
107
|
+
snmp = snmp_manager unless snmp
|
108
|
+
|
109
|
+
get_names(snmp) if @rule_names.empty?
|
110
|
+
res = gather_snmp_metrics_by_name("Rules/Aborts", @rule_names, OID_LTM_RULE_STAT_ABORTS, snmp)
|
111
|
+
NewRelic::PlatformLogger.debug("Rules: Got #{res.size}/#{@rule_names.size} Abort metrics")
|
112
|
+
return res
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
#
|
118
|
+
# Gather Average iRule execution time (in cycles)
|
119
|
+
#
|
120
|
+
def get_average_cycles(snmp = nil)
|
121
|
+
snmp = snmp_manager unless snmp
|
122
|
+
|
123
|
+
get_names(snmp) if @rule_names.empty?
|
124
|
+
res = gather_snmp_metrics_by_name("Rules/Time", @rule_names, OID_LTM_RULE_STAT_AVG_CYCLES, snmp)
|
125
|
+
NewRelic::PlatformLogger.debug("Rules: Got #{res.size}/#{@rule_names.size} Abort metrics")
|
126
|
+
return res
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
data/lib/newrelic_f5_plugin.rb
CHANGED
@@ -3,6 +3,7 @@ require 'newrelic_f5_plugin/util'
|
|
3
3
|
require 'newrelic_f5_plugin/device'
|
4
4
|
require 'newrelic_f5_plugin/nodes'
|
5
5
|
require 'newrelic_f5_plugin/pools'
|
6
|
+
require 'newrelic_f5_plugin/rules'
|
6
7
|
require 'newrelic_f5_plugin/snatpools'
|
7
8
|
require 'newrelic_f5_plugin/virtuals'
|
8
9
|
require 'newrelic_f5_plugin/agent'
|
data/newrelic_f5_plugin.gemspec
CHANGED
@@ -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_f5_plugin'
|
16
|
-
s.version = '1.0.
|
17
|
-
s.date = '2014-
|
16
|
+
s.version = '1.0.10'
|
17
|
+
s.date = '2014-02-03'
|
18
18
|
s.rubyforge_project = 'newrelic_f5_plugin'
|
19
19
|
|
20
20
|
## Make sure your summary is short. The description may be as long
|
@@ -78,6 +78,7 @@ to find out how to install and run the plugin agent.
|
|
78
78
|
lib/newrelic_f5_plugin/device.rb
|
79
79
|
lib/newrelic_f5_plugin/nodes.rb
|
80
80
|
lib/newrelic_f5_plugin/pools.rb
|
81
|
+
lib/newrelic_f5_plugin/rules.rb
|
81
82
|
lib/newrelic_f5_plugin/snatpools.rb
|
82
83
|
lib/newrelic_f5_plugin/util.rb
|
83
84
|
lib/newrelic_f5_plugin/virtuals.rb
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newrelic_f5_plugin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.10
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-02-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: newrelic_plugin
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- lib/newrelic_f5_plugin/device.rb
|
70
70
|
- lib/newrelic_f5_plugin/nodes.rb
|
71
71
|
- lib/newrelic_f5_plugin/pools.rb
|
72
|
+
- lib/newrelic_f5_plugin/rules.rb
|
72
73
|
- lib/newrelic_f5_plugin/snatpools.rb
|
73
74
|
- lib/newrelic_f5_plugin/util.rb
|
74
75
|
- lib/newrelic_f5_plugin/virtuals.rb
|