newrelic_f5_plugin 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +35 -0
- data/Gemfile +12 -0
- data/LICENSE +22 -0
- data/NOTES +30 -0
- data/README.rdoc +53 -0
- data/Rakefile +155 -0
- data/bin/f5_monitor +58 -0
- data/config/newrelic_plugin.yml +38 -0
- data/lib/newrelic_f5_plugin.rb +8 -0
- data/lib/newrelic_f5_plugin/agent.rb +381 -0
- data/lib/newrelic_f5_plugin/nodes.rb +61 -0
- data/newrelic_f5_plugin.gemspec +89 -0
- data/test/f5_monitor_test.rb +35 -0
- data/test/plugin_test.rb +79 -0
- data/test/test_helper.rb +6 -0
- metadata +103 -0
data/CHANGES
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
* 1.0.0
|
2
|
+
- Updated version for release!
|
3
|
+
|
4
|
+
* 0.0.8
|
5
|
+
- Updated to require newrelic_platform.gem > 0.2.10
|
6
|
+
- Added a total throughput metric
|
7
|
+
|
8
|
+
* 0.0.7
|
9
|
+
- Initial reporting of Nodes (Monitor Status)
|
10
|
+
- Include a Total throughput summary metric
|
11
|
+
|
12
|
+
* 0.0.6
|
13
|
+
- Change the GUID to match the standard naming scheme
|
14
|
+
- Added a summary metric for CPU usage
|
15
|
+
- Added summary metrics for SSL
|
16
|
+
- Added HTTP Compression metrics
|
17
|
+
|
18
|
+
* 0.0.5
|
19
|
+
- Changed bytes to bits on throughput metrics
|
20
|
+
|
21
|
+
* 0.0.4
|
22
|
+
- Added SSL metric collection
|
23
|
+
- Changed CPU to be a percentage of 100 by asking how many CPUs the device has
|
24
|
+
|
25
|
+
* 0.0.3
|
26
|
+
- Added more HTTP metrics
|
27
|
+
- Added default port so you don't have to specify it in the yaml
|
28
|
+
- Refactored much of the agent implementation to make if more modular
|
29
|
+
|
30
|
+
* 0.0.2
|
31
|
+
- Added Global CPU Metrics
|
32
|
+
|
33
|
+
* 0.0.1
|
34
|
+
- In Dev
|
35
|
+
|
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# This gemfile is used in the context of development on this plugin agent.
|
4
|
+
|
5
|
+
gem 'newrelic_plugin', :git => 'git@github.com:newrelic-platform/newrelic_plugin.git', :branch => 'release'
|
6
|
+
gem "snmp"
|
7
|
+
gem "rake", ">0.9.2"
|
8
|
+
gem 'test-unit'
|
9
|
+
gem "shoulda"
|
10
|
+
gem "mocha"
|
11
|
+
gem "rdoc", ">2.4.2"
|
12
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2013 New Relic, Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
data/NOTES
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
F5 MIB Tree Overview
|
2
|
+
-----------------------------------
|
3
|
+
1.3.6.1.4.1 Enterprises
|
4
|
+
+-3375 F5
|
5
|
+
+-2 bigipTrafficMgmt
|
6
|
+
+-1 bigipSystem
|
7
|
+
+-1 sysGlobals
|
8
|
+
| +-2 sysGlobalStats
|
9
|
+
| | +-1 sysGlobalStat
|
10
|
+
| | | +-38 sysStatCpuCount
|
11
|
+
| | +-4 sysGlobalHttpStat
|
12
|
+
| | +-12 sysGlobalTcpStat
|
13
|
+
| | +-20 sysGlobalHost
|
14
|
+
| | | +-4 sysGlobalHostCpuCount
|
15
|
+
| | +-22 sysGlobalHttpCompressionStat
|
16
|
+
| | +-2 sysHttpCompressionStatPrecompressBytes
|
17
|
+
| 2 sysNetwork
|
18
|
+
| +-4 sysInterfaces
|
19
|
+
| 3 sysPlatform
|
20
|
+
| +-2 sysChassis
|
21
|
+
| +-6 sysSystem
|
22
|
+
| 4 sysProduct
|
23
|
+
2 bigipLocalTM
|
24
|
+
+-1 ltmGlobals
|
25
|
+
+-4 ltmNodes
|
26
|
+
+-5 ltmPools
|
27
|
+
+-6 ltmProfiles
|
28
|
+
+-8 ltmRules
|
29
|
+
+-10 ltmVirtualServers
|
30
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
= New Relic F5 Plugin
|
2
|
+
|
3
|
+
The New Relic F5 Plugin enables integrated monitoring of your F5 Local Traffic
|
4
|
+
Manager devices inside of New Relic. Currently the following metrics are recorded:
|
5
|
+
|
6
|
+
Device wide Metrics
|
7
|
+
* CPU / Memory usage
|
8
|
+
* Throughput (Total, Client side, Server side)
|
9
|
+
* HTTP Requests (Requests/second, HTTP Methods, Status Codes, Versions)
|
10
|
+
* HTTP Compression (Pre/Post broken down by content type)
|
11
|
+
* SSL Requests/second
|
12
|
+
* TCP Details (Current connections, connection rate, Server/Client side, Wait State)
|
13
|
+
* Node status
|
14
|
+
|
15
|
+
|
16
|
+
== Requirements
|
17
|
+
|
18
|
+
=== Proxy host
|
19
|
+
|
20
|
+
You need a host to install the plugin on that is able to poll the desired F5s via SNMP. That
|
21
|
+
host also needs Ruby (tested with 1.8.7 and 1.9.3), and support for rubygems.
|
22
|
+
|
23
|
+
|
24
|
+
=== F5
|
25
|
+
|
26
|
+
This plugin has been tested with F5 LTM versions 11.2.x and 11.3.x. Some metrics are reported on
|
27
|
+
10.2.x, but the data is incomplete due to SNMP changes made by F5 between 10 and 11.
|
28
|
+
|
29
|
+
A *read-only* SNMP community is required for each device to be monitored. Currently, only
|
30
|
+
SNMP verison 2c is supported.
|
31
|
+
|
32
|
+
|
33
|
+
== Instructions for running the F5 plugin agent
|
34
|
+
|
35
|
+
1. Install the +newrelic_plugin+ gem.
|
36
|
+
2. Install this gem.
|
37
|
+
3. Create an installation directory (like /opt/newrelic/f5 ).
|
38
|
+
4. In the installation directory, execute
|
39
|
+
|
40
|
+
f5_monitor install -l LICENSE_KEY
|
41
|
+
|
42
|
+
using the license key from your New Relic account.
|
43
|
+
5. Edit the +config/newrelic_plugin.yml+ file generated in step 4. Setup name/hostname/port/snmp_community for each F5 you wish to monitor.
|
44
|
+
6. Execute
|
45
|
+
|
46
|
+
f5_monitor run
|
47
|
+
|
48
|
+
== Developer Instructions
|
49
|
+
|
50
|
+
1. Fork/Clone the repository
|
51
|
+
2. Install bundler and do +bundle install+
|
52
|
+
3. Do <b><tt>rake -T</tt></b> to see rake options, including tests.
|
53
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
# https://raw.github.com/mojombo/rakegem
|
6
|
+
|
7
|
+
#############################################################################
|
8
|
+
#
|
9
|
+
# Helper functions
|
10
|
+
#
|
11
|
+
#############################################################################
|
12
|
+
|
13
|
+
def name
|
14
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
15
|
+
end
|
16
|
+
|
17
|
+
def version
|
18
|
+
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
|
19
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
20
|
+
end
|
21
|
+
|
22
|
+
def date
|
23
|
+
Date.today.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def rubyforge_project
|
27
|
+
name
|
28
|
+
end
|
29
|
+
|
30
|
+
def gemspec_file
|
31
|
+
"#{name}.gemspec"
|
32
|
+
end
|
33
|
+
|
34
|
+
def gem_file
|
35
|
+
"#{name}-#{version}.gem"
|
36
|
+
end
|
37
|
+
|
38
|
+
def replace_header(head, header_name)
|
39
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
40
|
+
end
|
41
|
+
|
42
|
+
#############################################################################
|
43
|
+
#
|
44
|
+
# Standard tasks
|
45
|
+
#
|
46
|
+
#############################################################################
|
47
|
+
|
48
|
+
task :default => :test
|
49
|
+
|
50
|
+
require 'rake/testtask'
|
51
|
+
Rake::TestTask.new(:test) do |test|
|
52
|
+
test.libs << 'lib' << 'test'
|
53
|
+
test.pattern = 'test/**/*_test.rb'
|
54
|
+
test.verbose = true
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Generate RCov test coverage and open in your browser"
|
58
|
+
task :coverage do
|
59
|
+
require 'rcov'
|
60
|
+
sh "rm -fr coverage"
|
61
|
+
sh "rcov test/test_*.rb"
|
62
|
+
sh "open coverage/index.html"
|
63
|
+
end
|
64
|
+
|
65
|
+
require 'rdoc/task'
|
66
|
+
Rake::RDocTask.new do |rdoc|
|
67
|
+
rdoc.rdoc_dir = 'rdoc'
|
68
|
+
rdoc.title = "#{name} #{version}"
|
69
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
70
|
+
rdoc.rdoc_files.include('README.rdoc')
|
71
|
+
rdoc.rdoc_files.include('LICENSE')
|
72
|
+
rdoc.rdoc_files.include('CHANGES')
|
73
|
+
rdoc.main = "README.rdoc"
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "Open an irb session preloaded with this library"
|
77
|
+
task :console do
|
78
|
+
sh "irb -rubygems -I./lib -r ./lib/#{name}.rb"
|
79
|
+
end
|
80
|
+
|
81
|
+
#############################################################################
|
82
|
+
#
|
83
|
+
# Custom tasks (add your own tasks here)
|
84
|
+
#
|
85
|
+
#############################################################################
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
#############################################################################
|
90
|
+
#
|
91
|
+
# Packaging tasks
|
92
|
+
#
|
93
|
+
#############################################################################
|
94
|
+
|
95
|
+
desc "Create tag v#{version} and build and push #{gem_file} to Rubgems"
|
96
|
+
task :release => :build do
|
97
|
+
unless `git branch` =~ /^\* master$/
|
98
|
+
puts "You must be on the master branch to release!"
|
99
|
+
exit!
|
100
|
+
end
|
101
|
+
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
102
|
+
sh "git tag v#{version}"
|
103
|
+
sh "git push origin master"
|
104
|
+
sh "git push origin v#{version}"
|
105
|
+
sh "gem push pkg/#{name}-#{version}.gem"
|
106
|
+
end
|
107
|
+
|
108
|
+
desc "Build #{gem_file} into the pkg directory"
|
109
|
+
task :build => :gemspec do
|
110
|
+
sh "mkdir -p pkg"
|
111
|
+
sh "gem build #{gemspec_file}"
|
112
|
+
sh "mv #{gem_file} pkg"
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "Generate #{gemspec_file}"
|
116
|
+
task :gemspec => :validate do
|
117
|
+
# read spec file and split out manifest section
|
118
|
+
spec = File.read(gemspec_file)
|
119
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
120
|
+
|
121
|
+
# replace name version and date
|
122
|
+
replace_header(head, :name)
|
123
|
+
replace_header(head, :version)
|
124
|
+
replace_header(head, :date)
|
125
|
+
#comment this out if your rubyforge_project has a different name
|
126
|
+
replace_header(head, :rubyforge_project)
|
127
|
+
|
128
|
+
# determine file list from git ls-files
|
129
|
+
files = `git ls-files`.
|
130
|
+
split("\n").
|
131
|
+
sort.
|
132
|
+
reject { |file| file =~ /^\./ }.
|
133
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
134
|
+
map { |file| " #{file}" }.
|
135
|
+
join("\n")
|
136
|
+
|
137
|
+
# piece file back together and write
|
138
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
139
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
140
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
141
|
+
puts "Updated #{gemspec_file}"
|
142
|
+
end
|
143
|
+
|
144
|
+
desc "Validate #{gemspec_file}"
|
145
|
+
task :validate do
|
146
|
+
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
147
|
+
unless libfiles.empty?
|
148
|
+
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
149
|
+
exit!
|
150
|
+
end
|
151
|
+
unless Dir['VERSION*'].empty?
|
152
|
+
puts "A `VERSION` file at root level violates Gem best practices."
|
153
|
+
exit!
|
154
|
+
end
|
155
|
+
end
|
data/bin/f5_monitor
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.expand_path "../../lib", __FILE__
|
3
|
+
require "newrelic_f5_plugin"
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = OptionParser.new do |opts|
|
7
|
+
opts.banner = <<-EOF
|
8
|
+
Usage:
|
9
|
+
f5_monitor ( run | install ) [options]
|
10
|
+
EOF
|
11
|
+
|
12
|
+
opts.on("-v", "--verbose", "Run verbosely") do
|
13
|
+
NewRelic::Plugin::Config.config.newrelic['verbose'] = 1
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on("-l", "--license LICENSE_KEY", "Your NewRelic account License Key") do | license_key |
|
17
|
+
$license_key = license_key
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-c", "--config FILE", "Override the location of the newrelic_plugin.yml") do | filename |
|
21
|
+
if !File.exists? filename
|
22
|
+
puts "File not found: #{filename.inspect}"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
NewRelic::Plugin::Config.config_file = filename
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-h", "--help") do
|
29
|
+
puts opts
|
30
|
+
if File.basename($0) == File.basename(__FILE__)
|
31
|
+
exit 0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
args = options.parse!(ARGV)
|
38
|
+
|
39
|
+
if args.first == "run"
|
40
|
+
if $license_key
|
41
|
+
NewRelic::Plugin::Config.config.options['newrelic']['license_key'] = $license_key
|
42
|
+
end
|
43
|
+
NewRelic::F5Plugin.run
|
44
|
+
elsif args.first == "install"
|
45
|
+
config_file = File.read(File.expand_path("../../config/newrelic_plugin.yml", __FILE__))
|
46
|
+
if $license_key
|
47
|
+
config_file.gsub!("YOUR_LICENSE_KEY_HERE", $license_key)
|
48
|
+
end
|
49
|
+
require 'fileutils'
|
50
|
+
FileUtils.mkdir_p "config"
|
51
|
+
File.open("config/newrelic_plugin.yml", "w") do | io |
|
52
|
+
io.write(config_file)
|
53
|
+
end
|
54
|
+
puts "Saved agent config file #{File.expand_path("config/newrelic_plugin.yml")}"
|
55
|
+
else
|
56
|
+
puts options
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
#
|
3
|
+
# This is a sample newrelic_plugin.yml file. Please move this file
|
4
|
+
# to the following location if it is not already there:
|
5
|
+
#
|
6
|
+
# ./config/newrelic_plugin.yml
|
7
|
+
#
|
8
|
+
# Where the current directory is the directory where your main program resides and is your current
|
9
|
+
# directory when you run the main program.
|
10
|
+
#
|
11
|
+
# Please make sure to update the license_key information with the license key for your New Relic
|
12
|
+
# account.
|
13
|
+
#
|
14
|
+
#
|
15
|
+
newrelic:
|
16
|
+
#
|
17
|
+
# Update with your New Relic account license key:
|
18
|
+
#
|
19
|
+
license_key: 'YOUR_LICENSE_KEY_HERE'
|
20
|
+
#
|
21
|
+
# Set to '1' for verbose output, remove for normal output.
|
22
|
+
# All output goes to stdout/stderr.
|
23
|
+
#
|
24
|
+
#verbose: 1
|
25
|
+
|
26
|
+
|
27
|
+
#
|
28
|
+
# Agent Configuration:
|
29
|
+
#
|
30
|
+
agents:
|
31
|
+
f5:
|
32
|
+
# Define one or more instances
|
33
|
+
-
|
34
|
+
name: 'My F5'
|
35
|
+
hostname: 'my-f5'
|
36
|
+
port: 161
|
37
|
+
snmp_community: 'public'
|
38
|
+
|
@@ -0,0 +1,381 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'newrelic_plugin'
|
6
|
+
require 'snmp'
|
7
|
+
|
8
|
+
|
9
|
+
module NewRelic::F5Plugin
|
10
|
+
|
11
|
+
# Register and run the agent
|
12
|
+
def self.run
|
13
|
+
# Register this agent.
|
14
|
+
NewRelic::Plugin::Setup.install_agent :f5, self
|
15
|
+
|
16
|
+
# Launch the agent; this never returns.
|
17
|
+
NewRelic::Plugin::Run.setup_and_run
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# Part of me wants to split this out into different devices using this OID:
|
22
|
+
# 1.3.6.1.4.1.3375.2.1.3.5.2.0 = STRING: "BIG-IP 3900" or
|
23
|
+
# 1.3.6.1.4.1.3375.2.1.3.5.1.0 = STRING: "C106"
|
24
|
+
# Especially since a 3900, 6900, Viprion won't respond exactly the same.
|
25
|
+
# To make it worse, versions of BIG-IP older than 11.2 might not implent all
|
26
|
+
# all of these OIDs.
|
27
|
+
# Version: 1.3.6.1.4.1.3375.2.1.4.2.0
|
28
|
+
# Build: 1.3.6.1.4.1.3375.2.1.4.3.0
|
29
|
+
class Agent < NewRelic::Plugin::Agent::Base
|
30
|
+
agent_guid 'com.newrelic.f5'
|
31
|
+
agent_version '1.0.0'
|
32
|
+
agent_config_options :hostname, :port, :snmp_community
|
33
|
+
agent_human_labels('F5') { "#{hostname}" }
|
34
|
+
|
35
|
+
#
|
36
|
+
# Required, but not used
|
37
|
+
#
|
38
|
+
def setup_metrics
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
#
|
43
|
+
# This is called on every polling cycle
|
44
|
+
#
|
45
|
+
def poll_cycle
|
46
|
+
# SNMP Stuff here
|
47
|
+
snmp = SNMP::Manager.new(:host => hostname, :port => port, :community => snmp_community)
|
48
|
+
|
49
|
+
report_global_cpu_metrics(snmp)
|
50
|
+
report_global_memory_metrics(snmp)
|
51
|
+
report_global_connection_metrics(snmp)
|
52
|
+
report_global_throughput_metrics(snmp)
|
53
|
+
report_global_http_metrics(snmp)
|
54
|
+
report_global_http_compression_metrics(snmp)
|
55
|
+
report_global_ssl_metrics(snmp)
|
56
|
+
report_global_tcp_metrics(snmp)
|
57
|
+
|
58
|
+
node_status = NewRelic::F5Plugin::Nodes.get_status(snmp)
|
59
|
+
node_status.each_key { |m|
|
60
|
+
report_metric m, node_status[m][:label], node_status[m][:count]
|
61
|
+
}
|
62
|
+
|
63
|
+
snmp.close
|
64
|
+
rescue => e
|
65
|
+
$stderr.puts "#{e}: #{e.backtrace.join("\n ")}"
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
#
|
70
|
+
# You do not have to specify the SNMP port in the yaml if you don't want to.
|
71
|
+
#
|
72
|
+
def port
|
73
|
+
@port || 161
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
#
|
78
|
+
# Helper function to create and keep track of all the counters
|
79
|
+
#
|
80
|
+
def report_counter_metric(metric, type, value)
|
81
|
+
@processors ||= {}
|
82
|
+
|
83
|
+
if @processors[metric].nil?
|
84
|
+
@processors[metric] = NewRelic::Processor::EpochCounter.new
|
85
|
+
end
|
86
|
+
|
87
|
+
report_metric metric, type, @processors[metric].process(value)
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
#
|
92
|
+
# Gather CPU Related metrics and report them
|
93
|
+
#
|
94
|
+
def report_global_cpu_metrics(snmp)
|
95
|
+
# Create the OIDs if they do not exist
|
96
|
+
@oid_sysGlobalHostCpuUser1m ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.22.0")
|
97
|
+
@oid_sysGlobalHostCpuNice1m ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.23.0")
|
98
|
+
@oid_sysGlobalHostCpuSystem1m ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.24.0")
|
99
|
+
#@oid_sysGlobalHostCpuIdle1m ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.25.0") # Ignoring the idle time
|
100
|
+
@oid_sysGlobalHostCpuIrq1m ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.26.0")
|
101
|
+
@oid_sysGlobalHostCpuSoftirq1m ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.27.0")
|
102
|
+
@oid_sysGlobalHostCpuIowait1m ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.28.0")
|
103
|
+
@oid_sysGlobalHostCpuCount ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.20.4.0")
|
104
|
+
|
105
|
+
if snmp
|
106
|
+
res = snmp.get_value([@oid_sysGlobalHostCpuCount, @oid_sysGlobalHostCpuUser1m, @oid_sysGlobalHostCpuNice1m,
|
107
|
+
@oid_sysGlobalHostCpuSystem1m, @oid_sysGlobalHostCpuIrq1m, @oid_sysGlobalHostCpuSoftirq1m,
|
108
|
+
@oid_sysGlobalHostCpuIowait1m, ])
|
109
|
+
|
110
|
+
# In order to show the CPU usage as a total percentage, we divide by the number of cpus
|
111
|
+
cpu_count = res[0].to_i
|
112
|
+
vals = res[1..6].map { |i| i.to_f / cpu_count }
|
113
|
+
report_metric "CPU/Global/User", "%", vals[0]
|
114
|
+
report_metric "CPU/Global/Nice", "%", vals[1]
|
115
|
+
report_metric "CPU/Global/System", "%", vals[2]
|
116
|
+
report_metric "CPU/Global/IRQ", "%", vals[3]
|
117
|
+
report_metric "CPU/Global/Soft IRQ", "%", vals[4]
|
118
|
+
report_metric "CPU/Global/IO Wait", "%", vals[5]
|
119
|
+
|
120
|
+
# Add it all up, and send a summary metric
|
121
|
+
report_metric "CPU/Total/Global", "%", vals.inject(0.0){ |a,b| a + b }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
#
|
127
|
+
# Gather Memory related metrics and report them
|
128
|
+
#
|
129
|
+
def report_global_memory_metrics(snmp)
|
130
|
+
# Create the OIDs if they don't exist
|
131
|
+
@oid_sysStatMemoryUsed ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.45.0")
|
132
|
+
@oid_sysHostMemoryUsed ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.7.1.2.0")
|
133
|
+
|
134
|
+
if snmp
|
135
|
+
res = snmp.get_value([@oid_sysStatMemoryUsed, @oid_sysHostMemoryUsed])
|
136
|
+
report_metric "Memory/TMM", "bytes", res[0]
|
137
|
+
report_metric "Memory/Host", "bytes", res[1]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
#
|
143
|
+
# Gather Global connection related metrics and report them
|
144
|
+
#
|
145
|
+
def report_global_connection_metrics(snmp)
|
146
|
+
# Create the OIDs if they don't exist
|
147
|
+
@oid_sysStatClientCurConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.8.0")
|
148
|
+
@oid_sysStatServerCurConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.15.0")
|
149
|
+
@oid_sysStatClientTotConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.7.0")
|
150
|
+
@oid_sysStatServerTotConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.14.0")
|
151
|
+
#@oid_sysStatPvaClientCurConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.22.0")
|
152
|
+
#@oid_sysStatPvaServerCurConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.29.0")
|
153
|
+
# These should be moved to an SSL metric...
|
154
|
+
@oid_sysClientsslStatCurConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.9.2.0")
|
155
|
+
@oid_sysServersslStatCurConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.10.2.0")
|
156
|
+
|
157
|
+
if snmp
|
158
|
+
res = snmp.get_value([@oid_sysStatClientCurConns, @oid_sysStatServerCurConns, @oid_sysStatClientTotConns,
|
159
|
+
@oid_sysStatServerTotConns, @oid_sysClientsslStatCurConns, @oid_sysServersslStatCurConns])
|
160
|
+
report_metric "Connections/Current/Client", "conn", res[0]
|
161
|
+
report_metric "Connections/Current/Server", "conn", res[1]
|
162
|
+
report_counter_metric "Connections/Rate/Client", "conn/sec", res[2]
|
163
|
+
report_counter_metric "Connections/Rate/Server", "conn/sec", res[3]
|
164
|
+
report_metric "Connections/Current/Client SSL", "conn", res[4]
|
165
|
+
report_metric "Connections/Current/Server SSL", "conn", res[5]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
#
|
171
|
+
# Gather Global throughput related metrics and report them
|
172
|
+
#
|
173
|
+
def report_global_throughput_metrics(snmp)
|
174
|
+
# Create the OIDs if they don't exist
|
175
|
+
@oid_sysStatClientBytesIn ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.3.0")
|
176
|
+
@oid_sysStatClientBytesOut ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.5.0")
|
177
|
+
@oid_sysStatServerBytesIn ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.10.0")
|
178
|
+
@oid_sysStatServerBytesOut ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.1.12.0")
|
179
|
+
|
180
|
+
if snmp
|
181
|
+
res = snmp.get_value([@oid_sysStatClientBytesIn, @oid_sysStatClientBytesOut, @oid_sysStatServerBytesIn,
|
182
|
+
@oid_sysStatServerBytesOut])
|
183
|
+
|
184
|
+
report_counter_metric "Throughput/Client/In", "bits/sec", (res[0].to_f * 8)
|
185
|
+
report_counter_metric "Throughput/Client/Out", "bits/sec", (res[1].to_f * 8)
|
186
|
+
report_counter_metric "Throughput/Server/In", "bits/sec", (res[2].to_f * 8)
|
187
|
+
report_counter_metric "Throughput/Server/Out", "bits/sec", (res[3].to_f * 8)
|
188
|
+
tot = 0
|
189
|
+
res.each { |x| tot += x.to_f }
|
190
|
+
report_counter_metric "Throughput/Total", "bits/sec", (tot * 8)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
#
|
196
|
+
# Gather Global HTTP related metrics and report them
|
197
|
+
#
|
198
|
+
def report_global_http_metrics(snmp)
|
199
|
+
# Create the OIDs if they don't exist
|
200
|
+
@oid_sysHttpStatResp2xxCnt ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.3.0")
|
201
|
+
@oid_sysHttpStatResp3xxCnt ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.4.0")
|
202
|
+
@oid_sysHttpStatResp4xxCnt ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.5.0")
|
203
|
+
@oid_sysHttpStatResp5xxCnt ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.6.0")
|
204
|
+
@oid_sysHttpStatNumberReqs ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.7.0")
|
205
|
+
@oid_sysHttpStatGetReqs ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.8.0")
|
206
|
+
@oid_sysHttpStatPostReqs ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.9.0")
|
207
|
+
@oid_sysHttpStatV9Reqs ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.10.0")
|
208
|
+
@oid_sysHttpStatV10Reqs ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.11.0")
|
209
|
+
@oid_sysHttpStatV11Reqs ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.12.0")
|
210
|
+
@oid_sysHttpStatV9Resp ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.13.0")
|
211
|
+
@oid_sysHttpStatV10Resp ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.14.0")
|
212
|
+
@oid_sysHttpStatV11Resp ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.15.0")
|
213
|
+
@oid_sysHttpStatRespBucket1k ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.17.0")
|
214
|
+
@oid_sysHttpStatRespBucket4k ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.18.0")
|
215
|
+
@oid_sysHttpStatRespBucket16k ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.19.0")
|
216
|
+
@oid_sysHttpStatRespBucket32k ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.4.20.0")
|
217
|
+
|
218
|
+
if snmp
|
219
|
+
res = snmp.get_value([@oid_sysHttpStatResp2xxCnt, @oid_sysHttpStatResp3xxCnt, @oid_sysHttpStatResp4xxCnt,
|
220
|
+
@oid_sysHttpStatResp5xxCnt, @oid_sysHttpStatNumberReqs, @oid_sysHttpStatGetReqs,
|
221
|
+
@oid_sysHttpStatPostReqs, @oid_sysHttpStatV9Reqs, @oid_sysHttpStatV10Reqs,
|
222
|
+
@oid_sysHttpStatV11Reqs, @oid_sysHttpStatV9Resp, @oid_sysHttpStatV10Resp,
|
223
|
+
@oid_sysHttpStatV11Resp, @oid_sysHttpStatRespBucket1k, @oid_sysHttpStatRespBucket4k,
|
224
|
+
@oid_sysHttpStatRespBucket16k, @oid_sysHttpStatRespBucket32k, ])
|
225
|
+
|
226
|
+
report_counter_metric "HTTP/Response Code/2xx", "resp/sec", res[0]
|
227
|
+
report_counter_metric "HTTP/Response Code/3xx", "resp/sec", res[1]
|
228
|
+
report_counter_metric "HTTP/Response Code/4xx", "resp/sec", res[2]
|
229
|
+
report_counter_metric "HTTP/Response Code/5xx", "resp/sec", res[3]
|
230
|
+
|
231
|
+
report_counter_metric "HTTP/Method/All", "req/sec", res[4]
|
232
|
+
report_counter_metric "HTTP/Method/Get", "req/sec", res[5]
|
233
|
+
report_counter_metric "HTTP/Method/Post", "req/sec", res[6]
|
234
|
+
report_counter_metric "HTTP/Version/v0.9/Request", "req/sec", res[7]
|
235
|
+
report_counter_metric "HTTP/Version/v1.0/Request", "req/sec", res[8]
|
236
|
+
report_counter_metric "HTTP/Version/v1.1/Request", "req/sec", res[9]
|
237
|
+
report_counter_metric "HTTP/Version/v0.9/Response", "resp/sec", res[10]
|
238
|
+
report_counter_metric "HTTP/Version/v1.0/Response", "resp/sec", res[11]
|
239
|
+
report_counter_metric "HTTP/Version/v1.1/Response", "resp/sec", res[12]
|
240
|
+
|
241
|
+
report_counter_metric "HTTP/Response Size/1k Bucket", "resp/sec", res[13]
|
242
|
+
report_counter_metric "HTTP/Response Size/4k Bucket", "resp/sec", res[14]
|
243
|
+
report_counter_metric "HTTP/Response Size/16k Bucket", "resp/sec", res[15]
|
244
|
+
report_counter_metric "HTTP/Response Size/32k Bucket", "resp/sec", res[16]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
#
|
250
|
+
# HTTP Compression Stats
|
251
|
+
#
|
252
|
+
def report_global_http_compression_metrics(snmp)
|
253
|
+
@oid_sysHttpCompressionStatPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.2.0")
|
254
|
+
@oid_sysHttpCompressionStatPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.3.0")
|
255
|
+
@oid_sysHttpCompressionStatHtmlPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.5.0")
|
256
|
+
@oid_sysHttpCompressionStatHtmlPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.6.0")
|
257
|
+
@oid_sysHttpCompressionStatCssPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.7.0")
|
258
|
+
@oid_sysHttpCompressionStatCssPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.8.0")
|
259
|
+
@oid_sysHttpCompressionStatJsPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.9.0")
|
260
|
+
@oid_sysHttpCompressionStatJsPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.10.0")
|
261
|
+
@oid_sysHttpCompressionStatXmlPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.11.0")
|
262
|
+
@oid_sysHttpCompressionStatXmlPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.12.0")
|
263
|
+
@oid_sysHttpCompressionStatSgmlPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.13.0")
|
264
|
+
@oid_sysHttpCompressionStatSgmlPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.14.0")
|
265
|
+
@oid_sysHttpCompressionStatPlainPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.15.0")
|
266
|
+
@oid_sysHttpCompressionStatPlainPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.16.0")
|
267
|
+
@oid_sysHttpCompressionStatOctetPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.17.0")
|
268
|
+
@oid_sysHttpCompressionStatOctetPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.18.0")
|
269
|
+
@oid_sysHttpCompressionStatImagePrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.19.0")
|
270
|
+
@oid_sysHttpCompressionStatImagePostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.20.0")
|
271
|
+
@oid_sysHttpCompressionStatVideoPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.21.0")
|
272
|
+
@oid_sysHttpCompressionStatVideoPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.22.0")
|
273
|
+
@oid_sysHttpCompressionStatAudioPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.23.0")
|
274
|
+
@oid_sysHttpCompressionStatAudioPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.24.0")
|
275
|
+
@oid_sysHttpCompressionStatOtherPrecompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.25.0")
|
276
|
+
@oid_sysHttpCompressionStatOtherPostcompressBytes ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.22.26.0")
|
277
|
+
|
278
|
+
if snmp
|
279
|
+
res = snmp.get_value([@oid_sysHttpCompressionStatPrecompressBytes, @oid_sysHttpCompressionStatPostcompressBytes,
|
280
|
+
@oid_sysHttpCompressionStatHtmlPrecompressBytes, @oid_sysHttpCompressionStatHtmlPostcompressBytes,
|
281
|
+
@oid_sysHttpCompressionStatCssPrecompressBytes, @oid_sysHttpCompressionStatCssPostcompressBytes,
|
282
|
+
@oid_sysHttpCompressionStatJsPrecompressBytes, @oid_sysHttpCompressionStatJsPostcompressBytes,
|
283
|
+
@oid_sysHttpCompressionStatXmlPrecompressBytes, @oid_sysHttpCompressionStatXmlPostcompressBytes,
|
284
|
+
@oid_sysHttpCompressionStatSgmlPrecompressBytes, @oid_sysHttpCompressionStatSgmlPostcompressBytes,
|
285
|
+
@oid_sysHttpCompressionStatPlainPrecompressBytes, @oid_sysHttpCompressionStatPlainPostcompressBytes,
|
286
|
+
@oid_sysHttpCompressionStatOctetPrecompressBytes, @oid_sysHttpCompressionStatOctetPostcompressBytes,
|
287
|
+
@oid_sysHttpCompressionStatImagePrecompressBytes, @oid_sysHttpCompressionStatImagePostcompressBytes,
|
288
|
+
@oid_sysHttpCompressionStatVideoPrecompressBytes, @oid_sysHttpCompressionStatVideoPostcompressBytes,
|
289
|
+
@oid_sysHttpCompressionStatAudioPrecompressBytes, @oid_sysHttpCompressionStatAudioPostcompressBytes,
|
290
|
+
@oid_sysHttpCompressionStatOtherPrecompressBytes, @oid_sysHttpCompressionStatOtherPostcompressBytes, ])
|
291
|
+
|
292
|
+
vals = res.map { |i| i.to_f * 8 } # Convert to bits
|
293
|
+
report_counter_metric "HTTP/Compression/Total/Pre", "bits/sec", vals[0]
|
294
|
+
report_counter_metric "HTTP/Compression/Total/Post", "bits/sec", vals[1]
|
295
|
+
report_counter_metric "HTTP/Compression/HTML/Pre", "bits/sec", vals[2]
|
296
|
+
report_counter_metric "HTTP/Compression/HTML/Post", "bits/sec", vals[3]
|
297
|
+
report_counter_metric "HTTP/Compression/CSS/Pre", "bits/sec", vals[4]
|
298
|
+
report_counter_metric "HTTP/Compression/CSS/Post", "bits/sec", vals[5]
|
299
|
+
report_counter_metric "HTTP/Compression/Javascript/Pre", "bits/sec", vals[6]
|
300
|
+
report_counter_metric "HTTP/Compression/Javascript/Post", "bits/sec", vals[7]
|
301
|
+
report_counter_metric "HTTP/Compression/XML/Pre", "bits/sec", vals[8]
|
302
|
+
report_counter_metric "HTTP/Compression/XML/Post", "bits/sec", vals[9]
|
303
|
+
report_counter_metric "HTTP/Compression/SGML/Pre", "bits/sec", vals[10]
|
304
|
+
report_counter_metric "HTTP/Compression/SGML/Post", "bits/sec", vals[11]
|
305
|
+
report_counter_metric "HTTP/Compression/Plain/Pre", "bits/sec", vals[12]
|
306
|
+
report_counter_metric "HTTP/Compression/Plain/Post", "bits/sec", vals[13]
|
307
|
+
report_counter_metric "HTTP/Compression/Octet/Pre", "bits/sec", vals[14]
|
308
|
+
report_counter_metric "HTTP/Compression/Octet/Post", "bits/sec", vals[15]
|
309
|
+
report_counter_metric "HTTP/Compression/Image/Pre", "bits/sec", vals[16]
|
310
|
+
report_counter_metric "HTTP/Compression/Image/Post", "bits/sec", vals[17]
|
311
|
+
report_counter_metric "HTTP/Compression/Video/Pre", "bits/sec", vals[18]
|
312
|
+
report_counter_metric "HTTP/Compression/Video/Post", "bits/sec", vals[19]
|
313
|
+
report_counter_metric "HTTP/Compression/Audio/Pre", "bits/sec", vals[20]
|
314
|
+
report_counter_metric "HTTP/Compression/Audio/Post", "bits/sec", vals[21]
|
315
|
+
report_counter_metric "HTTP/Compression/Other/Pre", "bits/sec", vals[22]
|
316
|
+
report_counter_metric "HTTP/Compression/Other/Post", "bits/sec", vals[23]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
#
|
321
|
+
# SSL Stats
|
322
|
+
#
|
323
|
+
def report_global_ssl_metrics(snmp)
|
324
|
+
@oid_sysClientsslStatTotNativeConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.9.6.0")
|
325
|
+
@oid_sysClientsslStatTotCompatConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.9.9.0")
|
326
|
+
@oid_sysServersslStatTotNativeConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.10.6.0")
|
327
|
+
@oid_sysServersslStatTotCompatConns ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.10.9.0")
|
328
|
+
|
329
|
+
if snmp
|
330
|
+
res = snmp.get_value([@oid_sysClientsslStatTotNativeConns, @oid_sysClientsslStatTotCompatConns, @oid_sysServersslStatTotNativeConns,
|
331
|
+
@oid_sysServersslStatTotCompatConns])
|
332
|
+
vals = res.map { |i| i.to_i }
|
333
|
+
report_counter_metric "SSL/Global/Client/Native", "trans/sec", vals[0]
|
334
|
+
report_counter_metric "SSL/Global/Client/Compat", "trans/sec", vals[1]
|
335
|
+
report_counter_metric "SSL/Global/Server/Native", "trans/sec", vals[2]
|
336
|
+
report_counter_metric "SSL/Global/Server/Compat", "trans/sec", vals[3]
|
337
|
+
report_counter_metric "SSL/Global/Total/Client", "trans/sec", (vals[0] + vals[1])
|
338
|
+
report_counter_metric "SSL/Global/Total/Server", "trans/sec", (vals[2] + vals[3])
|
339
|
+
report_counter_metric "SSL/Global/Total/All", "trans/sec", vals.inject(0) { |t,i| t + i }
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
|
344
|
+
#
|
345
|
+
# Gather TCP Statistics and report them
|
346
|
+
#
|
347
|
+
def report_global_tcp_metrics(snmp)
|
348
|
+
# Create the OIDs if they don't exist
|
349
|
+
@oid_sysTcpStatOpen ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.2.0") # "The number of current open connections."
|
350
|
+
@oid_sysTcpStatCloseWait ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.3.0") # "The number of current connections in CLOSE-WAIT/LAST-ACK."
|
351
|
+
@oid_sysTcpStatFinWait ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.4.0") # "The number of current connections in FIN-WAIT/CLOSING."
|
352
|
+
@oid_sysTcpStatTimeWait ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.5.0") # "The number of current connections in TIME-WAIT."
|
353
|
+
@oid_sysTcpStatAccepts ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.6.0") # "The number of connections accepted."
|
354
|
+
# @oid_sysTcpStatAcceptfails ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.7.0") # "The number of connections not accepted."
|
355
|
+
# @oid_sysTcpStatConnects ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.8.0") # "The number of connections established."
|
356
|
+
# @oid_sysTcpStatConnfails ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.9.0") # "The number of connection failures."
|
357
|
+
# @oid_sysTcpStatExpires ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.10.0") # "The number of connections expired due to idle timeout."
|
358
|
+
# @oid_sysTcpStatAbandons ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.11.0") # "The number of connections abandoned connections due to retries/keep-alives."
|
359
|
+
# @oid_sysTcpStatRxrst ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.12.0") # "The number of received RST."
|
360
|
+
# @oid_sysTcpStatRxbadsum ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.13.0") # "The number of bad checksum."
|
361
|
+
# @oid_sysTcpStatRxbadseg ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.14.0") # "The number of malformed segments."
|
362
|
+
# @oid_sysTcpStatRxooseg ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.15.0") # "The number of out of order segments."
|
363
|
+
# @oid_sysTcpStatRxcookie ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.16.0") # "The number of received SYN-cookies."
|
364
|
+
# @oid_sysTcpStatRxbadcookie ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.17.0") # "The number of bad SYN-cookies."
|
365
|
+
# @oid_sysTcpStatSyncacheover ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.18.0") # "The number of SYN-cache overflow."
|
366
|
+
# @oid_sysTcpStatTxrexmits ||= SNMP::ObjectId.new("1.3.6.1.4.1.3375.2.1.1.2.12.19.0") # "The number of retransmitted segments."
|
367
|
+
if snmp
|
368
|
+
res = snmp.get_value([@oid_sysTcpStatOpen, @oid_sysTcpStatCloseWait, @oid_sysTcpStatFinWait,
|
369
|
+
@oid_sysTcpStatTimeWait, @oid_sysTcpStatAccepts, ])
|
370
|
+
|
371
|
+
report_metric "TCP/Connection State/Open", "conn", res[0]
|
372
|
+
report_metric "TCP/Connection State/Wait/Close", "conn", res[1]
|
373
|
+
report_metric "TCP/Connection State/Wait/FIN", "conn", res[2]
|
374
|
+
report_metric "TCP/Connection State/Wait/TIME", "conn", res[3]
|
375
|
+
report_counter_metric "TCP/Accepts", "conn/sec", res[4]
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'newrelic_plugin'
|
6
|
+
require 'snmp'
|
7
|
+
|
8
|
+
|
9
|
+
module NewRelic
|
10
|
+
module F5Plugin
|
11
|
+
|
12
|
+
module Nodes
|
13
|
+
NODE_MONITOR_STATES = {
|
14
|
+
0 => 'unchecked',
|
15
|
+
1 => 'checking',
|
16
|
+
2 => 'inband',
|
17
|
+
3 => 'forced-up',
|
18
|
+
4 => 'up',
|
19
|
+
19 => 'down',
|
20
|
+
20 => 'forced-down',
|
21
|
+
21 => 'maint',
|
22
|
+
22 => 'irule-down',
|
23
|
+
23 => 'inband-down',
|
24
|
+
24 => 'down-manual-resume',
|
25
|
+
25 => 'disabled',
|
26
|
+
}
|
27
|
+
|
28
|
+
#
|
29
|
+
# Node Naming in SNMP
|
30
|
+
#
|
31
|
+
# vb.name = SNMPv2-SMI::enterprises.3375.2.2.4.1.2.1.7.{name length}.{name in dot seperated ASCII code} (because why not...)
|
32
|
+
#tmp_name = vb.name.to_s.gsub(/SNMPv2-SMI::enterprises\.3375\.2\.2\.4\.1\.2\.1\.7\.\d+\./, '').split('.').collect! { |c| c.to_i.chr } # Create an array of the ASCII chars of the node name
|
33
|
+
#name = tmp_name.join
|
34
|
+
|
35
|
+
#
|
36
|
+
# Gather Node Status and report
|
37
|
+
#
|
38
|
+
def self.get_status(snmp)
|
39
|
+
if snmp
|
40
|
+
# Init all the states with zeros so we always get them
|
41
|
+
base_name = "Nodes/Monitor Status"
|
42
|
+
metrics = { }
|
43
|
+
NODE_MONITOR_STATES.each do |key,value|
|
44
|
+
metrics["#{base_name}/#{value}"] = { :label => "nodes", :count => 0 }
|
45
|
+
end
|
46
|
+
|
47
|
+
# ltmNodeAddrMonitorStatus
|
48
|
+
snmp.walk(["1.3.6.1.4.1.3375.2.2.4.1.2.1.7"]) do |row|
|
49
|
+
row.each do |vb|
|
50
|
+
metric_name = "#{base_name}/#{NODE_MONITOR_STATES[vb.value.to_i]}"
|
51
|
+
metrics[metric_name][:count] += 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
return metrics
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
## This is the rakegem gemspec template. Make sure you read and understand
|
2
|
+
## all of the comments. Some sections require modification, and others can
|
3
|
+
## be deleted if you don't need them. Once you understand the contents of
|
4
|
+
## this file, feel free to delete any comments that begin with two hash marks.
|
5
|
+
## You can find comprehensive Gem::Specification documentation, at
|
6
|
+
## http://docs.rubygems.org/read/chapter/20
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
|
+
s.rubygems_version = '1.3.5'
|
11
|
+
|
12
|
+
## Leave these as is they will be modified for you by the rake gemspec task.
|
13
|
+
## If your rubyforge_project name is different, then edit it and comment out
|
14
|
+
## the sub! line in the Rakefile
|
15
|
+
s.name = 'newrelic_f5_plugin'
|
16
|
+
s.version = '1.0.0'
|
17
|
+
s.date = '2013-06-18'
|
18
|
+
s.rubyforge_project = 'newrelic_f5_plugin'
|
19
|
+
|
20
|
+
## Make sure your summary is short. The description may be as long
|
21
|
+
## as you like.
|
22
|
+
s.summary = "New Relic F5 plugin"
|
23
|
+
s.description = <<-EOF
|
24
|
+
This is the New Relic plugin for monitoring F5 devices developed by New Relic, Inc.
|
25
|
+
EOF
|
26
|
+
|
27
|
+
## List the primary authors. If there are a bunch of authors, it's probably
|
28
|
+
## better to set the email to an email list or something. If you don't have
|
29
|
+
## a custom homepage, consider using your GitHub URL or the like.
|
30
|
+
s.authors = ["Jonathan Thurman"]
|
31
|
+
s.email = 'support@newrelic.com'
|
32
|
+
s.homepage = 'http://newrelic.com'
|
33
|
+
|
34
|
+
## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
|
35
|
+
## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
|
36
|
+
s.require_paths = %w[lib]
|
37
|
+
|
38
|
+
## This sections is only necessary if you have C extensions.
|
39
|
+
# s.require_paths << 'ext'
|
40
|
+
# s.extensions = %w[ext/extconf.rb]
|
41
|
+
|
42
|
+
## If your gem includes any executables, list them here.
|
43
|
+
s.executables = ["f5_monitor"]
|
44
|
+
|
45
|
+
## Specify any RDoc options here. You'll want to add your README and
|
46
|
+
## LICENSE files to the extra_rdoc_files list.
|
47
|
+
s.rdoc_options = ["--charset=UTF-8",
|
48
|
+
"--main", "README.rdoc"]
|
49
|
+
s.extra_rdoc_files = %w[README.rdoc LICENSE CHANGES]
|
50
|
+
|
51
|
+
## The newrelic_plugin needs to be installed. Prior to public release, the
|
52
|
+
# gem needs to be downloaded from git@github.com:newrelic-platform/newrelic_plugin.git
|
53
|
+
# and built using the "rake build" command
|
54
|
+
s.add_dependency('newrelic_plugin', ">= 0.2.11")
|
55
|
+
s.add_dependency('snmp', ">= 1.1.0")
|
56
|
+
|
57
|
+
s.post_install_message = <<-EOF
|
58
|
+
To get started with this plugin, create a working directory and do
|
59
|
+
f5_monitor -h
|
60
|
+
to find out how to install and run the plugin agent.
|
61
|
+
EOF
|
62
|
+
|
63
|
+
## Leave this section as-is. It will be automatically generated from the
|
64
|
+
## contents of your Git repository via the gemspec task. DO NOT REMOVE
|
65
|
+
## THE MANIFEST COMMENTS, they are used as delimiters by the task.
|
66
|
+
# = MANIFEST =
|
67
|
+
s.files = %w[
|
68
|
+
CHANGES
|
69
|
+
Gemfile
|
70
|
+
LICENSE
|
71
|
+
NOTES
|
72
|
+
README.rdoc
|
73
|
+
Rakefile
|
74
|
+
bin/f5_monitor
|
75
|
+
config/newrelic_plugin.yml
|
76
|
+
lib/newrelic_f5_plugin.rb
|
77
|
+
lib/newrelic_f5_plugin/agent.rb
|
78
|
+
lib/newrelic_f5_plugin/nodes.rb
|
79
|
+
newrelic_f5_plugin.gemspec
|
80
|
+
test/f5_monitor_test.rb
|
81
|
+
test/plugin_test.rb
|
82
|
+
test/test_helper.rb
|
83
|
+
]
|
84
|
+
# = MANIFEST =
|
85
|
+
|
86
|
+
## Test files will be grabbed from the file list. Make sure the path glob
|
87
|
+
## matches what you actually use.
|
88
|
+
s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
|
89
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test_helper.rb'
|
2
|
+
class F5MonitorTest < Test::Unit::TestCase
|
3
|
+
|
4
|
+
context "f5_monitor" do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@verbose = $VERBOSE
|
8
|
+
$VERBOSE = nil
|
9
|
+
@file = File.expand_path("../../bin/f5_monitor", __FILE__)
|
10
|
+
end
|
11
|
+
|
12
|
+
teardown do
|
13
|
+
$VERBOSE = @verbose
|
14
|
+
end
|
15
|
+
|
16
|
+
should "show help" do
|
17
|
+
`#{@file} -h` =~ /Usage:/
|
18
|
+
end
|
19
|
+
|
20
|
+
should "run" do
|
21
|
+
::ARGV = %w[run]
|
22
|
+
NewRelic::F5Plugin.expects :run
|
23
|
+
load @file
|
24
|
+
end
|
25
|
+
|
26
|
+
should "install" do
|
27
|
+
::ARGV = %w[install --license LICENSE_KEY]
|
28
|
+
FileUtils.expects :mkdir_p
|
29
|
+
File.expects :open
|
30
|
+
load @file
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
data/test/plugin_test.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper.rb'
|
2
|
+
class PluginTest < Test::Unit::TestCase
|
3
|
+
|
4
|
+
context "Plugin" do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
NewRelic::F5Plugin
|
8
|
+
NewRelic::Plugin::Config.config_yaml = <<-EOF
|
9
|
+
newrelic:
|
10
|
+
license_key: 'test_license_key'
|
11
|
+
verbose: 0
|
12
|
+
host: "localhost"
|
13
|
+
agents:
|
14
|
+
f5:
|
15
|
+
-
|
16
|
+
name: 'My F5 LTM'
|
17
|
+
hostname: 'my-f5'
|
18
|
+
port: 161
|
19
|
+
snmp_community: 'public'
|
20
|
+
EOF
|
21
|
+
NewRelic::Plugin::Setup.install_agent :f5, NewRelic::F5Plugin
|
22
|
+
end
|
23
|
+
|
24
|
+
should "create a run" do
|
25
|
+
# The run loop is stubbed out so this just verifies the agent initializes correctly.
|
26
|
+
NewRelic::Plugin::Run.any_instance.expects :setup_from_config
|
27
|
+
NewRelic::Plugin::Run.any_instance.expects :loop_forever
|
28
|
+
NewRelic::F5Plugin.run
|
29
|
+
end
|
30
|
+
|
31
|
+
# This mimics NewRelic::Plugin::Run.setup_and_run except for the loop_forever part
|
32
|
+
context "run" do
|
33
|
+
setup do
|
34
|
+
NewRelic::Plugin::Run.any_instance.stubs :loop_forever
|
35
|
+
@run = NewRelic::Plugin::Run.new
|
36
|
+
@run.setup_from_config
|
37
|
+
agents = @run.configured_agents
|
38
|
+
assert_equal 1, agents.size
|
39
|
+
@agent = agents.first
|
40
|
+
end
|
41
|
+
|
42
|
+
should "have one configured agent" do
|
43
|
+
assert_equal "My F5 LTM", @agent.name
|
44
|
+
end
|
45
|
+
|
46
|
+
#context "test db" do
|
47
|
+
# setup do
|
48
|
+
# # Setup a test database
|
49
|
+
# @client = Mysql2::Client.new :host => 'localhost', :username => 'root'
|
50
|
+
# @client.query "create database nr_mysql_plugin" rescue nil
|
51
|
+
# @client.query "create table nr_mysql_plugin.example (id int)"
|
52
|
+
# @client.query "create table nr_mysql_plugin.ignored (id int)"
|
53
|
+
# @client.query "insert into nr_mysql_plugin.example values (1),(2),(3),(4),(5)"
|
54
|
+
# end
|
55
|
+
# teardown do
|
56
|
+
# @client.query "drop database nr_mysql_plugin" rescue nil
|
57
|
+
# end
|
58
|
+
# should "get table stats" do
|
59
|
+
# schemas = @agent.mysql_table_stats
|
60
|
+
# assert_equal 1, schemas.size
|
61
|
+
# tables = schemas['nr_mysql_plugin']
|
62
|
+
# assert_equal 1, tables.size
|
63
|
+
# rec = tables.first
|
64
|
+
# assert_equal "example", rec.name
|
65
|
+
# assert_equal 5, rec.rows
|
66
|
+
# end
|
67
|
+
# should "poll" do
|
68
|
+
# # This stubs out the remote connection--we're not testing the plugin agent here
|
69
|
+
# NewRelic::Plugin::DataCollector.any_instance.stubs :process
|
70
|
+
# @agent.run 60 # seconds
|
71
|
+
# end
|
72
|
+
#end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: newrelic_f5_plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jonathan Thurman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: newrelic_plugin
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.2.11
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.2.11
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: snmp
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.1.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.1.0
|
46
|
+
description: ! 'This is the New Relic plugin for monitoring F5 devices developed by
|
47
|
+
New Relic, Inc.
|
48
|
+
|
49
|
+
'
|
50
|
+
email: support@newrelic.com
|
51
|
+
executables:
|
52
|
+
- f5_monitor
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files:
|
55
|
+
- README.rdoc
|
56
|
+
- LICENSE
|
57
|
+
- CHANGES
|
58
|
+
files:
|
59
|
+
- CHANGES
|
60
|
+
- Gemfile
|
61
|
+
- LICENSE
|
62
|
+
- NOTES
|
63
|
+
- README.rdoc
|
64
|
+
- Rakefile
|
65
|
+
- bin/f5_monitor
|
66
|
+
- config/newrelic_plugin.yml
|
67
|
+
- lib/newrelic_f5_plugin.rb
|
68
|
+
- lib/newrelic_f5_plugin/agent.rb
|
69
|
+
- lib/newrelic_f5_plugin/nodes.rb
|
70
|
+
- newrelic_f5_plugin.gemspec
|
71
|
+
- test/f5_monitor_test.rb
|
72
|
+
- test/plugin_test.rb
|
73
|
+
- test/test_helper.rb
|
74
|
+
homepage: http://newrelic.com
|
75
|
+
licenses: []
|
76
|
+
post_install_message: ! "To get started with this plugin, create a working directory
|
77
|
+
and do \n f5_monitor -h\nto find out how to install and run the plugin agent.\n"
|
78
|
+
rdoc_options:
|
79
|
+
- --charset=UTF-8
|
80
|
+
- --main
|
81
|
+
- README.rdoc
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project: newrelic_f5_plugin
|
98
|
+
rubygems_version: 1.8.23
|
99
|
+
signing_key:
|
100
|
+
specification_version: 2
|
101
|
+
summary: New Relic F5 plugin
|
102
|
+
test_files:
|
103
|
+
- test/test_helper.rb
|