newrelic_f5_plugin 1.0.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.
- 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
|