Ruby plugins: apply code changes as suggested by "rubocop --auto-correct"

This commit is contained in:
Lars Kruse 2020-08-25 17:06:15 +02:00
parent b0b39b018e
commit 809639ab65
33 changed files with 904 additions and 910 deletions

7
.rubocop.yml Normal file
View File

@ -0,0 +1,7 @@
# Allow "=begin"/"=end" multiline comments in order to protect munin's
# magic markers ("#%#").
Style/BlockComments:
Enabled: false
AllCops:
NewCops: enable

View File

@ -9,24 +9,22 @@ This plugin shows various statistics from 'netstat -m'
Required privileges: none Required privileges: none
OS: OS:
Supposed: BSD Supposed: BSD
Tested: FreeBSD 8.2 Tested: FreeBSD 8.2
Author: Artem Sheremet <dot.doom@gmail.com> Author: Artem Sheremet <dot.doom@gmail.com>
#%# family=auto #%# family=auto
#%# capabilities=autoconf suggest #%# capabilities=autoconf suggest
=end =end
# original filename # original filename
PLUGIN_NAME = 'netstat_bsd_m_' PLUGIN_NAME = 'netstat_bsd_m_'.freeze
class String class String
def escape def escape
self.gsub /[^\w]/, '_' gsub(/[^\w]/, '_')
end end
unless method_defined? :start_with? unless method_defined? :start_with?
@ -37,17 +35,20 @@ class String
end end
def netstat_m(filter = nil) def netstat_m(filter = nil)
Hash[`netstat -m`.split($/).map { |line| Hash[`netstat -m`.split($/).map do |line|
if line =~ /^([\d\/K]+) (.*) \(([\w\/+]+)\)$/ if line =~ %r{^([\d/K]+) (.*) \(([\w/+]+)\)$}
# 7891K/22385K/30276K bytes allocated to network (current/cache/total) # 7891K/22385K/30276K bytes allocated to network (current/cache/total)
values, desc, names = $1, $2, $3 values = Regexp.last_match(1)
[desc, names.split('/').zip(values.split '/')] if filter.nil? or desc.escape == filter desc = Regexp.last_match(2)
names = Regexp.last_match(3)
[desc, names.split('/').zip(values.split('/'))] if filter.nil? || (desc.escape == filter)
elsif line =~ /^(\d+) (.*)$/ elsif line =~ /^(\d+) (.*)$/
# 12327 requests for I/O initiated by sendfile # 12327 requests for I/O initiated by sendfile
value, desc = $1, $2 value = Regexp.last_match(1)
[desc, [[:value, value]]] if filter.nil? or desc.escape == filter desc = Regexp.last_match(2)
[desc, [[:value, value]]] if filter.nil? || (desc.escape == filter)
end end
}.compact] end.compact]
end end
stat_name = File.basename($0, '.*').escape stat_name = File.basename($0, '.*').escape
@ -74,7 +75,7 @@ when 'config'
CONFIG CONFIG
puts values.map { |name, _| puts values.map { |name, _|
esc_name = name.to_s.escape esc_name = name.to_s.escape
"#{esc_name}.draw " + if %w(total max).include? name "#{esc_name}.draw " + if %w[total max].include? name
'LINE' 'LINE'
elsif stack elsif stack
if first if first

View File

@ -21,9 +21,9 @@ require 'yaml'
# #
LOG_FILE = ENV['log'] || '/var/log/ejabberd/ejabberd.log' LOG_FILE = ENV['log'] || '/var/log/ejabberd/ejabberd.log'
CACHE_FILE = '/tmp/ejabberd_scanlog_cache' # cache file position CACHE_FILE = '/tmp/ejabberd_scanlog_cache'.freeze # cache file position
DEFAULT_CACHE = { :start => 0 } DEFAULT_CACHE = { start: 0 }.freeze
$debug_mode = ARGV.first == 'debug' $debug_mode = ARGV.first == 'debug'
@ -32,7 +32,7 @@ if $debug_mode
else else
begin begin
log_info = YAML.load IO.read(CACHE_FILE) log_info = YAML.load IO.read(CACHE_FILE)
rescue rescue StandardError
log_info = DEFAULT_CACHE log_info = DEFAULT_CACHE
end end
@ -43,7 +43,7 @@ else
end end
if ARGV.first == 'reset' if ARGV.first == 'reset'
log_info = { :start => File.size(LOG_FILE) - 1 } log_info = { start: File.size(LOG_FILE) - 1 }
puts 'Log reset' puts 'Log reset'
end end
@ -80,8 +80,8 @@ KNOWN_LOG_TYPES = [
['mysql', ['mysql',
'Failed connecting to']], 'Failed connecting to']],
['Timeout while running a hook', ['Timeout while running a hook',
['ejabberd_hooks', %w[ejabberd_hooks
'timeout']], timeout]],
['SQL transaction restarts exceeded', ['SQL transaction restarts exceeded',
['SQL transaction restarts exceeded']], ['SQL transaction restarts exceeded']],
['Unexpected info', ['Unexpected info',
@ -89,8 +89,8 @@ KNOWN_LOG_TYPES = [
['Other sql_cmd timeout', ['Other sql_cmd timeout',
['sql_cmd']], ['sql_cmd']],
['System limit hit: ports', # check with length(erlang:ports())., set in ejabberdctl config file ['System limit hit: ports', # check with length(erlang:ports())., set in ejabberdctl config file
['system_limit', %w[system_limit
'open_port']], open_port]],
['Other system limit hit', # processes? check with erlang:system_info(process_count)., erlang:system_info(process_limit)., set in ejabberdctl cfg ['Other system limit hit', # processes? check with erlang:system_info(process_count)., erlang:system_info(process_limit)., set in ejabberdctl cfg
['system_limit']], ['system_limit']],
['Generic server terminating', ['Generic server terminating',
@ -115,20 +115,22 @@ KNOWN_LOG_TYPES = [
['mysql_conn: init failed receiving data']], ['mysql_conn: init failed receiving data']],
['TCP Error', ['TCP Error',
['Failed TCP']] ['Failed TCP']]
] ].freeze
def log_type(text) def log_type(text)
KNOWN_LOG_TYPES.find_index { |entry| KNOWN_LOG_TYPES.find_index do |entry|
entry[1].all? { |substr| text.include? substr } entry[1].all? { |substr| text.include? substr }
} end
end end
new_data.split("\n=").each { |report| new_data.split("\n=").each do |report|
next if report.empty? next if report.empty?
report =~ /\A(\w+) REPORT==== (.*) ===\n(.*)\z/m report =~ /\A(\w+) REPORT==== (.*) ===\n(.*)\z/m
type, time, text = $1, $2, $3 type = Regexp.last_match(1)
next unless type and time and text time = Regexp.last_match(2)
text = Regexp.last_match(3)
next unless type && time && text
log_info[type] = (log_info[type] || 0) + 1 log_info[type] = (log_info[type] || 0) + 1
if sub_type = log_type(text) if sub_type = log_type(text)
@ -136,7 +138,7 @@ new_data.split("\n=").each { |report|
elsif $debug_mode elsif $debug_mode
warn "Unparsed log entry #{type}: #{text} at #{time}" warn "Unparsed log entry #{type}: #{text} at #{time}"
end end
} end
log_info[:start] += new_data.size log_info[:start] += new_data.size
File.open(CACHE_FILE, 'w') { |f| f.write log_info.to_yaml } unless $debug_mode File.open(CACHE_FILE, 'w') { |f| f.write log_info.to_yaml } unless $debug_mode
@ -150,7 +152,7 @@ if ARGV.first == 'config'
CONFIG CONFIG
end end
(KNOWN_LOG_TYPES + %w(ERROR WARNING INFO DEBUG)).each.with_index { |log_type, index| (KNOWN_LOG_TYPES + %w[ERROR WARNING INFO DEBUG]).each.with_index do |log_type, index|
label, index = if log_type.is_a? Array label, index = if log_type.is_a? Array
[log_type.first, index] [log_type.first, index]
else else
@ -162,4 +164,4 @@ end
else else
puts "T#{index}.value #{log_info[index] or 0}" puts "T#{index}.value #{log_info[index] or 0}"
end end
} end

View File

@ -34,33 +34,32 @@ Contributors: Adam Jacob (<adam@hjksolutions.com>)
=end =end
module Munin module Munin
class MongrelProcessMemory class MongrelProcessMemory
def run def run
pid_port_map = get_pids() pid_port_map = get_pids
port_list = Hash.new port_list = {}
pid_port_map.sort.each do |pid, port| pid_port_map.sort.each do |pid, port|
rss = `pmap -x #{pid} | grep total`.split(" ")[3] rss = `pmap -x #{pid} | grep total`.split(' ')[3]
puts "mongrel_#{port}.value #{rss}" puts "mongrel_#{port}.value #{rss}"
end end
end end
def get_pids def get_pids
h = Hash.new h = {}
pids = [] pids = []
pids += `pgrep mongrel_rails`.split("\n") pids += `pgrep mongrel_rails`.split("\n")
pids += `pgrep ruby`.split("\n") pids += `pgrep ruby`.split("\n")
pids.each { |pid| pids.each do |pid|
l = `pargs -l #{pid}` l = `pargs -l #{pid}`
l =~ /-p (\d+)/ l =~ /-p (\d+)/
h[pid] = $1 if $1 h[pid] = Regexp.last_match(1) if Regexp.last_match(1)
} end
h h
end end
def autoconf def autoconf
get_pids().length > 0 get_pids.length > 0
end end
end end
end end
@ -68,25 +67,25 @@ end
mpm = Munin::MongrelProcessMemory.new mpm = Munin::MongrelProcessMemory.new
case ARGV[0] case ARGV[0]
when "config" when 'config'
puts "graph_title Mongrel Memory" puts 'graph_title Mongrel Memory'
puts "graph_vlabel RSS" puts 'graph_vlabel RSS'
puts "graph_category memory" puts 'graph_category memory'
puts "graph_args --base 1024 -l 0" puts 'graph_args --base 1024 -l 0'
puts "graph_scale yes" puts 'graph_scale yes'
puts "graph_info Tracks the size of individual mongrel processes" puts 'graph_info Tracks the size of individual mongrel processes'
mpm.get_pids.values.sort.each do |port| mpm.get_pids.values.sort.each do |port|
puts "mongrel_#{port}.label mongrel_#{port}" puts "mongrel_#{port}.label mongrel_#{port}"
puts "mongrel_#{port}.info Process memory" puts "mongrel_#{port}.info Process memory"
puts "mongrel_#{port}.type GAUGE" puts "mongrel_#{port}.type GAUGE"
puts "mongrel_#{port}.min 0" puts "mongrel_#{port}.min 0"
end end
when "autoconf" when 'autoconf'
if mpm.autoconf if mpm.autoconf
puts "yes" puts 'yes'
exit 0 exit 0
end end
puts "no" puts 'no'
exit 0 exit 0
else else
mpm.run mpm.run

View File

@ -28,27 +28,24 @@ Contributors: Adam Jacob (<adam@hjksolutions.com>)
=end =end
module Munin module Munin
class MongrelProcessMemory class MongrelProcessMemory
def run def run
h = get_pids() h = get_pids
ps_output = "" ps_output = ''
# I have no doubt that this is a terrible way of doing this. # I have no doubt that this is a terrible way of doing this.
h.each do |k, v| h.each do |k, _v|
ps_output = ps_output + `ps --no-heading l #{k}` ps_output += `ps --no-heading l #{k}`
end end
if ps_output if ps_output
port_list = Hash.new port_list = {}
ps_output.each_line do |l| ps_output.each_line do |l|
if l =~ /-p (\d+)/ next unless l =~ /-p (\d+)/
port = $1
l_ary = l.split(/\s+/) port = Regexp.last_match(1)
if l_ary.length > 6 l_ary = l.split(/\s+/)
port_list[port] = l_ary[7].to_i * 1024 port_list[port] = l_ary[7].to_i * 1024 if l_ary.length > 6
end
end
end end
port_list.sort.each do |port| port_list.sort.each do |port|
puts "mongrel_#{port[0]}.value #{port[1]}" puts "mongrel_#{port[0]}.value #{port[1]}"
@ -58,14 +55,14 @@ module Munin
end end
def get_pids def get_pids
h = Hash.new h = {}
pids = [] pids = []
pids = `pgrep mongrel_rails` pids = `pgrep mongrel_rails`
pids.each { |p| pids.each do |p|
l = `ps #{p}` l = `ps #{p}`
l =~ /-p (\d+)/ l =~ /-p (\d+)/
h[p] = $1 h[p] = Regexp.last_match(1)
} end
h h
end end
@ -78,25 +75,25 @@ end
mpm = Munin::MongrelProcessMemory.new mpm = Munin::MongrelProcessMemory.new
case ARGV[0] case ARGV[0]
when "config" when 'config'
puts "graph_title Mongrel Memory" puts 'graph_title Mongrel Memory'
puts "graph_vlabel RSS" puts 'graph_vlabel RSS'
puts "graph_category memory" puts 'graph_category memory'
puts "graph_args --base 1024 -l 0" puts 'graph_args --base 1024 -l 0'
puts "graph_scale yes" puts 'graph_scale yes'
puts "graph_info Tracks the size of individual mongrel processes" puts 'graph_info Tracks the size of individual mongrel processes'
mpm.get_pids.values.sort.each do |port| mpm.get_pids.values.sort.each do |port|
puts "mongrel_#{port}.label mongrel_#{port}" puts "mongrel_#{port}.label mongrel_#{port}"
puts "mongrel_#{port}.info Process memory" puts "mongrel_#{port}.info Process memory"
puts "mongrel_#{port}.type GAUGE" puts "mongrel_#{port}.type GAUGE"
puts "mongrel_#{port}.min 0" puts "mongrel_#{port}.min 0"
end end
when "autoconf" when 'autoconf'
if mpm.autoconf if mpm.autoconf
puts "yes" puts 'yes'
exit 0 exit 0
end end
puts "no" puts 'no'
exit 0 exit 0
else else
mpm.run mpm.run

View File

@ -18,10 +18,10 @@ require 'open-uri'
def get_conf def get_conf
# Default values # Default values
conf = { :host => '127.0.0.1', :port => 8000, conf = { host: '127.0.0.1', port: 8000,
:username => 'admin', :password => 'hackme' } username: 'admin', password: 'hackme' }
conf.keys.each do |key| conf.keys.each do |key|
env_key = sprintf('icecast_%s', key) env_key = format('icecast_%s', key)
conf[key] = ENV[env_key] if ENV.has_key?(env_key) conf[key] = ENV[env_key] if ENV.has_key?(env_key)
end end
conf conf
@ -29,12 +29,12 @@ end
def get_data(conf) def get_data(conf)
begin begin
data = Hpricot(open(sprintf('http://%s:%s/admin/stats', data = Hpricot(open(format('http://%s:%s/admin/stats',
conf[:host], conf[:port]), conf[:host], conf[:port]),
:http_basic_authentication => [conf[:username], http_basic_authentication: [conf[:username],
conf[:password]])) conf[:password]]))
rescue OpenURI::HTTPError rescue OpenURI::HTTPError
puts "Cannot connect: HTTP connection error" puts 'Cannot connect: HTTP connection error'
exit 1 exit 1
end end
data data
@ -42,13 +42,13 @@ end
def get_values(data) def get_values(data)
vals = {} vals = {}
[:sources, :clients].each do |key| %i[sources clients].each do |key|
elem = data / key elem = data / key
if elem.nil? vals[key] = if elem.nil?
vals[key] = 0 0
else else
vals[key] = elem.innerHTML elem.innerHTML
end end
end end
vals vals
end end
@ -56,15 +56,16 @@ end
data = get_data(get_conf) data = get_data(get_conf)
vals = get_values(data) vals = get_values(data)
if ARGV[0] == 'autoconf' case ARGV[0]
when 'autoconf'
puts 'yes' puts 'yes'
elsif ARGV[0] == 'config' when 'config'
puts "graph_title Total sources and clients for Icecast" puts 'graph_title Total sources and clients for Icecast'
puts "graph_vlabel listeners" puts 'graph_vlabel listeners'
puts "graph_category streaming" puts 'graph_category streaming'
puts "sources.label Total number of sources" puts 'sources.label Total number of sources'
puts "clients.label Total number of clients" puts 'clients.label Total number of clients'
else else
puts "sources.value " + vals[:sources] puts 'sources.value ' + vals[:sources]
puts "clients.value " + vals[:clients] puts 'clients.value ' + vals[:clients]
end end

View File

@ -8,29 +8,29 @@
require 'socket' require 'socket'
if ARGV[0] == 'config' if ARGV[0] == 'config'
puts "graph_title Connected players" puts 'graph_title Connected players'
puts "graph_vlabel players" puts 'graph_vlabel players'
puts "players.label players" puts 'players.label players'
puts "graph_info Number of players connected to Minecraft" puts 'graph_info Number of players connected to Minecraft'
puts "graph_category games" puts 'graph_category games'
exit exit
end end
host = ENV['host'] host = ENV['host']
host = 'localhost' unless host host ||= 'localhost'
port = ENV['port'] port = ENV['port']
port = '25566' unless port port ||= '25566'
socket = TCPSocket.new(host, port) socket = TCPSocket.new(host, port)
socket.puts "QUERY" socket.puts 'QUERY'
response = socket.read response = socket.read
response = response.split("\n") response = response.split("\n")
server_port = response[0].split(" ", 2)[1].to_i server_port = response[0].split(' ', 2)[1].to_i
player_count = response[1].split(" ", 2)[1].to_i player_count = response[1].split(' ', 2)[1].to_i
max_players = response[2].split(" ", 2)[1].to_i max_players = response[2].split(' ', 2)[1].to_i
player_list = response[3].split(" ", 2)[1].chomp[1..-2] player_list = response[3].split(' ', 2)[1].chomp[1..-2]
puts "players.value #{player_count}" puts "players.value #{player_count}"

View File

@ -24,44 +24,43 @@ Magic markers
=end =end
# #
# Initialize vars # Initialize vars
# #
$logfile = ENV['logfile'] || "/var/log/moblock.log" $logfile = ENV['logfile'] || '/var/log/moblock.log'
# #
# Configure generated graph # Configure generated graph
# #
def config def config
puts "graph_args --base 1000 -r --lower-limit 0" puts 'graph_args --base 1000 -r --lower-limit 0'
puts "graph_title Moblock" puts 'graph_title Moblock'
puts "graph_vlabel Blocked Connections" puts 'graph_vlabel Blocked Connections'
puts "graph_category fw" puts 'graph_category fw'
puts "graph_info This graph shows the number of connections blocked by Moblock" puts 'graph_info This graph shows the number of connections blocked by Moblock'
puts "blocked_in.label Blocked In" puts 'blocked_in.label Blocked In'
puts "blocked_in.draw LINE1" puts 'blocked_in.draw LINE1'
puts "blocked_in.info Number of blocked incoming connections" puts 'blocked_in.info Number of blocked incoming connections'
puts "blocked_in.type GAUGE" puts 'blocked_in.type GAUGE'
puts "blocked_out.label Blocked Out" puts 'blocked_out.label Blocked Out'
puts "blocked_out.draw LINE1" puts 'blocked_out.draw LINE1'
puts "blocked_out.info Number of blocked outgoing connections" puts 'blocked_out.info Number of blocked outgoing connections'
puts "blocked_out.type GAUGE" puts 'blocked_out.type GAUGE'
puts "blocked_total.label Total Blocked" puts 'blocked_total.label Total Blocked'
puts "blocked_total.draw LINE1" puts 'blocked_total.draw LINE1'
puts "blocked_total.info Total Number of blocked connections" puts 'blocked_total.info Total Number of blocked connections'
puts "blocked_total.type GAUGE" puts 'blocked_total.type GAUGE'
end end
# #
# Grep moblock logs for stats # Grep moblock logs for stats
# #
def fetch(debug = false) def fetch(_debug = false)
num_in = %x{cat #{$logfile} | grep --extended-regexp 'IN: ' | wc -l} num_in = `cat #{$logfile} | grep --extended-regexp 'IN: ' | wc -l`
num_out = %x{cat #{$logfile} | grep --extended-regexp 'OUT: ' | wc -l} num_out = `cat #{$logfile} | grep --extended-regexp 'OUT: ' | wc -l`
num_total = num_in.to_i + num_out.to_i num_total = num_in.to_i + num_out.to_i
puts "blocked_in.value #{num_in}" puts "blocked_in.value #{num_in}"
@ -73,11 +72,11 @@ end
# If moblock executable on path then allow autoconfiguration # If moblock executable on path then allow autoconfiguration
# #
def autoconf def autoconf
moblock_path = %x{which moblock} moblock_path = `which moblock`
if moblock_path.index('moblock') if moblock_path.index('moblock')
puts "yes" puts 'yes'
else else
puts "no" puts 'no'
end end
end end

View File

@ -21,34 +21,32 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Prerequistes: Prerequistes:
1) /etc/odbc.ini and /etc/freetds.conf 1) /etc/odbc.ini and /etc/freetds.conf
2) rubygems 2) rubygems
3) ruby-dbi 3) ruby-dbi
Usage: Usage:
1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins) 1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins)
2) chmod to allow executable to others 2) chmod to allow executable to others
3) create symbolic link in /etc/munin/plugins 3) create symbolic link in /etc/munin/plugins
ln -s /usr/share/munin/plugins/mssql_transaction.rb /etc/munin/plugins/mssql_transaction.rb ln -s /usr/share/munin/plugins/mssql_transaction.rb /etc/munin/plugins/mssql_transaction.rb
Parameters: Parameters:
autoconf autoconf
config (required) config (required)
Config variables: Config variables:
sqluser : mssql user who has view server state privilege sqluser : mssql user who has view server state privilege
sqlpass : password for the mssql user sqlpass : password for the mssql user
dsn : datasource name as defined in /etc/odbc.ini dsn : datasource name as defined in /etc/odbc.ini
instance: instance to monitor instance: instance to monitor
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
require 'rubygems' require 'rubygems'
require 'dbi' require 'dbi'
@ -74,7 +72,7 @@ transaction_query = "select cntr_value from sys.dm_os_performance_counters
and object_name = 'SQLServer:Databases' and object_name = 'SQLServer:Databases'
and instance_name = ?" and instance_name = ?"
all_instance_names = Array.new all_instance_names = []
sth = dbh.execute(instance_name_query) sth = dbh.execute(instance_name_query)
sth.fetch do |row| sth.fetch do |row|
all_instance_names.push(row[0].strip) all_instance_names.push(row[0].strip)
@ -84,25 +82,26 @@ sth.finish
# #
# autoconf # autoconf
# #
if ARGV[0] == "autoconf" case ARGV[0]
when 'autoconf'
if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1 if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1
puts "yes" puts 'yes'
else else
puts "no" puts 'no'
puts "Usage: #{__FILE__} autoconf|conf" puts "Usage: #{__FILE__} autoconf|conf"
end end
exit 0 exit 0
# #
# config definition # config definition
# #
elsif ARGV[0] == "config" when 'config'
puts "graph_args --base 1000 -r --lower-limit 0" puts 'graph_args --base 1000 -r --lower-limit 0'
puts "graph_title MSSQL Transactions/s" puts 'graph_title MSSQL Transactions/s'
puts "graph_category db" puts 'graph_category db'
puts "graph_info This graph shows transactions/s" puts 'graph_info This graph shows transactions/s'
puts "graph_vlabel transactions/s" puts 'graph_vlabel transactions/s'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_period second" puts 'graph_period second'
all_instance_names.sort.each do |s| all_instance_names.sort.each do |s|
puts "#{s}.label #{s}" puts "#{s}.label #{s}"
@ -122,7 +121,7 @@ all_instance_names.sort.each do |k|
sth.execute(k) sth.execute(k)
sth.fetch do |row| sth.fetch do |row|
# since type is DERIVE, need to convert value to integer then to string # since type is DERIVE, need to convert value to integer then to string
puts "#{k.to_s}.value #{row[0].to_i.to_s}" puts "#{k}.value #{row[0].to_i}"
end end
end end
sth.finish sth.finish

View File

@ -21,33 +21,31 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Prerequistes: Prerequistes:
1) /etc/odbc.ini and /etc/freetds.conf 1) /etc/odbc.ini and /etc/freetds.conf
2) rubygems 2) rubygems
3) ruby-dbi 3) ruby-dbi
Usage: Usage:
1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins) 1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins)
2) chmod to allow executable to others 2) chmod to allow executable to others
3) create symbolic link in /etc/munin/plugins 3) create symbolic link in /etc/munin/plugins
ln -s /usr/share/munin/plugins/mssql_buffercachehitratio.rb /etc/munin/plugins/mssql_buffercachehitratio.rb ln -s /usr/share/munin/plugins/mssql_buffercachehitratio.rb /etc/munin/plugins/mssql_buffercachehitratio.rb
Parameters: Parameters:
autoconf autoconf
config (required) config (required)
Config variables: Config variables:
sqluser : mssql user who has view server state privilege sqluser : mssql user who has view server state privilege
sqlpass : password for the mssql user sqlpass : password for the mssql user
dsn : datasource name as defined in /etc/odbc.ini dsn : datasource name as defined in /etc/odbc.ini
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
require 'rubygems' require 'rubygems'
require 'dbi' require 'dbi'
@ -74,37 +72,38 @@ buffercachehitratio_query = "select (a.cntr_value * 1.0 / b.cntr_value) * 100.0
# #
# autoconf # autoconf
# #
if ARGV[0] == "autoconf" case ARGV[0]
when 'autoconf'
if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1 if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1
puts "yes" puts 'yes'
else else
puts "no" puts 'no'
puts "Usage: #{__FILE__} autoconf|conf" puts "Usage: #{__FILE__} autoconf|conf"
end end
exit 0 exit 0
# #
# config definition # config definition
# #
elsif ARGV[0] == "config" when 'config'
puts "graph_args --base 1000 -r --lower-limit 0" puts 'graph_args --base 1000 -r --lower-limit 0'
puts "graph_title MSSQL Buffer Cache Hit Ratio " puts 'graph_title MSSQL Buffer Cache Hit Ratio '
puts "graph_category db" puts 'graph_category db'
puts "graph_info This graph shows Buffer Cache Hit Ratio" puts 'graph_info This graph shows Buffer Cache Hit Ratio'
puts "graph_vlabel %" puts 'graph_vlabel %'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_period second" puts 'graph_period second'
puts "bc_hitratio.label BufferCacheHitRatio" puts 'bc_hitratio.label BufferCacheHitRatio'
puts "bc_hitratio.info BufferCacheHitRatio" puts 'bc_hitratio.info BufferCacheHitRatio'
puts "bc_hitratio.type GAUGE" puts 'bc_hitratio.type GAUGE'
puts "bc_hitratio.draw LINE1" puts 'bc_hitratio.draw LINE1'
exit 0 exit 0
end end
sth = dbh.execute(buffercachehitratio_query) sth = dbh.execute(buffercachehitratio_query)
sth.fetch do |row| sth.fetch do |row|
puts "bc_hitratio.value #{row[0].strip.to_s}" puts "bc_hitratio.value #{row[0].strip}"
end end
sth.finish sth.finish
dbh.disconnect dbh.disconnect

View File

@ -21,34 +21,32 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Prerequistes: Prerequistes:
1) /etc/odbc.ini and /etc/freetds.conf 1) /etc/odbc.ini and /etc/freetds.conf
2) rubygems 2) rubygems
3) ruby-dbi 3) ruby-dbi
Usage: Usage:
1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins) 1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins)
2) chmod to allow executable to others 2) chmod to allow executable to others
3) create symbolic link in /etc/munin/plugins 3) create symbolic link in /etc/munin/plugins
ln -s /usr/share/munin/plugins/mssql_datafilesizes.rb /etc/munin/plugins/mssql_datafilesizes.rb ln -s /usr/share/munin/plugins/mssql_datafilesizes.rb /etc/munin/plugins/mssql_datafilesizes.rb
Parameters: Parameters:
autoconf autoconf
config (required) config (required)
Config variables: Config variables:
sqluser : mssql user who has view server state privilege sqluser : mssql user who has view server state privilege
sqlpass : password for the mssql user sqlpass : password for the mssql user
dsn : datasource name as defined in /etc/odbc.ini dsn : datasource name as defined in /etc/odbc.ini
instance: instance to monitor instance: instance to monitor
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
require 'rubygems' require 'rubygems'
require 'dbi' require 'dbi'
@ -72,7 +70,7 @@ transaction_query = "select cntr_value/1024.0 from sys.dm_os_performance_counter
and object_name = 'SQLServer:Databases' and object_name = 'SQLServer:Databases'
and instance_name = ?" and instance_name = ?"
all_instance_names = Array.new all_instance_names = []
sth = dbh.execute(instance_name_query) sth = dbh.execute(instance_name_query)
sth.fetch do |row| sth.fetch do |row|
all_instance_names.push(row[0].strip) all_instance_names.push(row[0].strip)
@ -82,25 +80,26 @@ sth.finish
# #
# autoconf # autoconf
# #
if ARGV[0] == "autoconf" case ARGV[0]
when 'autoconf'
if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1 if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1
puts "yes" puts 'yes'
else else
puts "no" puts 'no'
puts "Usage: #{__FILE__} autoconf|conf" puts "Usage: #{__FILE__} autoconf|conf"
end end
exit 0 exit 0
# #
# config definition # config definition
# #
elsif ARGV[0] == "config" when 'config'
puts "graph_args --base 1024k -r --lower-limit 0" puts 'graph_args --base 1024k -r --lower-limit 0'
puts "graph_title MSSQL DB File Sizes" puts 'graph_title MSSQL DB File Sizes'
puts "graph_category db" puts 'graph_category db'
puts "graph_info This graph shows DB File Sizes (MB)" puts 'graph_info This graph shows DB File Sizes (MB)'
puts "graph_vlabel MB" puts 'graph_vlabel MB'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_period second" puts 'graph_period second'
all_instance_names.sort.each do |s| all_instance_names.sort.each do |s|
puts "#{s}.label #{s}" puts "#{s}.label #{s}"
@ -119,7 +118,7 @@ sth = dbh.prepare(transaction_query)
all_instance_names.sort.each do |k| all_instance_names.sort.each do |k|
sth.execute(k) sth.execute(k)
sth.fetch do |row| sth.fetch do |row|
puts "#{k.to_s}.value #{row[0].to_s}" puts "#{k}.value #{row[0]}"
end end
end end
sth.finish sth.finish

View File

@ -21,34 +21,32 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Prerequistes: Prerequistes:
1) /etc/odbc.ini and /etc/freetds.conf 1) /etc/odbc.ini and /etc/freetds.conf
2) rubygems 2) rubygems
3) ruby-dbi 3) ruby-dbi
Usage: Usage:
1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins) 1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins)
2) chmod to allow executable to others 2) chmod to allow executable to others
3) create symbolic link in /etc/munin/plugins 3) create symbolic link in /etc/munin/plugins
ln -s /usr/share/munin/plugins/mssql_logfilesizes.rb /etc/munin/plugins/mssql_logfilesizes.rb ln -s /usr/share/munin/plugins/mssql_logfilesizes.rb /etc/munin/plugins/mssql_logfilesizes.rb
Parameters: Parameters:
autoconf autoconf
config (required) config (required)
Config variables: Config variables:
sqluser : mssql user who has view server state privilege sqluser : mssql user who has view server state privilege
sqlpass : password for the mssql user sqlpass : password for the mssql user
dsn : datasource name as defined in /etc/odbc.ini dsn : datasource name as defined in /etc/odbc.ini
instance: instance to monitor instance: instance to monitor
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
require 'rubygems' require 'rubygems'
require 'dbi' require 'dbi'
@ -72,7 +70,7 @@ logfilesize_query = "SELECT cntr_value/1024.0 from sys.dm_os_performance_counter
AND object_name = 'SQLServer:Databases' AND object_name = 'SQLServer:Databases'
AND instance_name = ?" AND instance_name = ?"
all_instance_names = Array.new all_instance_names = []
sth = dbh.execute(instance_name_query) sth = dbh.execute(instance_name_query)
sth.fetch do |row| sth.fetch do |row|
all_instance_names.push(row[0].strip) all_instance_names.push(row[0].strip)
@ -82,25 +80,26 @@ sth.finish
# #
# autoconf # autoconf
# #
if ARGV[0] == "autoconf" case ARGV[0]
when 'autoconf'
if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1 if all_instance_names.length > 1 && sqluser.length > 1 && sqlpass.length > 1
puts "yes" puts 'yes'
else else
puts "no" puts 'no'
puts "Usage: #{__FILE__} autoconf|conf" puts "Usage: #{__FILE__} autoconf|conf"
end end
exit 0 exit 0
# #
# config definition # config definition
# #
elsif ARGV[0] == "config" when 'config'
puts "graph_args --base 1024k -r --lower-limit 0" puts 'graph_args --base 1024k -r --lower-limit 0'
puts "graph_title MSSQL DB Log File Sizes" puts 'graph_title MSSQL DB Log File Sizes'
puts "graph_category db" puts 'graph_category db'
puts "graph_info This graph shows DB Log File Sizes (MB)" puts 'graph_info This graph shows DB Log File Sizes (MB)'
puts "graph_vlabel MB" puts 'graph_vlabel MB'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_period second" puts 'graph_period second'
all_instance_names.sort.each do |s| all_instance_names.sort.each do |s|
puts "#{s}.label #{s}" puts "#{s}.label #{s}"
@ -116,7 +115,7 @@ sth = dbh.prepare(logfilesize_query)
all_instance_names.sort.each do |k| all_instance_names.sort.each do |k|
sth.execute(k) sth.execute(k)
sth.fetch do |row| sth.fetch do |row|
puts "#{k.to_s}.value #{row[0].to_s}" puts "#{k}.value #{row[0]}"
end end
end end
sth.finish sth.finish

View File

@ -1,42 +1,40 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
if $0 =~ /^(?:|.*\/)http_([^_]+)_/ host = Regexp.last_match(1) if $0 =~ %r{^(?:|.*/)http_([^_]+)_}
host = $1
end
abort "# Error: couldn't understand what I'm supposed to monitor." unless host abort "# Error: couldn't understand what I'm supposed to monitor." unless host
user = ENV['user'] || 'user' user = ENV['user'] || 'user'
password = ENV['password'] || 'user' password = ENV['password'] || 'user'
if (ARGV[0] == 'config') if ARGV[0] == 'config'
puts "host_name #{host}" unless host == 'localhost' puts "host_name #{host}" unless host == 'localhost'
puts "multigraph dsl_rate" puts 'multigraph dsl_rate'
puts "graph_title DSL line speed" puts 'graph_title DSL line speed'
puts "graph_args --base 1000 -l 0" puts 'graph_args --base 1000 -l 0'
puts "graph_vlabel bps" puts 'graph_vlabel bps'
puts "graph_category network" puts 'graph_category network'
puts "downstream.label downstream" puts 'downstream.label downstream'
puts "downstream.type GAUGE" puts 'downstream.type GAUGE'
puts "downstream.min 0" puts 'downstream.min 0'
puts "downstream.cdef downstream,1000,*" puts 'downstream.cdef downstream,1000,*'
puts "upstream.label upstream" puts 'upstream.label upstream'
puts "upstream.type GAUGE" puts 'upstream.type GAUGE'
puts "upstream.min 0" puts 'upstream.min 0'
puts "upstream.cdef upstream,1000,*" puts 'upstream.cdef upstream,1000,*'
puts "multigraph dsl_snr" puts 'multigraph dsl_snr'
puts "graph_title DSL SNR" puts 'graph_title DSL SNR'
puts "graph_args --base 1000 -l 0" puts 'graph_args --base 1000 -l 0'
puts "graph_vlabel dB" puts 'graph_vlabel dB'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_category network" puts 'graph_category network'
puts "downstream.label downstream" puts 'downstream.label downstream'
puts "downstream.type GAUGE" puts 'downstream.type GAUGE'
puts "downstream.min 0" puts 'downstream.min 0'
puts "upstream.label upstream" puts 'upstream.label upstream'
puts "upstream.type GAUGE" puts 'upstream.type GAUGE'
puts "upstream.min 0" puts 'upstream.min 0'
exit 0 exit 0
end end
@ -56,21 +54,21 @@ class TPAdslStats
def field_values(label) def field_values(label)
if @html =~ />#{label}.*?<td>([0-9.]+).*?([0-9.]+)/m if @html =~ />#{label}.*?<td>([0-9.]+).*?([0-9.]+)/m
[$1, $2] [Regexp.last_match(1), Regexp.last_match(2)]
else else
['U', 'U'] %w[U U]
end end
end end
end end
stats = TPAdslStats.new(host, user, password) stats = TPAdslStats.new(host, user, password)
puts "multigraph dsl_rate" puts 'multigraph dsl_rate'
rate = stats.field_values('Rate') rate = stats.field_values('Rate')
puts "downstream.value #{rate[0]}" puts "downstream.value #{rate[0]}"
puts "upstream.value #{rate[1]}" puts "upstream.value #{rate[1]}"
puts "multigraph dsl_snr" puts 'multigraph dsl_snr'
snr = stats.field_values('SNR') snr = stats.field_values('SNR')
puts "downstream.value #{snr[0]}" puts "downstream.value #{snr[0]}"
puts "upstream.value #{snr[1]}" puts "upstream.value #{snr[1]}"

View File

@ -9,27 +9,26 @@ This plugin shows various statistics from 'netstat -s'
Required privileges: none Required privileges: none
OS: OS:
Supposed: BSD, Linux (only a few items, see netstat_multi for more) Supposed: BSD, Linux (only a few items, see netstat_multi for more)
Tested: FreeBSD: 8.2, 8.3, 9.1 Tested: FreeBSD: 8.2, 8.3, 9.1
Linux : Debian 6 (kernel 2.6.32), Arch (kernel 3.11.6), CentOS 6 Linux : Debian 6 (kernel 2.6.32), Arch (kernel 3.11.6), CentOS 6
Author: Artem Sheremet <dot.doom@gmail.com> Author: Artem Sheremet <dot.doom@gmail.com>
#%# family=auto #%# family=auto
#%# capabilities=autoconf suggest #%# capabilities=autoconf suggest
=end =end
# original filename # original filename
PLUGIN_NAME = 'netstat_s_' PLUGIN_NAME = 'netstat_s_'.freeze
$os = `uname -s`.strip.downcase.to_sym $os = `uname -s`.strip.downcase.to_sym
$debug_mode = ARGV.first == 'debug' $debug_mode = ARGV.first == 'debug'
class String class String
def escape def escape
self.gsub /[^\w]/, '_' gsub(/[^\w]/, '_')
end end
unless method_defined? :start_with? unless method_defined? :start_with?
@ -40,14 +39,16 @@ class String
unless method_defined? :lines unless method_defined? :lines
def lines def lines
self.split($/).to_enum split($/).to_enum
end end
end end
end end
class Graph class Graph
def initialize(name, protocol, parse_expr) def initialize(name, protocol, parse_expr)
@name, @protocol, @parse_expr = name, protocol, parse_expr @name = name
@protocol = protocol
@parse_expr = parse_expr
end end
def config def config
@ -56,31 +57,31 @@ class Graph
# first, build a list of multigraphs (one graph per unit) # first, build a list of multigraphs (one graph per unit)
# Hash key is unit, and the value is array of labels # Hash key is unit, and the value is array of labels
multigraphs = {} multigraphs = {}
@parse_expr.each { |expr, descr| @parse_expr.each do |_expr, descr|
next unless descr # no label - skip this entry next unless descr # no label - skip this entry
descr.each { |entry| descr.each do |entry|
labels_array = (multigraphs[entry[0]] ||= []) labels_array = (multigraphs[entry[0]] ||= [])
labels_array.push [entry[1], entry[2]] labels_array.push [entry[1], entry[2]]
} end
} end
multigraphs.each_pair { |unit, labels_and_negatives| multigraphs.each_pair do |unit, labels_and_negatives|
# now just add options to the config # now just add options to the config
config_options.concat [ config_options.concat [
"multigraph #{name(unit)}", "multigraph #{name(unit)}",
"graph_title Netstat: #{@protocol}: #{@name}#{" (#{unit})" if multigraphs.size > 1}", "graph_title Netstat: #{@protocol}: #{@name}#{" (#{unit})" if multigraphs.size > 1}",
"graph_category network", 'graph_category network',
"graph_order #{labels_and_negatives.map { |label, _negative| label.escape }.join(' ')}" "graph_order #{labels_and_negatives.map { |label, _negative| label.escape }.join(' ')}"
] ]
config_options.push "graph_args --base 1024" if unit == :bytes config_options.push 'graph_args --base 1024' if unit == :bytes
has_negatives = false has_negatives = false
labels_and_negatives.each { |label, negative| labels_and_negatives.each do |label, negative|
label_esc = label.escape label_esc = label.escape
has_negatives = true unless negative == nil has_negatives = true unless negative.nil?
if negative == true if negative == true
# the value has no opposite and is negative # the value has no opposite and is negative
@ -114,10 +115,10 @@ class Graph
"#{negative_esc}.graph no" "#{negative_esc}.graph no"
] ]
end end
} end
config_options.push "graph_vlabel per second#{" in (-) / out (+)" if has_negatives}" config_options.push "graph_vlabel per second#{' in (-) / out (+)' if has_negatives}"
} end
config_options config_options
end end
@ -128,25 +129,25 @@ class Graph
# first build a set of multigraphs, one per unit. # first build a set of multigraphs, one per unit.
# Hash key is unit, and the value is a hash of 'escaped label' => 'value' # Hash key is unit, and the value is a hash of 'escaped label' => 'value'
multigraphs = {} multigraphs = {}
@parse_expr.each { |expr, descr| @parse_expr.each do |expr, descr|
next unless descr # no label - skip this entry next unless descr # no label - skip this entry
index = data.index { |line| line =~ expr } index = data.index { |line| line =~ expr }
if index if index
data.delete_at index data.delete_at index
$~[1..-1].zip(descr).each { |value, info| $~[1..-1].zip(descr).each do |value, info|
unit, label = info unit, label = info
(multigraphs[unit] ||= {})[label.escape] = value (multigraphs[unit] ||= {})[label.escape] = value
} end
else else
warn "no line found for #{expr}, #{descr}" if $debug_mode warn "no line found for #{expr}, #{descr}" if $debug_mode
end end
} end
multigraphs.each_pair { |unit, values| multigraphs.each_pair do |unit, values|
output_data.push "multigraph #{name(unit)}" output_data.push "multigraph #{name(unit)}"
output_data += values.map { |label, value| "#{label}.value #{value}" } output_data += values.map { |label, value| "#{label}.value #{value}" }
} end
output_data output_data
end end
@ -161,214 +162,230 @@ def graphs_for(protocol)
# Order of the graps in each section is important for parsing. # Order of the graps in each section is important for parsing.
# At the same time, it is not important for munin, so we are OK placing it in parsing order here. # At the same time, it is not important for munin, so we are OK placing it in parsing order here.
when 'tcp' when 'tcp'
$os == :linux ? [ if $os == :linux
Graph.new('sent', protocol, [ [
# Description of the elements of arrays below: Graph.new('sent', protocol, [
# 0: regexp to parse the line # Description of the elements of arrays below:
# 1: Array<Array[3]> for each matching group in the regular expression. # 0: regexp to parse the line
# 0: unit name # 1: Array<Array[3]> for each matching group in the regular expression.
# 1: label # 0: unit name
# 2 (optional): negative label # 1: label
# It could be reasonable to add more elements as warning and critical values. # 2 (optional): negative label
# It could be reasonable to add more elements as warning and critical values.
[/(\d+) segments send out$/, [[:segments, 'total']]], [/(\d+) segments send out$/, [[:segments, 'total']]],
[/(\d+) segments retransmitted$/, [[:segments, 'retransmitted']]] [/(\d+) segments retransmitted$/, [[:segments, 'retransmitted']]]
]), ]),
Graph.new('received', protocol, [ Graph.new('received', protocol, [
[/(\d+) segments received$/, [[:segments, 'total']]], [/(\d+) segments received$/, [[:segments, 'total']]],
[/(\d+) bad segments received.$/, [[:segments, 'bad']]] [/(\d+) bad segments received.$/, [[:segments, 'bad']]]
]), ]),
Graph.new('connections', protocol, [ Graph.new('connections', protocol, [
[/(\d+) active connections openings$/, [[:connections, 'active openings']]], [/(\d+) active connections openings$/, [[:connections, 'active openings']]],
[/(\d+) passive connection openings$/, [[:connections, 'passive openings']]], [/(\d+) passive connection openings$/, [[:connections, 'passive openings']]],
[/(\d+) failed connection attempts$/, [[:connections, 'failed attempts']]], [/(\d+) failed connection attempts$/, [[:connections, 'failed attempts']]],
[/(\d+) connection resets received$/, [[:connections, 'RST received']]], [/(\d+) connection resets received$/, [[:connections, 'RST received']]],
[/(\d+) connections established$/, [[:connections, 'established']]], [/(\d+) connections established$/, [[:connections, 'established']]],
[/(\d+) resets sent$/, [[:connections, 'RST sent']]] [/(\d+) resets sent$/, [[:connections, 'RST sent']]]
]), ]),
Graph.new('timeouts', protocol, [ Graph.new('timeouts', protocol, [
[/(\d+) timeouts after SACK recovery$/, [[:segments, 'after SACK recovery']]], [/(\d+) timeouts after SACK recovery$/, [[:segments, 'after SACK recovery']]],
[/(\d+) other TCP timeouts$/, [[:segments, 'other TCP']]], [/(\d+) other TCP timeouts$/, [[:segments, 'other TCP']]],
[/(\d+) timeouts in loss state$/, [[:segments, 'in a loss state']]] [/(\d+) timeouts in loss state$/, [[:segments, 'in a loss state']]]
]) ])
] : [ ]
Graph.new('sent', protocol, [ else
[/(\d+) packets sent$/, [[:packets, 'total']]], [
[/(\d+) data packets \((\d+) bytes\)$/, [[:packets, 'data'], [:bytes, 'data']]], Graph.new('sent', protocol, [
[/(\d+) data packets \((\d+) bytes\) retransmitted$/, [[:packets, 'retransmitted'], [:bytes, 'retransmitted']]], [/(\d+) packets sent$/, [[:packets, 'total']]],
[/(\d+) data packets unnecessarily retransmitted$/, [[:packets, 'unnecessarily retransmitted']]], [/(\d+) data packets \((\d+) bytes\)$/, [[:packets, 'data'], [:bytes, 'data']]],
[/(\d+) resends initiated by MTU discovery$/, [[:packets, 'resends initiated by MTU discovery']]], [/(\d+) data packets \((\d+) bytes\) retransmitted$/, [[:packets, 'retransmitted'], [:bytes, 'retransmitted']]],
[/(\d+) ack-only packets \((\d+) delayed\)$/, [[:packets, 'ack-only'], [:packets, 'ack-only delayed']]], [/(\d+) data packets unnecessarily retransmitted$/, [[:packets, 'unnecessarily retransmitted']]],
[/(\d+) URG only packets$/, [[:packets, 'URG only']]], [/(\d+) resends initiated by MTU discovery$/, [[:packets, 'resends initiated by MTU discovery']]],
[/(\d+) window probe packets$/, [[:packets, 'window probe']]], [/(\d+) ack-only packets \((\d+) delayed\)$/, [[:packets, 'ack-only'], [:packets, 'ack-only delayed']]],
[/(\d+) window update packets$/, [[:packets, 'window update']]], [/(\d+) URG only packets$/, [[:packets, 'URG only']]],
[/(\d+) control packets$/, [[:packets, 'control']]] [/(\d+) window probe packets$/, [[:packets, 'window probe']]],
]), [/(\d+) window update packets$/, [[:packets, 'window update']]],
[/(\d+) control packets$/, [[:packets, 'control']]]
]),
Graph.new('received', protocol, [ Graph.new('received', protocol, [
[/(\d+) packets received$/, [[:packets, 'total']]], [/(\d+) packets received$/, [[:packets, 'total']]],
[/(\d+) acks \(for (\d+) bytes\)$/, [[:packets, 'acks'], [:bytes, 'acks']]], [/(\d+) acks \(for (\d+) bytes\)$/, [[:packets, 'acks'], [:bytes, 'acks']]],
[/(\d+) duplicate acks$/, [[:packets, 'duplicate acks']]], [/(\d+) duplicate acks$/, [[:packets, 'duplicate acks']]],
[/(\d+) acks for unsent data$/, [[:packets, 'acks for unsent data']]], [/(\d+) acks for unsent data$/, [[:packets, 'acks for unsent data']]],
[/(\d+) packets \((\d+) bytes\) received in-sequence$/, [[:packets, 'in-sequence'], [:bytes, 'in-sequence']]], [/(\d+) packets \((\d+) bytes\) received in-sequence$/, [[:packets, 'in-sequence'], [:bytes, 'in-sequence']]],
[/(\d+) completely duplicate packets \((\d+) bytes\)$/, [[:packets, 'completely duplicate'], [:bytes, 'completely duplicate']]], [/(\d+) completely duplicate packets \((\d+) bytes\)$/, [[:packets, 'completely duplicate'], [:bytes, 'completely duplicate']]],
[/(\d+) old duplicate packets$/, [[:packets, 'old duplicate']]], [/(\d+) old duplicate packets$/, [[:packets, 'old duplicate']]],
[/(\d+) packets with some dup\. data \((\d+) bytes duped\)$/, [[:packets, 'some dup. data'], [:bytes, 'partial dups']]], [/(\d+) packets with some dup\. data \((\d+) bytes duped\)$/, [[:packets, 'some dup. data'], [:bytes, 'partial dups']]],
[/(\d+) out-of-order packets \((\d+) bytes\)$/, [[:packets, 'out-of-order'], [:bytes, 'out-of-order']]], [/(\d+) out-of-order packets \((\d+) bytes\)$/, [[:packets, 'out-of-order'], [:bytes, 'out-of-order']]],
[/(\d+) packets \((\d+) bytes\) of data after window$/, [[:packets, 'data after window'], [:bytes, 'data after window']]], [/(\d+) packets \((\d+) bytes\) of data after window$/, [[:packets, 'data after window'], [:bytes, 'data after window']]],
[/(\d+) window probes$/, [[:packets, 'window probes']]], [/(\d+) window probes$/, [[:packets, 'window probes']]],
[/(\d+) window update packets$/, [[:packets, 'window update']]], [/(\d+) window update packets$/, [[:packets, 'window update']]],
[/(\d+) packets received after close$/, [[:packets, 'after close']]], [/(\d+) packets received after close$/, [[:packets, 'after close']]],
[/(\d+) discarded for bad checksums$/, [[:packets, 'bad checksums']]], [/(\d+) discarded for bad checksums$/, [[:packets, 'bad checksums']]],
[/(\d+) discarded for bad header offset fields?$/, [[:packets, 'bad header offset flds']]], [/(\d+) discarded for bad header offset fields?$/, [[:packets, 'bad header offset flds']]],
[/(\d+) discarded because packet too short$/, [[:packets, 'too short']]], [/(\d+) discarded because packet too short$/, [[:packets, 'too short']]],
[/(\d+) discarded due to memory problems$/, [[:packets, 'discarded: memory problems']]], [/(\d+) discarded due to memory problems$/, [[:packets, 'discarded: memory problems']]],
[/(\d+) ignored RSTs in the windows$/, [[:packets, 'ignored RSTs in windows']]], [/(\d+) ignored RSTs in the windows$/, [[:packets, 'ignored RSTs in windows']]],
[/(\d+) segments updated rtt \(of (\d+) attempts\)$/, [[:packets, 'RTT: updated'], [:packets, 'RTT: attempts to update']]] [/(\d+) segments updated rtt \(of (\d+) attempts\)$/, [[:packets, 'RTT: updated'], [:packets, 'RTT: attempts to update']]]
]), ]),
Graph.new('connections', protocol, [ Graph.new('connections', protocol, [
[/(\d+) connection requests$/, [[:connections, 'requests']]], [/(\d+) connection requests$/, [[:connections, 'requests']]],
[/(\d+) connection accepts$/, [[:connections, 'accepts']]], [/(\d+) connection accepts$/, [[:connections, 'accepts']]],
[/(\d+) bad connection attempts$/, [[:connections, 'bad attempts']]], [/(\d+) bad connection attempts$/, [[:connections, 'bad attempts']]],
[/(\d+) listen queue overflows$/, [[:connections, 'listen queue overflows']]], [/(\d+) listen queue overflows$/, [[:connections, 'listen queue overflows']]],
[/(\d+) connections established \(including accepts\)$/, [[:connections, 'established']]], [/(\d+) connections established \(including accepts\)$/, [[:connections, 'established']]],
[/(\d+) connections closed \(including (\d+) drops\)$/, [[:connections, 'closed'], [:connections, 'dropped']]], [/(\d+) connections closed \(including (\d+) drops\)$/, [[:connections, 'closed'], [:connections, 'dropped']]],
[/(\d+) connections updated cached RTT on close$/, [[:connections, 'closed & upd cached RTT']]], [/(\d+) connections updated cached RTT on close$/, [[:connections, 'closed & upd cached RTT']]],
[/(\d+) connections updated cached RTT variance on close$/, [[:connections, 'closed & upd cached RTT variance']]], [/(\d+) connections updated cached RTT variance on close$/, [[:connections, 'closed & upd cached RTT variance']]],
[/(\d+) connections updated cached ssthresh on close$/, [[:connections, 'closed & upd cached ssthresh']]], [/(\d+) connections updated cached ssthresh on close$/, [[:connections, 'closed & upd cached ssthresh']]],
[/(\d+) embryonic connections dropped$/, [[:connections, 'embryonic dropped']]] [/(\d+) embryonic connections dropped$/, [[:connections, 'embryonic dropped']]]
]), ]),
Graph.new('timeouts', protocol, [ Graph.new('timeouts', protocol, [
[/(\d+) retransmit timeouts$/, [[:connections, 'retransmit']]], [/(\d+) retransmit timeouts$/, [[:connections, 'retransmit']]],
[/(\d+) connections dropped by rexmit timeout$/, [[:connections, 'retransmit: dropped']]], [/(\d+) connections dropped by rexmit timeout$/, [[:connections, 'retransmit: dropped']]],
[/(\d+) persist timeouts$/, [[:connections, 'persist']]], [/(\d+) persist timeouts$/, [[:connections, 'persist']]],
[/(\d+) connections dropped by persist timeout$/, [[:connections, 'persist: dropped']]], [/(\d+) connections dropped by persist timeout$/, [[:connections, 'persist: dropped']]],
[/(\d+) Connections \(fin_wait_2\) dropped because of timeout$/, [[:connections, 'fin_wait_2: dropped']]], [/(\d+) Connections \(fin_wait_2\) dropped because of timeout$/, [[:connections, 'fin_wait_2: dropped']]],
[/(\d+) keepalive timeouts$/, [[:connections, 'keepalive']]], [/(\d+) keepalive timeouts$/, [[:connections, 'keepalive']]],
[/(\d+) keepalive probes sent$/, [[:connections, 'keepalive: probes sent']]], [/(\d+) keepalive probes sent$/, [[:connections, 'keepalive: probes sent']]],
[/(\d+) connections dropped by keepalive$/, [[:connections, 'keepalive: dropped']]] [/(\d+) connections dropped by keepalive$/, [[:connections, 'keepalive: dropped']]]
]), ]),
Graph.new('correct predictions', protocol, [ Graph.new('correct predictions', protocol, [
[/(\d+) correct ACK header predictions$/, [[:predictions, 'ACK header']]], [/(\d+) correct ACK header predictions$/, [[:predictions, 'ACK header']]],
[/(\d+) correct data packet header predictions$/, [[:predictions, 'data packet header']]] [/(\d+) correct data packet header predictions$/, [[:predictions, 'data packet header']]]
]), ]),
Graph.new('SYN', protocol, [ Graph.new('SYN', protocol, [
[/(\d+) syncache entries added$/, [[:entries, 'cache added']]], [/(\d+) syncache entries added$/, [[:entries, 'cache added']]],
[/(\d+) cookies sent$/, [[:entries, 'cookies sent']]], [/(\d+) cookies sent$/, [[:entries, 'cookies sent']]],
[/(\d+) cookies received$/, [[:entries, 'cookies received']]], [/(\d+) cookies received$/, [[:entries, 'cookies received']]],
[/(\d+) retransmitted$/, [[:entries, 'retransmitted']]], [/(\d+) retransmitted$/, [[:entries, 'retransmitted']]],
[/(\d+) dupsyn$/, [[:entries, 'duplicates']]], [/(\d+) dupsyn$/, [[:entries, 'duplicates']]],
[/(\d+) dropped$/, [[:entries, 'dropped']]], [/(\d+) dropped$/, [[:entries, 'dropped']]],
[/(\d+) completed$/, [[:entries, 'completed']]], [/(\d+) completed$/, [[:entries, 'completed']]],
[/(\d+) bucket overflow$/, [[:entries, 'bucket overflow']]], [/(\d+) bucket overflow$/, [[:entries, 'bucket overflow']]],
[/(\d+) cache overflow$/, [[:entries, 'cache overflow']]], [/(\d+) cache overflow$/, [[:entries, 'cache overflow']]],
[/(\d+) reset$/, [[:entries, 'reset']]], [/(\d+) reset$/, [[:entries, 'reset']]],
[/(\d+) stale$/, [[:entries, 'stale']]], [/(\d+) stale$/, [[:entries, 'stale']]],
[/(\d+) aborted$/, [[:entries, 'aborted']]], [/(\d+) aborted$/, [[:entries, 'aborted']]],
[/(\d+) badack$/, [[:entries, 'bad ACK']]], [/(\d+) badack$/, [[:entries, 'bad ACK']]],
[/(\d+) unreach$/, [[:entries, 'unreachable']]], [/(\d+) unreach$/, [[:entries, 'unreachable']]],
[/(\d+) zone failures$/, [[:entries, 'zone failures']]], [/(\d+) zone failures$/, [[:entries, 'zone failures']]],
[/(\d+) hostcache entries added$/, [[:entries, 'hostcache added']]], [/(\d+) hostcache entries added$/, [[:entries, 'hostcache added']]],
[/(\d+) bucket overflow$/, [[:entries, 'hostcache overflow']]] [/(\d+) bucket overflow$/, [[:entries, 'hostcache overflow']]]
]), ]),
Graph.new('SACK', protocol, [ Graph.new('SACK', protocol, [
[/(\d+) SACK recovery episodes$/, [[:packets, 'recovery episodes']]], [/(\d+) SACK recovery episodes$/, [[:packets, 'recovery episodes']]],
[/(\d+) segment rexmits in SACK recovery episodes$/, [[:packets, 'segment rexmits']]], [/(\d+) segment rexmits in SACK recovery episodes$/, [[:packets, 'segment rexmits']]],
[/(\d+) byte rexmits in SACK recovery episodes$/, [[:bytes, 'bytes rexmitted']]], [/(\d+) byte rexmits in SACK recovery episodes$/, [[:bytes, 'bytes rexmitted']]],
[/(\d+) SACK options \(SACK blocks\) received$/, [[:packets, 'options blocks rcvd']]], [/(\d+) SACK options \(SACK blocks\) received$/, [[:packets, 'options blocks rcvd']]],
[/(\d+) SACK options \(SACK blocks\) sent$/, [[:packets, 'options blocks sent']]], [/(\d+) SACK options \(SACK blocks\) sent$/, [[:packets, 'options blocks sent']]],
[/(\d+) SACK scoreboard overflow$/, [[:packets, 'scoreboard overflow']]] [/(\d+) SACK scoreboard overflow$/, [[:packets, 'scoreboard overflow']]]
]), ]),
Graph.new('ECN', protocol, [ Graph.new('ECN', protocol, [
[/(\d+) packets with ECN CE bit set$/, [[:packets, 'CE bit']]], [/(\d+) packets with ECN CE bit set$/, [[:packets, 'CE bit']]],
[/(\d+) packets with ECN ECT\(0\) bit set$/, [[:packets, 'ECT(0) bit']]], [/(\d+) packets with ECN ECT\(0\) bit set$/, [[:packets, 'ECT(0) bit']]],
[/(\d+) packets with ECN ECT\(1\) bit set$/, [[:packets, 'ECT(1) bit']]], [/(\d+) packets with ECN ECT\(1\) bit set$/, [[:packets, 'ECT(1) bit']]],
[/(\d+) successful ECN handshakes$/, [[:packets, 'successful handshakes']]], [/(\d+) successful ECN handshakes$/, [[:packets, 'successful handshakes']]],
[/(\d+) times ECN reduced the congestion window$/, [[:packets, 'congestion window reduced']]] [/(\d+) times ECN reduced the congestion window$/, [[:packets, 'congestion window reduced']]]
]) ])
] ]
end
when 'udp' when 'udp'
$os == :linux ? [] : [ if $os == :linux
Graph.new('received', protocol, [ []
[/(\d+) datagrams received$/, [[:packets, 'total']]], else
[/(\d+) with incomplete header$/, [[:packets, 'incomplete header']]], [
[/(\d+) with bad data length field$/, [[:packets, 'bad data length field']]], Graph.new('received', protocol, [
[/(\d+) with bad checksum$/, [[:packets, 'bad checksum']]], [/(\d+) datagrams received$/, [[:packets, 'total']]],
[/(\d+) with no checksum$/, [[:packets, 'no checksum']]], [/(\d+) with incomplete header$/, [[:packets, 'incomplete header']]],
[/(\d+) dropped due to no socket$/, [[:packets, 'dropped: no socket']]], [/(\d+) with bad data length field$/, [[:packets, 'bad data length field']]],
[/(\d+) broadcast\/multicast datagrams undelivered$/, [[:packets, '*cast undelivered']]], [/(\d+) with bad checksum$/, [[:packets, 'bad checksum']]],
[/(\d+) dropped due to full socket buffers$/, [[:packets, 'dropped: no buffers']]], [/(\d+) with no checksum$/, [[:packets, 'no checksum']]],
[/(\d+) not for hashed pcb$/, [[:packets, 'not for hashed pcb']]], [/(\d+) dropped due to no socket$/, [[:packets, 'dropped: no socket']]],
[/(\d+) delivered$/, [[:packets, 'delivered']]] [%r{(\d+) broadcast/multicast datagrams undelivered$}, [[:packets, '*cast undelivered']]],
]), [/(\d+) dropped due to full socket buffers$/, [[:packets, 'dropped: no buffers']]],
[/(\d+) not for hashed pcb$/, [[:packets, 'not for hashed pcb']]],
[/(\d+) delivered$/, [[:packets, 'delivered']]]
]),
Graph.new('sent', protocol, [ Graph.new('sent', protocol, [
[/(\d+) datagrams output$/, [[:packets, 'total']]], [/(\d+) datagrams output$/, [[:packets, 'total']]],
[/(\d+) times multicast source filter matched$/, [[:packets, 'multicast src filter match']]] [/(\d+) times multicast source filter matched$/, [[:packets, 'multicast src filter match']]]
]) ])
] ]
end
when 'ip' when 'ip'
$os == :linux ? [] : [ if $os == :linux
Graph.new('received', protocol, [ []
[/(\d+) total packets received$/, [[:packets, 'total']]], else
[/(\d+) bad header checksums$/, [[:packets, 'bad header checksum']]], [
[/(\d+) with size smaller than minimum$/, [[:packets, 'size smaller than min']]], Graph.new('received', protocol, [
[/(\d+) with data size < data length$/, [[:packets, 'data size < data length']]], [/(\d+) total packets received$/, [[:packets, 'total']]],
[/(\d+) with ip length > max ip packet size$/, [[:packets, 'ip length > max ip packet sz']]], [/(\d+) bad header checksums$/, [[:packets, 'bad header checksum']]],
[/(\d+) with header length < data size$/, [[:packets, 'header length < data size']]], [/(\d+) with size smaller than minimum$/, [[:packets, 'size smaller than min']]],
[/(\d+) with data length < header length$/, [[:packets, 'data length < header length']]], [/(\d+) with data size < data length$/, [[:packets, 'data size < data length']]],
[/(\d+) with bad options$/, [[:packets, 'bad options']]], [/(\d+) with ip length > max ip packet size$/, [[:packets, 'ip length > max ip packet sz']]],
[/(\d+) with incorrect version number$/, [[:packets, 'incorrect version']]], [/(\d+) with header length < data size$/, [[:packets, 'header length < data size']]],
[/(\d+) fragments? received$/, [[:packets, 'fragments']]], [/(\d+) with data length < header length$/, [[:packets, 'data length < header length']]],
[/(\d+) fragments? dropped \(dup or out of space\)$/, [[:packets, 'frags dropped: dup/out of spc']]], [/(\d+) with bad options$/, [[:packets, 'bad options']]],
[/(\d+) fragments? dropped after timeout$/, [[:packets, 'frags dropped: timeout']]], [/(\d+) with incorrect version number$/, [[:packets, 'incorrect version']]],
[/(\d+) packets? reassembled ok$/, [[:packets, 'reassembled ok']]], [/(\d+) fragments? received$/, [[:packets, 'fragments']]],
[/(\d+) packets? for this host$/, [[:packets, 'for this host']]], [/(\d+) fragments? dropped \(dup or out of space\)$/, [[:packets, 'frags dropped: dup/out of spc']]],
[/(\d+) packets? for unknown\/unsupported protocol$/, [[:packets, 'for unknown/unsup protocol']]], [/(\d+) fragments? dropped after timeout$/, [[:packets, 'frags dropped: timeout']]],
[/(\d+) packets? forwarded \((\d+) packets fast forwarded\)$/, [[:packets, 'forwarded'], [:packets, 'fast forwarded']]], [/(\d+) packets? reassembled ok$/, [[:packets, 'reassembled ok']]],
[/(\d+) packets? not forwardable$/, [[:packets, 'not forwardable']]], [/(\d+) packets? for this host$/, [[:packets, 'for this host']]],
[/(\d+) packets? received for unknown multicast group$/, [[:packets, 'unknown multicast grp']]] [%r{(\d+) packets? for unknown/unsupported protocol$}, [[:packets, 'for unknown/unsup protocol']]],
]), [/(\d+) packets? forwarded \((\d+) packets fast forwarded\)$/, [[:packets, 'forwarded'], [:packets, 'fast forwarded']]],
[/(\d+) packets? not forwardable$/, [[:packets, 'not forwardable']]],
[/(\d+) packets? received for unknown multicast group$/, [[:packets, 'unknown multicast grp']]]
]),
Graph.new('sent', protocol, [ Graph.new('sent', protocol, [
[/(\d+) packets? sent from this host$/, [[:packets, 'total']]], [/(\d+) packets? sent from this host$/, [[:packets, 'total']]],
[/(\d+) redirects? sent$/, [[:packets, 'redirect']]], [/(\d+) redirects? sent$/, [[:packets, 'redirect']]],
[/(\d+) packets? sent with fabricated ip header$/, [[:packets, 'fabricated IP head']]], [/(\d+) packets? sent with fabricated ip header$/, [[:packets, 'fabricated IP head']]],
[/(\d+) output packets? dropped due to no bufs, etc\.$/, [[:packets, 'dropped: no bufs, etc']]], [/(\d+) output packets? dropped due to no bufs, etc\.$/, [[:packets, 'dropped: no bufs, etc']]],
[/(\d+) output packets? discarded due to no route$/, [[:packets, 'discarded: no route']]], [/(\d+) output packets? discarded due to no route$/, [[:packets, 'discarded: no route']]],
[/(\d+) output datagrams? fragmented$/, [[:packets, 'fragmented']]], [/(\d+) output datagrams? fragmented$/, [[:packets, 'fragmented']]],
[/(\d+) fragments? created$/, [[:packets, 'fragments created']]], [/(\d+) fragments? created$/, [[:packets, 'fragments created']]],
[/(\d+) datagrams? that can't be fragmented$/, [[:packets, "can't be fragmented"]]], [/(\d+) datagrams? that can't be fragmented$/, [[:packets, "can't be fragmented"]]],
[/(\d+) tunneling packets? that can't find gif$/, [[:packets, 'tunneling, gif not found']]], [/(\d+) tunneling packets? that can't find gif$/, [[:packets, 'tunneling, gif not found']]],
[/(\d+) datagrams? with bad address in header$/, [[:packets, 'bad address in header']]] [/(\d+) datagrams? with bad address in header$/, [[:packets, 'bad address in header']]]
]) ])
] ]
end
when 'arp' when 'arp'
$os == :linux ? [] : [ if $os == :linux
Graph.new('packets', protocol, [ []
# This is just a total, so ignore the value but keep regexp to avoid 'not parsed' warning. else
[/(\d+) ARP packets? received$/], [
[/(\d+) ARP requests? received$/, [[:packets, 'requests received']]], Graph.new('packets', protocol, [
[/(\d+) ARP repl(?:y|ies) received$/, [[:packets, 'replies received']]], # This is just a total, so ignore the value but keep regexp to avoid 'not parsed' warning.
[/(\d+) ARP requests? sent$/, [[:packets, 'requests', 'requests received']]], [/(\d+) ARP packets? received$/],
[/(\d+) ARP repl(?:y|ies) sent$/, [[:packets, 'replies', 'replies received']]], [/(\d+) ARP requests? received$/, [[:packets, 'requests received']]],
[/(\d+) total packets? dropped due to no ARP entry$/, [[:packets, 'no entry']]] [/(\d+) ARP repl(?:y|ies) received$/, [[:packets, 'replies received']]],
]), [/(\d+) ARP requests? sent$/, [[:packets, 'requests', 'requests received']]],
[/(\d+) ARP repl(?:y|ies) sent$/, [[:packets, 'replies', 'replies received']]],
[/(\d+) total packets? dropped due to no ARP entry$/, [[:packets, 'no entry']]]
]),
Graph.new('entries', protocol, [ Graph.new('entries', protocol, [
[/(\d+) ARP entrys? timed out$/, [[:entries, 'timed out']]], [/(\d+) ARP entrys? timed out$/, [[:entries, 'timed out']]],
[/(\d+) Duplicate IPs seen$/, [[:entries, 'duplicate IPs seen']]] [/(\d+) Duplicate IPs seen$/, [[:entries, 'duplicate IPs seen']]]
]) ])
] ]
end
end end
end end
@ -379,9 +396,11 @@ proto_name = 'tcp' if proto_name.empty?
def netstat_s(protocol) def netstat_s(protocol)
if $os == :linux if $os == :linux
%w(tcp udp).include?(protocol) ? if %w[tcp udp].include?(protocol)
`netstat -s --#{protocol}` : `netstat -s --#{protocol}`
else
`netstat -s --raw` `netstat -s --raw`
end
else else
`netstat -sp #{protocol}` `netstat -sp #{protocol}`
end.lines.reject { |line| line =~ /^\w+:/ } end.lines.reject { |line| line =~ /^\w+:/ }
@ -389,20 +408,22 @@ end
case ARGV.first case ARGV.first
when 'autoconf' when 'autoconf'
puts [:linux, :freebsd].include?($os) ? 'yes' : 'no' puts %i[linux freebsd].include?($os) ? 'yes' : 'no'
when 'suggest' when 'suggest'
puts $os == :linux ? %w(tcp) : %w(tcp udp ip arp) puts $os == :linux ? %w[tcp] : %w[tcp udp ip arp]
when 'config' when 'config'
graphs_for(proto_name).each { |graph| graphs_for(proto_name).each do |graph|
puts graph.config.join $/ puts graph.config.join $/
} end
else else
data = netstat_s(proto_name) data = netstat_s(proto_name)
graphs_for(proto_name).each { |graph| graphs_for(proto_name).each do |graph|
puts graph.fetch(data).join $/ puts graph.fetch(data).join $/
} end
warn "not parsed:\n#{data.join}" unless data.empty? if $debug_mode if $debug_mode
warn "not parsed:\n#{data.join}" unless data.empty?
end
end end
# awful performance when scrolling through those regexps above # awful performance when scrolling through those regexps above

View File

@ -21,39 +21,36 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Prerequistes: Prerequistes:
1) env.ORACLE_HOME set in munin-node 1) env.ORACLE_HOME set in munin-node
2) rubygems 2) rubygems
3) oci8 - DBI gem for connecting to Oracle 3) oci8 - DBI gem for connecting to Oracle
* instruction of installing oci8 is available here: * instruction of installing oci8 is available here:
http://ruby-oci8.rubyforge.org/en/InstallBinaryPackage.html http://ruby-oci8.rubyforge.org/en/InstallBinaryPackage.html
Usage: Usage:
1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins) 1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins)
2) chmod to allow executable to others 2) chmod to allow executable to others
3) create symbolic link in /etc/munin/plugins 3) create symbolic link in /etc/munin/plugins
ln -s /usr/share/munin/plugins/oracle_<sid>_pga.rb /etc/munin/plugins/oracle_<sid>_pga.rb ln -s /usr/share/munin/plugins/oracle_<sid>_pga.rb /etc/munin/plugins/oracle_<sid>_pga.rb
** replace <sid> with your oralce sid ** replace <sid> with your oralce sid
Parameters: Parameters:
autoconf autoconf
config (required) config (required)
Configurable variables: Configurable variables:
orauser : oracle user who has select privilege to query v$pgastat view orauser : oracle user who has select privilege to query v$pgastat view
orapass : password for the oracle user orapass : password for the oracle user
dbport : port used by the monitored instance (notice: numeric value) dbport : port used by the monitored instance (notice: numeric value)
dbname : database to be monitored dbname : database to be monitored
dbhost : host or ip address of db instance dbhost : host or ip address of db instance
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
require 'rubygems' require 'rubygems'
require 'oci8' require 'oci8'
@ -69,7 +66,7 @@ tnsname = "(DESCRIPTION =
def runQuery(name, query) def runQuery(name, query)
rows = $conn.exec(query) rows = $conn.exec(query)
puts "#{name}.value #{rows.fetch().to_s}" puts "#{name}.value #{rows.fetch}"
rows.close rows.close
end end
@ -82,31 +79,32 @@ pga_target_query = "SELECT TO_CHAR(ROUND(decode(unit,'bytes',(value)/(1024*1024)
pga_query = "SELECT TO_CHAR(ROUND(decode(unit,'bytes',(value)/(1024*1024),value),2)) pga pga_query = "SELECT TO_CHAR(ROUND(decode(unit,'bytes',(value)/(1024*1024),value),2)) pga
from V$PGASTAT where name = 'total PGA inuse'" from V$PGASTAT where name = 'total PGA inuse'"
pga_components = { "pga_target" => pga_target_query, pga_components = { 'pga_target' => pga_target_query,
"pga_in_use" => pga_query } 'pga_in_use' => pga_query }
# #
# autoconf # autoconf
# #
if ARGV[0] == "autoconf" case ARGV[0]
when 'autoconf'
if tnsname.length > 1 && orauser.length > 1 && orapass.length > 1 if tnsname.length > 1 && orauser.length > 1 && orapass.length > 1
puts "yes" puts 'yes'
else else
puts "no" puts 'no'
puts "Usage: #{__FILE__} autoconf|conf" puts "Usage: #{__FILE__} autoconf|conf"
end end
exit 0 exit 0
# #
# config definition # config definition
# #
elsif ARGV[0] == "config" when 'config'
puts "graph_args --base 1024k -r --lower-limit 0" puts 'graph_args --base 1024k -r --lower-limit 0'
puts "graph_title Oracle PGA from #{dbname}" puts "graph_title Oracle PGA from #{dbname}"
puts "graph_category db" puts 'graph_category db'
puts "graph_info This graph shows the PGA memory usage (in MB)" puts 'graph_info This graph shows the PGA memory usage (in MB)'
puts "graph_vlabel MB" puts 'graph_vlabel MB'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_period second" puts 'graph_period second'
pga_components.keys.each do |p| pga_components.keys.each do |p|
puts "#{p}.label #{p}" puts "#{p}.label #{p}"

View File

@ -21,38 +21,35 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Prerequistes: Prerequistes:
1) env.ORACLE_HOME set in munin-node 1) env.ORACLE_HOME set in munin-node
2) rubygems 2) rubygems
3) oci8 - DBI gem for connecting to Oracle 3) oci8 - DBI gem for connecting to Oracle
* instruction of installing oci8 is available here: * instruction of installing oci8 is available here:
http://ruby-oci8.rubyforge.org/en/InstallBinaryPackage.html http://ruby-oci8.rubyforge.org/en/InstallBinaryPackage.html
Usage: Usage:
1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins) 1) copy this script to the munin install plugins directory (e.g. /usr/share/munin/plugins)
2) chmod to allow executable to others 2) chmod to allow executable to others
3) create symbolic link in /etc/munin/plugins 3) create symbolic link in /etc/munin/plugins
ln -s /usr/share/munin/plugins/oracle_orcl_sga.rb /etc/munin/plugins/oracle_orcl_sga.rb ln -s /usr/share/munin/plugins/oracle_orcl_sga.rb /etc/munin/plugins/oracle_orcl_sga.rb
Parameters: Parameters:
autoconf autoconf
config (required) config (required)
Configurable variables: Configurable variables:
orauser : oracle user who has select privilege to query v$sgastat view orauser : oracle user who has select privilege to query v$sgastat view
orapass : password for the oracle user orapass : password for the oracle user
dbport : port used by the monitored instance (notice: numeric value) dbport : port used by the monitored instance (notice: numeric value)
dbname : database to be monitored dbname : database to be monitored
dbhost : host or ip address of db instance dbhost : host or ip address of db instance
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
require 'rubygems' require 'rubygems'
require 'oci8' require 'oci8'
@ -68,7 +65,7 @@ tnsname = "(DESCRIPTION =
def runQuery(name, query) def runQuery(name, query)
rows = $conn.exec(query) rows = $conn.exec(query)
puts "#{name}.value #{rows.fetch().to_s}" puts "#{name}.value #{rows.fetch}"
rows.close rows.close
end end
@ -102,35 +99,36 @@ log_buffer_query = "SELECT TO_CHAR(ROUND(SUM(decode(pool, NULL,
decode(name, 'log_buffer', (bytes)/(1024*1024),0),0)),2)) sga_lbuffer decode(name, 'log_buffer', (bytes)/(1024*1024),0),0)),2)) sga_lbuffer
from V$SGASTAT" from V$SGASTAT"
memory_components = { "fixed_area" => fixed_area_query, memory_components = { 'fixed_area' => fixed_area_query,
"buffer_cache" => buffer_cache_query, 'buffer_cache' => buffer_cache_query,
"java_pool" => java_pool_query, 'java_pool' => java_pool_query,
"large_pool" => large_pool_query, 'large_pool' => large_pool_query,
"log_buffer" => log_buffer_query, 'log_buffer' => log_buffer_query,
"shared_pool" => shared_pool_query } 'shared_pool' => shared_pool_query }
# #
# autoconf # autoconf
# #
if ARGV[0] == "autoconf" case ARGV[0]
when 'autoconf'
if tnsname.length > 1 && orauser.length > 1 && orapass.length > 1 if tnsname.length > 1 && orauser.length > 1 && orapass.length > 1
puts "yes" puts 'yes'
else else
puts "no" puts 'no'
puts "Usage: #{__FILE__} autoconf|conf" puts "Usage: #{__FILE__} autoconf|conf"
end end
exit 0 exit 0
# #
# config definition # config definition
# #
elsif ARGV[0] == "config" when 'config'
puts "graph_args --base 1024k -r --lower-limit 0" puts 'graph_args --base 1024k -r --lower-limit 0'
puts "graph_title Oracle SGA from #{dbname}" puts "graph_title Oracle SGA from #{dbname}"
puts "graph_category db" puts 'graph_category db'
puts "graph_info This graph shows the SGA memory usage (in MB)" puts 'graph_info This graph shows the SGA memory usage (in MB)'
puts "graph_vlabel MB" puts 'graph_vlabel MB'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_period second" puts 'graph_period second'
memory_components.keys.each do |m| memory_components.keys.each do |m|
puts "#{m}.label #{m}" puts "#{m}.label #{m}"
@ -138,7 +136,7 @@ elsif ARGV[0] == "config"
puts "#{m}.type GAUGE" puts "#{m}.type GAUGE"
# make sure fixed_area is at the bottom of the stack # make sure fixed_area is at the bottom of the stack
if (m == 'fixed_area') if m == 'fixed_area'
puts "#{m}.draw AREA" puts "#{m}.draw AREA"
else else
puts "#{m}.draw STACK" puts "#{m}.draw STACK"

View File

@ -16,53 +16,53 @@ require 'rubygems'
require 'munin' require 'munin'
SERVICE = $0.split('_').last SERVICE = $0.split('_').last
SERVICE_F = '/etc/services' SERVICE_F = '/etc/services'.freeze
PORT = /^[\d]+(\.[\d]+){0,1}$/ === SERVICE ? SERVICE : %x[grep #{SERVICE} #{SERVICE_F}].split("\t\t")[1].split('/')[0] PORT = SERVICE =~ /^\d+(\.\d+){0,1}$/ ? SERVICE : `grep #{SERVICE} #{SERVICE_F}`.split("\t\t")[1].split('/')[0]
class PortMonit < Munin::Plugin class PortMonit < Munin::Plugin
graph_attributes "#{SERVICE} port usage, known as #{PORT}", graph_attributes "#{SERVICE} port usage, known as #{PORT}",
:category => 'network', category: 'network',
:info => 'This graph shows connection split by the state of the socket.', info: 'This graph shows connection split by the state of the socket.',
:vlabel => 'Current connections' vlabel: 'Current connections'
declare_field :ESTABLISHED, declare_field :ESTABLISHED,
:label => 'Established', :draw => :AREA, label: 'Established', draw: :AREA,
:type => :GAUGE, :min => 0 type: :GAUGE, min: 0
declare_field :CLOSE_WAIT, declare_field :CLOSE_WAIT,
:label => 'Waiting close', :draw => :STACK, label: 'Waiting close', draw: :STACK,
:type => :GAUGE, :min => 0 type: :GAUGE, min: 0
declare_field :TIME_WAIT, declare_field :TIME_WAIT,
:label => 'Waiting after close', :draw => :STACK, label: 'Waiting after close', draw: :STACK,
:type => :GAUGE, :min => 0 type: :GAUGE, min: 0
declare_field :CLOSING, declare_field :CLOSING,
:label => 'Closing', :draw => :STACK, label: 'Closing', draw: :STACK,
:type => :GAUGE, :min => 0 type: :GAUGE, min: 0
declare_field :LAST_ACK, declare_field :LAST_ACK,
:label => 'Waiting for acknowledgement', :draw => :STACK, label: 'Waiting for acknowledgement', draw: :STACK,
:type => :GAUGE, :min => 0 type: :GAUGE, min: 0
declare_field :FIN_WAIT_1, declare_field :FIN_WAIT_1,
:label => 'Socket closed, connection shutting down', :draw => :STACK, label: 'Socket closed, connection shutting down', draw: :STACK,
:type => :GAUGE, :min => 0 type: :GAUGE, min: 0
declare_field :FIN_WAIT_2, declare_field :FIN_WAIT_2,
:label => 'Connection closed, Socket still waiting', :draw => :STACK, label: 'Connection closed, Socket still waiting', draw: :STACK,
:type => :GAUGE, :min => 0 type: :GAUGE, min: 0
def retrieve_values def retrieve_values
@_netstat = %x[netstat -n -P tcp | egrep "\.#{PORT} "].split("\n") @_netstat = `netstat -n -P tcp | egrep "\.#{PORT} "`.split("\n")
{ :ESTABLISHED => count(@_netstat, 'ESTABLISHED'), { ESTABLISHED: count(@_netstat, 'ESTABLISHED'),
:CLOSE_WAIT => count(@_netstat, 'CLOSE_WAIT'), CLOSE_WAIT: count(@_netstat, 'CLOSE_WAIT'),
:CLOSING => count(@_netstat, 'CLOSING'), CLOSING: count(@_netstat, 'CLOSING'),
:LAST_ACK => count(@_netstat, 'LAST_ACK'), LAST_ACK: count(@_netstat, 'LAST_ACK'),
:FIN_WAIT_1 => count(@_netstat, 'FIN_WAIT_1'), FIN_WAIT_1: count(@_netstat, 'FIN_WAIT_1'),
:FIN_WAIT_2 => count(@_netstat, 'FIN_WAIT_2'), FIN_WAIT_2: count(@_netstat, 'FIN_WAIT_2'),
:TIME_WAIT => count(@_netstat, 'TIME_WAIT') } TIME_WAIT: count(@_netstat, 'TIME_WAIT') }
end end
private private
@ -72,7 +72,7 @@ class PortMonit < Munin::Plugin
source.each { |obj| @_result += 1 if obj.match(regex) } source.each { |obj| @_result += 1 if obj.match(regex) }
return @_result @_result
end end
end end

View File

@ -11,11 +11,11 @@
memory_stats_command = ENV['memory_stats_command'] || '/opt/ruby-enterprise-1.8.6-20080810/bin/passenger-memory-stats' memory_stats_command = ENV['memory_stats_command'] || '/opt/ruby-enterprise-1.8.6-20080810/bin/passenger-memory-stats'
if ARGV.length > 0 && ARGV[0] == 'config' if ARGV.length > 0 && ARGV[0] == 'config'
puts "graph_title Passenger Memory Usage" puts 'graph_title Passenger Memory Usage'
puts "graph_category webserver" puts 'graph_category webserver'
puts "graph_vlabel MB" puts 'graph_vlabel MB'
puts "apache_rss.label Apache Dirty RSS" puts 'apache_rss.label Apache Dirty RSS'
puts "passenger_rss.label Passenger Dirty RSS" puts 'passenger_rss.label Passenger Dirty RSS'
exit(0) exit(0)
end end

View File

@ -8,13 +8,13 @@
process_stats_command = ENV['process_stats_command'] || '/opt/ruby-enterprise-1.8.6-20080810/bin/passenger-status' process_stats_command = ENV['process_stats_command'] || '/opt/ruby-enterprise-1.8.6-20080810/bin/passenger-status'
if ARGV.length > 0 && ARGV[0] == 'config' if ARGV.length > 0 && ARGV[0] == 'config'
puts "graph_title Passenger Processes" puts 'graph_title Passenger Processes'
puts "graph_category webserver" puts 'graph_category webserver'
puts "graph_vlabel processes" puts 'graph_vlabel processes'
puts "max.label Max processes" puts 'max.label Max processes'
puts "count.label Total processes" puts 'count.label Total processes'
puts "active.label Active processes" puts 'active.label Active processes'
puts "queued.label Queued requests" puts 'queued.label Queued requests'
exit(0) exit(0)
end end
@ -24,13 +24,14 @@ active = nil
queued = nil queued = nil
`#{process_stats_command}`.each_line do |line| `#{process_stats_command}`.each_line do |line|
if /max\s+=\s+(\d+)/.match(line) case line
when /max\s+=\s+(\d+)/
max = $~[1] max = $~[1]
elsif /count\s+=\s+(\d+)/.match(line) when /count\s+=\s+(\d+)/
count = $~[1] count = $~[1]
elsif /^active\s+=\s+(\d+)/.match(line) when /^active\s+=\s+(\d+)/
active = $~[1] active = $~[1]
elsif /Waiting on global queue\s+=\s+(\d+)/.match(line) when /Waiting on global queue\s+=\s+(\d+)/
queued = $~[1] queued = $~[1]
end end
end end

View File

@ -28,27 +28,27 @@ end
def output_values def output_values
status = `sudo passenger-status` status = `sudo passenger-status`
unless $?.success? unless $?.success?
$stderr.puts "failed executing passenger-status" warn 'failed executing passenger-status'
exit 1 exit 1
end end
status =~ /max\s+=\s+(\d+)/ status =~ /max\s+=\s+(\d+)/
puts "max.value #{$1}" puts "max.value #{Regexp.last_match(1)}"
status =~ /count\s+=\s+(\d+)/ status =~ /count\s+=\s+(\d+)/
puts "running.value #{$1}" puts "running.value #{Regexp.last_match(1)}"
status =~ /active\s+=\s+(\d+)/ status =~ /active\s+=\s+(\d+)/
puts "active.value #{$1}" puts "active.value #{Regexp.last_match(1)}"
status =~ /Waiting on global queue:\s+(\d+)/ status =~ /Waiting on global queue:\s+(\d+)/
puts "waiting.value #{$1}" puts "waiting.value #{Regexp.last_match(1)}"
total_sessions = 0 total_sessions = 0
status.scan(/Sessions: (\d+)/).flatten.each { |count| total_sessions += count.to_i } status.scan(/Sessions: (\d+)/).flatten.each { |count| total_sessions += count.to_i }
puts "sessions.value #{total_sessions}" puts "sessions.value #{total_sessions}"
end end
if ARGV[0] == "config" if ARGV[0] == 'config'
output_config output_config
else else
output_values output_values

View File

@ -31,7 +31,7 @@ user = ENV['user'] || 'user'
pwd = ENV['password'] || 'password' pwd = ENV['password'] || 'password'
url = ENV['url'] || 'http://127.0.0.1/control.php' url = ENV['url'] || 'http://127.0.0.1/control.php'
if ARGV[0] == "config" if ARGV[0] == 'config'
print "EAccelerator Monitoring\n" print "EAccelerator Monitoring\n"
print "graph_title PHP Eaccelerator\n" print "graph_title PHP Eaccelerator\n"
print "graph_category webserver\n" print "graph_category webserver\n"
@ -49,54 +49,48 @@ end
one_liners = 0 one_liners = 0
three_liners = 0 three_liners = 0
key = "" key = ''
open(url, :http_basic_authentication => [user, pwd]) do |f| open(url, http_basic_authentication: [user, pwd]) do |f|
f.each do |line| f.each do |line|
if three_liners > 0 if three_liners > 0
three_liners = three_liners + 1 three_liners += 1
if three_liners == 2 print 'Memoryusagepercentage.value ' if three_liners == 2
print "Memoryusagepercentage.value "
end
if three_liners == 3 print 'Memoryusage.value ' if three_liners == 3
print "Memoryusage.value "
end
if three_liners == 4 print 'Memorymax.value ' if three_liners == 4
print "Memorymax.value "
end
print line.gsub!(/[^0-9.]/s, "") print line.gsub!(/[^0-9.]/s, '')
print "\n" print "\n"
end end
if one_liners > 0 if one_liners > 0
one_liners = one_liners + 1 one_liners += 1
print "#{key}.value " print "#{key}.value "
print line.gsub!(/[^0-9.]/s, "") print line.gsub!(/[^0-9.]/s, '')
print "\n" print "\n"
end end
if one_liners > 1 if one_liners > 1
line = "" line = ''
one_liners = 0 one_liners = 0
end end
if three_liners > 3 if three_liners > 3
line = "" line = ''
three_liners = 0 three_liners = 0
end end
if line =~ /Memory usage/ if line =~ /Memory usage/
key = line.gsub!(/(<[^>]*>)|\n|\t| /s, "") key = line.gsub!(/(<[^>]*>)|\n|\t| /s, '')
three_liners = three_liners + 1 three_liners += 1
end end
if line =~ /<td class="e">Free memory/ || line =~ /<td class="e">Cached scripts/ || line =~ /<td class="e">Removed scripts/ || line =~ /<td class="e">Cached keys/ if line =~ /<td class="e">Free memory/ || line =~ /<td class="e">Cached scripts/ || line =~ /<td class="e">Removed scripts/ || line =~ /<td class="e">Cached keys/
key = line.gsub!(/(<[^>]*>)|\n|\t| /s, "") key = line.gsub!(/(<[^>]*>)|\n|\t| /s, '')
one_liners = one_liners + 1 one_liners += 1
end end
end end
end end

View File

@ -15,29 +15,29 @@
# reports how long the puppet agent took to apply the catalog # reports how long the puppet agent took to apply the catalog
def get_runtime def get_runtime
logfile = ENV["puppet_logfile"] || "/var/log/messages" logfile = ENV['puppet_logfile'] || '/var/log/messages'
t = Time.now t = Time.now
dateformat = ENV["puppet_logformat"] || "^%b %d" dateformat = ENV['puppet_logformat'] || '^%b %d'
today = t.strftime(dateformat) today = t.strftime(dateformat)
File.open(logfile).grep(/#{today}/).grep(/Finished catalog run in/).reverse_each do |line| File.open(logfile).grep(/#{today}/).grep(/Finished catalog run in/).reverse_each do |line|
if line =~ /in (.*) seconds/ if line =~ /in (.*) seconds/
puts "runtime.value #{$1}" puts "runtime.value #{Regexp.last_match(1)}"
exit 0 exit 0
end end
end end
end end
case ARGV[0] case ARGV[0]
when "config" when 'config'
puts "graph_category other" puts 'graph_category other'
puts "graph_args --base 1000 -l 0" puts 'graph_args --base 1000 -l 0'
puts "graph_scale no" puts 'graph_scale no'
puts "graph_title puppet catalog run time" puts 'graph_title puppet catalog run time'
puts "graph_vlabel Seconds" puts 'graph_vlabel Seconds'
puts "runtime.label Catalog application time" puts 'runtime.label Catalog application time'
exit 0 exit 0
when "autoconf" when 'autoconf'
puts "yes" puts 'yes'
exit 0 exit 0
else else
get_runtime get_runtime

View File

@ -35,7 +35,6 @@ Some magical munin foo...
=end =end
# Require this module, it is part of the standard ruby lib AFAIK # Require this module, it is part of the standard ruby lib AFAIK
require 'net/http' require 'net/http'
@ -49,7 +48,7 @@ stat = nil
# Check executable "name" for parameter count # Check executable "name" for parameter count
params = $0.split('_') params = $0.split('_')
if params.size != 3 if params.size != 3
puts "Incorrect number of parameters" puts 'Incorrect number of parameters'
exit 1 exit 1
end end
@ -59,11 +58,11 @@ host = params[1]
stat = params[2] stat = params[2]
unless ENV['debug'].nil? unless ENV['debug'].nil?
puts "user = " + user puts 'user = ' + user
puts "pass = " + pass puts 'pass = ' + pass
puts "host = " + host puts 'host = ' + host
puts "port = " + port puts 'port = ' + port
puts "stat = " + stat puts 'stat = ' + stat
end end
# Dump the graph configuration data # Dump the graph configuration data
@ -101,7 +100,7 @@ s = response.body
# Make sure we got the page successfully # Make sure we got the page successfully
if response.code != '200' if response.code != '200'
puts "Getting web page failed:" puts 'Getting web page failed:'
case response.code case response.code
when '401' when '401'
puts 'Probably because the username and password are incorrect' puts 'Probably because the username and password are incorrect'
@ -124,12 +123,12 @@ when 'syncrate'
when 'attenuation' when 'attenuation'
a = s.scan(/.*share\.lineatt.*\n.*share\.down[^0-9]*([0-9]+).*share\.up[^0-9]*([0-9]+).*$/) a = s.scan(/.*share\.lineatt.*\n.*share\.down[^0-9]*([0-9]+).*share\.up[^0-9]*([0-9]+).*$/)
b, c = a[0] b, c = a[0]
puts 'down.value ' + (b.to_i).to_s + "\n" + 'up.value ' + (c.to_i).to_s puts 'down.value ' + b.to_i.to_s + "\n" + 'up.value ' + c.to_i.to_s
exit 0 exit 0
when 'margin', 'noise' when 'margin', 'noise'
a = s.scan(/.*share\.noise.*\n.*share\.down[^0-9]*([0-9]+).*share\.up[^0-9]*([0-9]+).*$/) a = s.scan(/.*share\.noise.*\n.*share\.down[^0-9]*([0-9]+).*share\.up[^0-9]*([0-9]+).*$/)
b, c = a[0] b, c = a[0]
puts 'down.value ' + (b.to_i).to_s + "\n" + 'up.value ' + (c.to_i).to_s puts 'down.value ' + b.to_i.to_s + "\n" + 'up.value ' + c.to_i.to_s
exit 0 exit 0
else else
puts 'Statistic ' + stat.to_s + ' not known, would you like me to fabricate it for you?' puts 'Statistic ' + stat.to_s + ' not known, would you like me to fabricate it for you?'

View File

@ -32,13 +32,13 @@ require 'digest/md5'
require 'nokogiri' require 'nokogiri'
def output def output
nics = Hash.new nics = {}
nics["LAN"] = Hash.new nics['LAN'] = {}
nics["WAN"] = Hash.new nics['WAN'] = {}
nics["WLAN"] = Hash.new nics['WLAN'] = {}
password = ENV['router_password'] || "" password = ENV['router_password'] || ''
router_path = ENV['router_ip_address'] || "10.0.0.1" router_path = ENV['router_ip_address'] || '10.0.0.1'
router_path = "http://" + router_path router_path = 'http://' + router_path
agent = Mechanize.new agent = Mechanize.new
x = agent.get(router_path) x = agent.get(router_path)
salt = x.body.match(/salt = "(.*)"/)[1] salt = x.body.match(/salt = "(.*)"/)[1]
@ -48,7 +48,7 @@ def output
padded_password = password + "\x01" * pad_size padded_password = password + "\x01" * pad_size
# pad it the rest of the way, length 64 for user # pad it the rest of the way, length 64 for user
salted_password = salt + padded_password + ("\x01" * (63 - salt.length - padded_password.length)) + "U" salted_password = salt + padded_password + ("\x01" * (63 - salt.length - padded_password.length)) + 'U'
login_hash = salt + Digest::MD5.hexdigest(salted_password) login_hash = salt + Digest::MD5.hexdigest(salted_password)
# authenticate against the router using the hash that we just built # authenticate against the router using the hash that we just built
@ -61,87 +61,87 @@ def output
doc.xpath('//interface').each do |interface| doc.xpath('//interface').each do |interface|
children = interface.children children = interface.children
name = children.search('name')[0].text name = children.search('name')[0].text
nics[name]["packets_sent"] = children.search('packets_sent')[0].text nics[name]['packets_sent'] = children.search('packets_sent')[0].text
nics[name]["packets_received"] = children.search('packets_received')[0].text nics[name]['packets_received'] = children.search('packets_received')[0].text
nics[name]["tx_dropped"] = children.search('tx_dropped')[0].text nics[name]['tx_dropped'] = children.search('tx_dropped')[0].text
begin begin
nics[name]["tx_collisions"] = children.search('tx_collisions')[0].text nics[name]['tx_collisions'] = children.search('tx_collisions')[0].text
rescue Exception rescue Exception
nics[name]["tx_collisions"] = "0" nics[name]['tx_collisions'] = '0'
end end
nics[name]["rx_dropped"] = children.search('rx_dropped')[0].text nics[name]['rx_dropped'] = children.search('rx_dropped')[0].text
nics[name]["rx_errors"] = children.search('rx_errors')[0].text nics[name]['rx_errors'] = children.search('rx_errors')[0].text
end end
# get wifi associations and print out info for munin graph # get wifi associations and print out info for munin graph
puts "multigraph clients" puts 'multigraph clients'
clients_xml = agent.get("#{router_path}/wifi_assoc.xml").body clients_xml = agent.get("#{router_path}/wifi_assoc.xml").body
j = 0 j = 0
doc = Nokogiri::XML(clients_xml.to_s) doc = Nokogiri::XML(clients_xml.to_s)
doc.xpath('//assoc').each do |assoc| doc.xpath('//assoc').each do |_assoc|
j += 1 j += 1
end end
puts "wifi_assoc.value " + j.to_s puts 'wifi_assoc.value ' + j.to_s
# get dhcp clients and print out info for munin graph # get dhcp clients and print out info for munin graph
clients_xml = agent.get("#{router_path}/dhcp_clients.xml").body clients_xml = agent.get("#{router_path}/dhcp_clients.xml").body
j = 0 j = 0
doc = Nokogiri::XML(clients_xml.to_s) doc = Nokogiri::XML(clients_xml.to_s)
doc.xpath('//client').each do |client| doc.xpath('//client').each do |_client|
j += 1 j += 1
end end
puts "dhcp_clients.value " + j.to_s puts 'dhcp_clients.value ' + j.to_s
puts "multigraph uptime" puts 'multigraph uptime'
# get uptime of connection # get uptime of connection
clients_xml = agent.get("#{router_path}/wan_connection_status.xml").body clients_xml = agent.get("#{router_path}/wan_connection_status.xml").body
doc = Nokogiri::XML(clients_xml.to_s) doc = Nokogiri::XML(clients_xml.to_s)
uptime = doc.children.search('wan_interface_up_time_0')[0].text uptime = doc.children.search('wan_interface_up_time_0')[0].text
puts "uptime.value " + sprintf("%.2f", (Float(uptime) / 86400)) puts 'uptime.value ' + format('%.2f', (Float(uptime) / 86_400))
# graph overall interface packets transferred per interval # graph overall interface packets transferred per interval
puts "multigraph if_packets" puts 'multigraph if_packets'
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "#{i}_recv.value " + nics[i]["packets_received"] puts "#{i}_recv.value " + nics[i]['packets_received']
puts "#{i}_send.value " + nics[i]["packets_sent"] puts "#{i}_send.value " + nics[i]['packets_sent']
end end
# graph overall interface dropped packets per interval # graph overall interface dropped packets per interval
puts "multigraph if_drop" puts 'multigraph if_drop'
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "#{i}_recv.value " + nics[i]["rx_dropped"] puts "#{i}_recv.value " + nics[i]['rx_dropped']
puts "#{i}_send.value " + nics[i]["tx_dropped"] puts "#{i}_send.value " + nics[i]['tx_dropped']
end end
# graph overall interface collisions & errors per interval # graph overall interface collisions & errors per interval
puts "multigraph if_collerr" puts 'multigraph if_collerr'
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "#{i}_coll.value " + nics[i]["tx_collisions"] puts "#{i}_coll.value " + nics[i]['tx_collisions']
puts "#{i}_err.value " + nics[i]["rx_errors"] puts "#{i}_err.value " + nics[i]['rx_errors']
end end
# graph stats for each interface # graph stats for each interface
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "multigraph if_packets.#{i}" puts "multigraph if_packets.#{i}"
puts "send.value " + nics[i]["packets_sent"] puts 'send.value ' + nics[i]['packets_sent']
puts "recv.value " + nics[i]["packets_received"] puts 'recv.value ' + nics[i]['packets_received']
puts "multigraph if_drop.#{i}" puts "multigraph if_drop.#{i}"
puts "send.value " + nics[i]["tx_dropped"] puts 'send.value ' + nics[i]['tx_dropped']
puts "recv.value " + nics[i]["rx_dropped"] puts 'recv.value ' + nics[i]['rx_dropped']
puts "multigraph if_collerr.#{i}" puts "multigraph if_collerr.#{i}"
puts "coll.value " + nics[i]["tx_collisions"] puts 'coll.value ' + nics[i]['tx_collisions']
puts "err.value " + nics[i]["rx_errors"] puts 'err.value ' + nics[i]['rx_errors']
end end
end end
def config def config
# build the configuration for graphs # build the configuration for graphs
puts "multigraph if_packets" puts 'multigraph if_packets'
puts 'graph_title D-Link DIR-655 interface traffic' puts 'graph_title D-Link DIR-655 interface traffic'
puts 'graph_category network' puts 'graph_category network'
puts 'graph_order LAN_recv LAN_send WAN_recv WAN_send WLAN_recv WLAN_send' puts 'graph_order LAN_recv LAN_send WAN_recv WAN_send WLAN_recv WLAN_send'
puts 'graph_vlabel packets in (-) / out (+) per ${graph_period}' puts 'graph_vlabel packets in (-) / out (+) per ${graph_period}'
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "#{i}_recv.type DERIVE" puts "#{i}_recv.type DERIVE"
puts "#{i}_recv.graph no" puts "#{i}_recv.graph no"
puts "#{i}_recv.min 0" puts "#{i}_recv.min 0"
@ -151,12 +151,12 @@ def config
puts "#{i}_send.min 0" puts "#{i}_send.min 0"
end end
puts "multigraph if_drop" puts 'multigraph if_drop'
puts 'graph_title D-Link DIR-655 interface drops' puts 'graph_title D-Link DIR-655 interface drops'
puts 'graph_category network' puts 'graph_category network'
puts 'graph_order LAN_recv LAN_send WAN_recv WAN_send WLAN_recv WLAN_send' puts 'graph_order LAN_recv LAN_send WAN_recv WAN_send WLAN_recv WLAN_send'
puts 'graph_vlabel packets / ${graph_period}' puts 'graph_vlabel packets / ${graph_period}'
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "#{i}_recv.type DERIVE" puts "#{i}_recv.type DERIVE"
puts "#{i}_recv.graph no" puts "#{i}_recv.graph no"
puts "#{i}_recv.min 0" puts "#{i}_recv.min 0"
@ -166,12 +166,12 @@ def config
puts "#{i}_send.min 0" puts "#{i}_send.min 0"
end end
puts "multigraph if_collerr" puts 'multigraph if_collerr'
puts 'graph_title D-Link DIR-655 interface collisions & errors' puts 'graph_title D-Link DIR-655 interface collisions & errors'
puts 'graph_category network' puts 'graph_category network'
puts 'graph_order LAN_coll LAN_err WAN_coll WAN_err WLAN_coll WLAN_coll' puts 'graph_order LAN_coll LAN_err WAN_coll WAN_err WLAN_coll WLAN_coll'
puts 'graph_vlabel packets / ${graph_period}' puts 'graph_vlabel packets / ${graph_period}'
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "#{i}_coll.label #{i} collisions" puts "#{i}_coll.label #{i} collisions"
puts "#{i}_coll.type DERIVE" puts "#{i}_coll.type DERIVE"
puts "#{i}_coll.min 0" puts "#{i}_coll.min 0"
@ -180,26 +180,26 @@ def config
puts "#{i}_err.min 0" puts "#{i}_err.min 0"
end end
puts "multigraph clients" puts 'multigraph clients'
puts "graph_title D-Link DIR-655 client information" puts 'graph_title D-Link DIR-655 client information'
puts "graph_category system" puts 'graph_category system'
puts "graph_order dhcp_clients wifi_assoc" puts 'graph_order dhcp_clients wifi_assoc'
puts "graph_vlabel number of clients" puts 'graph_vlabel number of clients'
puts "dhcp_clients.label DHCP clients" puts 'dhcp_clients.label DHCP clients'
puts "dhcp_clients.type GAUGE" puts 'dhcp_clients.type GAUGE'
puts "dhcp_clients.min 0" puts 'dhcp_clients.min 0'
puts "wifi_assoc.label wifi clients" puts 'wifi_assoc.label wifi clients'
puts "wifi_assoc.type GAUGE" puts 'wifi_assoc.type GAUGE'
puts "wifi_assoc.min 0" puts 'wifi_assoc.min 0'
puts "multigraph uptime" puts 'multigraph uptime'
puts "graph_title Uptime" puts 'graph_title Uptime'
puts 'graph_vlabel uptime in days' puts 'graph_vlabel uptime in days'
puts 'graph_category system' puts 'graph_category system'
puts 'uptime.label uptime' puts 'uptime.label uptime'
puts 'uptime.draw AREA' puts 'uptime.draw AREA'
for i in ["LAN", "WAN", "WLAN"] do %w[LAN WAN WLAN].each do |i|
puts "multigraph if_packets.#{i}" puts "multigraph if_packets.#{i}"
puts "graph_title D-Link DIR-655 #{i} traffic" puts "graph_title D-Link DIR-655 #{i} traffic"
puts 'graph_category network' puts 'graph_category network'
@ -243,8 +243,8 @@ def config
end end
# main # main
if ARGV.length == 1 and ARGV[0] == 'config' if (ARGV.length == 1) && (ARGV[0] == 'config')
config() config
else else
output() output
end end

View File

@ -65,45 +65,43 @@ rights to this plugin are waived. Do with it as you wish.
require 'snmp' require 'snmp'
idx_oid = "enterprises.3955.89.108.1.1.2" idx_oid = 'enterprises.3955.89.108.1.1.2'
max_oid = "enterprises.3955.89.108.1.1.6" max_oid = 'enterprises.3955.89.108.1.1.6'
cur_oid = "enterprises.3955.89.108.1.1.5" cur_oid = 'enterprises.3955.89.108.1.1.5'
community = ENV['community'] || "public" community = ENV['community'] || 'public'
version = ENV['version'] == '1' ? :SNMPv1 : :SNMPv2c version = ENV['version'] == '1' ? :SNMPv1 : :SNMPv2c
case ARGV[0] case ARGV[0]
when "snmpconf" when 'snmpconf'
puts "require 1.3.6.1.4.1.3955.89.108.1.1.2.1. [0-9]" puts 'require 1.3.6.1.4.1.3955.89.108.1.1.2.1. [0-9]'
puts "require 1.3.6.1.4.1.3955.89.108.1.1.5.1. [0-9]" puts 'require 1.3.6.1.4.1.3955.89.108.1.1.5.1. [0-9]'
puts "require 1.3.6.1.4.1.3955.89.108.1.1.6.1. [0-9]" puts 'require 1.3.6.1.4.1.3955.89.108.1.1.6.1. [0-9]'
exit 0; exit 0
when "config" when 'config'
host = $0.match('^(?:|.*\/)snmp_([^_]+)')[1] host = $0.match('^(?:|.*\/)snmp_([^_]+)')[1]
puts "host_name #{host}" puts "host_name #{host}"
puts "graph_title PoE Power Usage" puts 'graph_title PoE Power Usage'
puts "graph_vlabel Watts" puts 'graph_vlabel Watts'
puts "graph_category sensors" puts 'graph_category sensors'
max_current = 0 max_current = 0
SNMP::Manager.open(:Host => host, SNMP::Manager.open(Host: host,
:Community => community, Community: community,
:Version => version) do |manager| Version: version) do |manager|
manager.walk([idx_oid, max_oid]) do |row| manager.walk([idx_oid, max_oid]) do |row|
puts "iface_#{row[0].value}.label Port #{row[0].value}" puts "iface_#{row[0].value}.label Port #{row[0].value}"
puts "iface_#{row[0].value}.cdef iface_#{row[0].value},1000,/" puts "iface_#{row[0].value}.cdef iface_#{row[0].value},1000,/"
puts "iface_#{row[0].value}.line #{row[1].value.to_f / 1000}" puts "iface_#{row[0].value}.line #{row[1].value.to_f / 1000}"
if row[1].value > max_current max_current = row[1].value if row[1].value > max_current
max_current = row[1].value
end
end end
end end
puts "graph_args --upper-limit #{max_current.to_f / 1000}" puts "graph_args --upper-limit #{max_current.to_f / 1000}"
exit 0 exit 0
else else
host = $0.match('^(?:|.*\/)snmp_([^_]+)')[1] host = $0.match('^(?:|.*\/)snmp_([^_]+)')[1]
SNMP::Manager.open(:Host => host, SNMP::Manager.open(Host: host,
:Community => community, Community: community,
:Version => version) do |manager| Version: version) do |manager|
manager.walk([idx_oid, cur_oid]) do |row| manager.walk([idx_oid, cur_oid]) do |row|
puts "iface_#{row[0].value}.value #{row[1].value}" puts "iface_#{row[0].value}.value #{row[1].value}"
end end

View File

@ -1,6 +1,4 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# encoding: utf-8
# Plugin to monitor Room Alert 11E environmental units. # Plugin to monitor Room Alert 11E environmental units.
# Requires ruby and the ruby SNMP library. # Requires ruby and the ruby SNMP library.
# #
@ -34,31 +32,31 @@
require 'snmp' require 'snmp'
base_oid = "enterprises.20916.1.3.1" base_oid = 'enterprises.20916.1.3.1'
case $0.match('[^_]+$')[0] case $0.match('[^_]+$')[0]
when "temperature" when 'temperature'
subchannel = 1 subchannel = 1
name = "temperature" name = 'temperature'
label = "°C" label = '°C'
letter = "t" letter = 't'
when "humidity" when 'humidity'
subchannel = 3 subchannel = 3
name = "humidity" name = 'humidity'
label = "% Relative Humidity" label = '% Relative Humidity'
letter = "h" letter = 'h'
else else
exit 1 exit 1
end end
def is_vb_valid(vb, subchannel) def is_vb_valid(vb, subchannel)
return (vb.name[-1] == 0 and vb.name[-2] == subchannel and vb.value > 1) (vb.name[-1] == 0 and vb.name[-2] == subchannel and vb.value > 1)
end end
def field_name(unit, vb, letter) def field_name(unit, vb, letter)
clean_unit = unit.gsub(/[.-]/, '_') clean_unit = unit.gsub(/[.-]/, '_')
sensor = vb.name[-3].to_s sensor = vb.name[-3].to_s
return "#{clean_unit}_#{letter}#{sensor}" "#{clean_unit}_#{letter}#{sensor}"
end end
def label(unit, vb) def label(unit, vb)
@ -67,28 +65,24 @@ def label(unit, vb)
label = "#{unit} " + (ENV["label_#{clean_unit}_#{sensor}"] || "sensor #{sensor}") label = "#{unit} " + (ENV["label_#{clean_unit}_#{sensor}"] || "sensor #{sensor}")
end end
units = (ENV['units'] || "").split(/\s+/) units = (ENV['units'] || '').split(/\s+/)
community = ENV['community'] || "public" community = ENV['community'] || 'public'
case ARGV[0] case ARGV[0]
when "autoconf" when 'autoconf'
puts "no" puts 'no'
exit 0 exit 0
when "config" when 'config'
puts "graph_title Room Alert 11E units (#{name} probes)" puts "graph_title Room Alert 11E units (#{name} probes)"
puts "graph_vlabel #{label}" puts "graph_vlabel #{label}"
puts "graph_category sensors" puts 'graph_category sensors'
if name == "humidity" puts 'graph_args --lower-limit 0 --upper-limit 100' if name == 'humidity'
puts "graph_args --lower-limit 0 --upper-limit 100"
end
units.each do |unit| units.each do |unit|
SNMP::Manager.open(:Host => unit, SNMP::Manager.open(Host: unit,
:Community => community, Community: community,
:Version => :SNMPv1) do |manager| Version: :SNMPv1) do |manager|
manager.walk(base_oid) do |vb| manager.walk(base_oid) do |vb|
if not is_vb_valid(vb, subchannel) next unless is_vb_valid(vb, subchannel)
next
end
puts "#{field_name(unit, vb, letter)}.label #{label(unit, vb)}" puts "#{field_name(unit, vb, letter)}.label #{label(unit, vb)}"
end end
@ -98,13 +92,11 @@ when "config"
end end
units.each do |unit| units.each do |unit|
SNMP::Manager.open(:Host => unit, SNMP::Manager.open(Host: unit,
:Community => community, Community: community,
:Version => :SNMPv1) do |manager| Version: :SNMPv1) do |manager|
manager.walk(base_oid) do |vb| manager.walk(base_oid) do |vb|
if not is_vb_valid(vb, subchannel) next unless is_vb_valid(vb, subchannel)
next
end
puts "#{field_name(unit, vb, letter)}.value #{vb.value.to_f / 100}" puts "#{field_name(unit, vb, letter)}.value #{vb.value.to_f / 100}"
end end

View File

@ -33,7 +33,6 @@ env.loadpath /usr/local/lib/ruby/gems/1.9.1/gems/geoip-0.8.8/lib/
=end =end
require (ENV['loadpath'] || '') + 'geoip' require (ENV['loadpath'] || '') + 'geoip'
SYSLOG = ENV['syslog'] || '/var/log/secure' SYSLOG = ENV['syslog'] || '/var/log/secure'
@ -45,28 +44,26 @@ AWK_CMD = 'awk \'/sshd\[.*Did not receive identification string/{print $12} ' +
def getInvalids def getInvalids
c = {} c = {}
wholeips = `#{AWK_CMD}`.split("\n") wholeips = `#{AWK_CMD}`.split("\n")
uniqueips = wholeips.inject({}) do |hash, key| uniqueips = wholeips.each_with_object({}) do |key, hash|
hash.include?(key) ? hash[key] += 1 : hash[key] = 1; hash.include?(key) ? hash[key] += 1 : hash[key] = 1
hash
end end
geoip = GeoIP.new(GEOIP_DB) geoip = GeoIP.new(GEOIP_DB)
uniqueips.each do |ip, cnt| uniqueips.each do |ip, cnt|
begin begin
country = geoip.country(ip)[5] country = geoip.country(ip)[5]
c[country] = c[country] ? c[country] + cnt : cnt c[country] = c[country] ? c[country] + cnt : cnt
rescue rescue StandardError
c['Unknown'] = c['Unknown'] ? c['Unknown'] + cnt : cnt c['Unknown'] = c['Unknown'] ? c['Unknown'] + cnt : cnt
end end
end end
c = c.to_a.sort { |a, b| a[0] <=> b[0] } c.to_a.sort { |a, b| a[0] <=> b[0] }
c
end end
case ARGV[0] case ARGV[0]
when 'autoconf' when 'autoconf'
begin begin
fh = open(SYSLOG, 'r') fh = open(SYSLOG, 'r')
rescue rescue StandardError
puts 'no' puts 'no'
exit 0 exit 0
else else
@ -79,7 +76,7 @@ when 'config'
puts 'graph_vlabel number of invalid access per country' puts 'graph_vlabel number of invalid access per country'
puts 'graph_category security' puts 'graph_category security'
puts 'graph_info This graph shows the countries of invalid access to sshd.' puts 'graph_info This graph shows the countries of invalid access to sshd.'
getInvalids.each { |k, v| puts k + '.label ' + k } getInvalids.each { |k, _v| puts k + '.label ' + k }
exit 0 exit 0
else else
getInvalids.each { |k, v| puts k + '.value ' + v.to_s } getInvalids.each { |k, v| puts k + '.value ' + v.to_s }

View File

@ -35,21 +35,19 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
module Munin module Munin
class ThinProcessMemory class ThinProcessMemory
# run main method # run main method
def run def run
instances = get_pids() instances = get_pids
instances.each do |instance| instances.each do |instance|
pid, port = instance.split("|") pid, port = instance.split('|')
rss = (pid_rss(pid).to_i) / 1024 rss = pid_rss(pid).to_i / 1024
puts "thin_#{port}.value #{rss}" puts "thin_#{port}.value #{rss}"
end end
end end
@ -57,10 +55,10 @@ module Munin
# only get the memory for each pid # only get the memory for each pid
def pid_rss(pid) def pid_rss(pid)
res = `grep "VmRSS" /proc/#{pid}/status`.split[1] res = `grep "VmRSS" /proc/#{pid}/status`.split[1]
if res.match("cannot access") if res.match('cannot access')
return nil nil
else else
return res res
end end
end end
@ -70,7 +68,7 @@ module Munin
end end
def autoconf def autoconf
get_pids().length > 0 get_pids.length > 0
end end
end end
end end
@ -78,26 +76,26 @@ end
mpm = Munin::ThinProcessMemory.new mpm = Munin::ThinProcessMemory.new
case ARGV[0] case ARGV[0]
when "config" when 'config'
puts "graph_title Thin Memory" puts 'graph_title Thin Memory'
puts "graph_vlabel RSS" puts 'graph_vlabel RSS'
puts "graph_category webserver" puts 'graph_category webserver'
puts "graph_args --base 1024 -l 0" puts 'graph_args --base 1024 -l 0'
puts "graph_scale yes" puts 'graph_scale yes'
puts "graph_info Tracks the size of individual thin processes" puts 'graph_info Tracks the size of individual thin processes'
mpm.get_pids.each do |instance| mpm.get_pids.each do |instance|
pid, port = instance.split("|") pid, port = instance.split('|')
puts "thin_#{port}.label thin_#{port}" puts "thin_#{port}.label thin_#{port}"
puts "thin_#{port}.info Process memory" puts "thin_#{port}.info Process memory"
puts "thin_#{port}.type GAUGE" puts "thin_#{port}.type GAUGE"
puts "thin_#{port}.min 0" puts "thin_#{port}.min 0"
end end
when "autoconf" when 'autoconf'
if mpm.autoconf if mpm.autoconf
puts "yes" puts 'yes'
exit 0 exit 0
end end
puts "no" puts 'no'
exit 0 exit 0
else else
mpm.run mpm.run

View File

@ -36,20 +36,18 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
module Munin module Munin
class ThinThreads class ThinThreads
def run def run
instances = get_pids() instances = get_pids
instances.each do |instance| instances.each do |instance|
pid, port = instance.split("|") pid, port = instance.split('|')
rss = (get_threads(pid).to_i) rss = get_threads(pid).to_i
puts "thin_#{port}.value #{rss}" puts "thin_#{port}.value #{rss}"
end end
end end
@ -60,11 +58,11 @@ module Munin
# TODO: make this work on OSX and Solaris, # TODO: make this work on OSX and Solaris,
# so the whole unix gang is happy ;) # so the whole unix gang is happy ;)
def get_threads(pid) def get_threads(pid)
res = `grep "Threads" /proc/#{pid}/status | cut -d ":" -f2`.gsub(/\s+/, "") res = `grep "Threads" /proc/#{pid}/status | cut -d ":" -f2`.gsub(/\s+/, '')
if res.match("cannot access") if res.match('cannot access')
return nil nil
else else
return res res
end end
end end
@ -74,7 +72,7 @@ module Munin
end end
def autoconf def autoconf
get_pids().length > 0 get_pids.length > 0
end end
end end
end end
@ -82,26 +80,26 @@ end
mpm = Munin::ThinThreads.new mpm = Munin::ThinThreads.new
case ARGV[0] case ARGV[0]
when "config" when 'config'
puts "graph_title Thin Threads" puts 'graph_title Thin Threads'
puts "graph_vlabel Threads" puts 'graph_vlabel Threads'
puts "graph_category webserver" puts 'graph_category webserver'
puts "graph_args -l 0" puts 'graph_args -l 0'
puts "graph_scale yes" puts 'graph_scale yes'
puts "graph_info Tracks how many threads per thin processes" puts 'graph_info Tracks how many threads per thin processes'
mpm.get_pids.each do |instance| mpm.get_pids.each do |instance|
pid, port = instance.split("|") pid, port = instance.split('|')
puts "thin_#{port}.label thin_#{port}" puts "thin_#{port}.label thin_#{port}"
puts "thin_#{port}.info Threads per Thin process" puts "thin_#{port}.info Threads per Thin process"
puts "thin_#{port}.type GAUGE" puts "thin_#{port}.type GAUGE"
puts "thin_#{port}.min 0" puts "thin_#{port}.min 0"
end end
when "autoconf" when 'autoconf'
if mpm.autoconf if mpm.autoconf
puts "yes" puts 'yes'
exit 0 exit 0
end end
puts "no" puts 'no'
exit 0 exit 0
else else
mpm.run mpm.run

View File

@ -33,20 +33,18 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#%# family=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=end =end
module Munin module Munin
class ThinPeakMemory class ThinPeakMemory
def run def run
instances = get_pids() instances = get_pids
instances.each do |instance| instances.each do |instance|
pid, port = instance.split("|") pid, port = instance.split('|')
hwm = (pid_hwm(pid).to_i) / 1024 hwm = pid_hwm(pid).to_i / 1024
puts "thin_#{port}.value #{hwm}" puts "thin_#{port}.value #{hwm}"
end end
end end
@ -59,10 +57,10 @@ module Munin
# so the whole unix gang is happy ;) # so the whole unix gang is happy ;)
def pid_hwm(pid) def pid_hwm(pid)
res = `grep "VmHWM" /proc/#{pid}/status`.split[1] res = `grep "VmHWM" /proc/#{pid}/status`.split[1]
if res.match("cannot access") if res.match('cannot access')
return nil nil
else else
return res res
end end
end end
@ -72,7 +70,7 @@ module Munin
end end
def autoconf def autoconf
get_pids().length > 0 get_pids.length > 0
end end
end end
end end
@ -80,26 +78,26 @@ end
mpm = Munin::ThinPeakMemory.new mpm = Munin::ThinPeakMemory.new
case ARGV[0] case ARGV[0]
when "config" when 'config'
puts "graph_title Thin Peak Memory (High Water Mark)" puts 'graph_title Thin Peak Memory (High Water Mark)'
puts "graph_vlabel HWM" puts 'graph_vlabel HWM'
puts "graph_category webserver" puts 'graph_category webserver'
puts "graph_args -l 0" puts 'graph_args -l 0'
puts "graph_scale yes" puts 'graph_scale yes'
puts "graph_info Tracks the peak memory of thin processes, aka High Water Mark." puts 'graph_info Tracks the peak memory of thin processes, aka High Water Mark.'
mpm.get_pids.each do |instance| mpm.get_pids.each do |instance|
pid, port = instance.split("|") pid, port = instance.split('|')
puts "thin_#{port}.label thin_#{port}" puts "thin_#{port}.label thin_#{port}"
puts "thin_#{port}.info Peak Memory" puts "thin_#{port}.info Peak Memory"
puts "thin_#{port}.type GAUGE" puts "thin_#{port}.type GAUGE"
puts "thin_#{port}.min 0" puts "thin_#{port}.min 0"
end end
when "autoconf" when 'autoconf'
if mpm.autoconf if mpm.autoconf
puts "yes" puts 'yes'
exit 0 exit 0
end end
puts "no" puts 'no'
exit 0 exit 0
else else
mpm.run mpm.run

View File

@ -8,10 +8,10 @@
# #
# set path to your rails app # set path to your rails app
RAILS_ROOT = "/path/to/rails/app" RAILS_ROOT = '/path/to/rails/app'.freeze
# set name to your unicorn.pid # set name to your unicorn.pid
PID_NAME = "unicorn.pid" PID_NAME = 'unicorn.pid'.freeze
module Munin module Munin
class UnicornMemoryStatus class UnicornMemoryStatus
@ -30,8 +30,9 @@ module Munin
ps_output = `ps w --ppid #{master_pid}` ps_output = `ps w --ppid #{master_pid}`
ps_output.split("\n").each do |line| ps_output.split("\n").each do |line|
chunks = line.strip.split(/\s+/, 5) chunks = line.strip.split(/\s+/, 5)
pid, pcmd = chunks[0], chunks[4] pid = chunks[0]
next if pid !~ /\A\d+\z/ or pcmd !~ /worker/ pcmd = chunks[4]
next if pid !~ /\A\d+\z/ || pcmd !~ /worker/
result << pid.to_i result << pid.to_i
end end
@ -42,18 +43,18 @@ module Munin
result = 0 result = 0
memory = memory_usage memory = memory_usage
result += memory[:master][master_pid] result += memory[:master][master_pid]
memory[:worker].each do |pid, worker_memory| memory[:worker].each do |_pid, worker_memory|
result += worker_memory result += worker_memory
end end
result result
end end
def memory_usage def memory_usage
result = { :master => { master_pid => nil }, :worker => {} } result = { master: { master_pid => nil }, worker: {} }
ps_output = `ps auxw | grep unicorn` ps_output = `ps auxw | grep unicorn`
ps_output.split("\n").each do |line| ps_output.split("\n").each do |line|
chunks = line.strip.split(/\s+/, 11) chunks = line.strip.split(/\s+/, 11)
pid, pmem_rss, _ = chunks.values_at(1, 5, 10) pid, pmem_rss, = chunks.values_at(1, 5, 10)
pmem = pmem_rss.to_i * 1024 pmem = pmem_rss.to_i * 1024
pid = pid.to_i pid = pid.to_i
@ -69,15 +70,15 @@ module Munin
end end
case ARGV[0] case ARGV[0]
when "autoconf" when 'autoconf'
puts "yes" puts 'yes'
when "config" when 'config'
puts "graph_title Unicorn [#{File.basename(__FILE__).gsub(/^unicorn_memory_status_/, '')}] - Memory usage" puts "graph_title Unicorn [#{File.basename(__FILE__).gsub(/^unicorn_memory_status_/, '')}] - Memory usage"
puts "graph_args --base 1024 -l 0" puts 'graph_args --base 1024 -l 0'
puts "graph_vlabel bytes" puts 'graph_vlabel bytes'
puts "graph_category webserver" puts 'graph_category webserver'
puts "total_memory.label total_memory" puts 'total_memory.label total_memory'
puts "total_memory.draw LINE2" puts 'total_memory.draw LINE2'
else else
m = Munin::UnicornMemoryStatus.new(ENV['rails_root'] || RAILS_ROOT, ENV['pid_name'] || PID_NAME) m = Munin::UnicornMemoryStatus.new(ENV['rails_root'] || RAILS_ROOT, ENV['pid_name'] || PID_NAME)
puts "total_memory.value #{m.total_memory}" puts "total_memory.value #{m.total_memory}"

View File

@ -8,10 +8,10 @@
# #
# set path to your rails app # set path to your rails app
RAILS_ROOT = "/path/to/rails/app" RAILS_ROOT = '/path/to/rails/app'.freeze
# set name to your unicorn.pid # set name to your unicorn.pid
PID_NAME = "unicorn.pid" PID_NAME = 'unicorn.pid'.freeze
module Munin module Munin
class UnicornStatus class UnicornStatus
@ -30,8 +30,9 @@ module Munin
ps_output = `ps w --ppid #{master_pid}` ps_output = `ps w --ppid #{master_pid}`
ps_output.split("\n").each do |line| ps_output.split("\n").each do |line|
chunks = line.strip.split(/\s+/, 5) chunks = line.strip.split(/\s+/, 5)
pid, pcmd = chunks[0], chunks[4] pid = chunks[0]
next if pid !~ /\A\d+\z/ or pcmd !~ /worker/ pcmd = chunks[4]
next if pid !~ /\A\d+\z/ || pcmd !~ /worker/
result << pid.to_i result << pid.to_i
end end
@ -67,15 +68,15 @@ module Munin
end end
case ARGV[0] case ARGV[0]
when "autoconf" when 'autoconf'
puts "yes" puts 'yes'
when "config" when 'config'
puts "graph_title Unicorn [#{File.basename(__FILE__).gsub(/^unicorn_status_/, '')}] - Status" puts "graph_title Unicorn [#{File.basename(__FILE__).gsub(/^unicorn_status_/, '')}] - Status"
puts "graph_args -l 0" puts 'graph_args -l 0'
puts "graph_vlabel number of workers" puts 'graph_vlabel number of workers'
puts "graph_category webserver" puts 'graph_category webserver'
puts "total_worker.label total_workers" puts 'total_worker.label total_workers'
puts "idle_worker.label idle_workers" puts 'idle_worker.label idle_workers'
else else
m = Munin::UnicornStatus.new(ENV['rails_root'] || RAILS_ROOT, ENV['pid_name'] || PID_NAME) m = Munin::UnicornStatus.new(ENV['rails_root'] || RAILS_ROOT, ENV['pid_name'] || PID_NAME)
puts "total_worker.value #{m.worker_count}" puts "total_worker.value #{m.worker_count}"

View File

@ -6,39 +6,37 @@
require 'rubygems' require 'rubygems'
require 'jmx4r' require 'jmx4r'
# %# family=auto
#%# family=auto # %# capabilities=autoconf
#%# capabilities=autoconf
# friendly name => result of listPerfStatsKeys via JMX # friendly name => result of listPerfStatsKeys via JMX
keys = { keys = {
"Throughput" => { "vlabel" => "rate", 'Throughput' => { 'vlabel' => 'rate',
"type" => "ABSOLUTE", 'type' => 'ABSOLUTE',
"values" => ["all_operation_throughput","delete_throughput", "get_all_throughput", "get_throughput", "put_throughput"] 'values' => %w[all_operation_throughput delete_throughput get_all_throughput get_throughput put_throughput] },
}, 'Number of Calls' => { 'vlabel' => 'counts',
"Number of Calls" => { "vlabel" => "counts", 'type' => 'COUNTER',
"type" => "COUNTER", 'values' => %w[number_of_calls_to_delete number_of_calls_to_get number_of_calls_to_get_all
"values" => ["number_of_calls_to_delete","number_of_calls_to_get", "number_of_calls_to_get_all", number_of_calls_to_put number_of_exceptions] }
"number_of_calls_to_put", "number_of_exceptions"]
}
} }
if ARGV[0] == "config" case ARGV[0]
when 'config'
keys.each_key do |key| keys.each_key do |key|
puts "multigraph voldemort_#{key.gsub(" ", "_")}" puts "multigraph voldemort_#{key.gsub(' ', '_')}"
puts "graph_title #{key}" puts "graph_title #{key}"
puts "graph_scale no" puts 'graph_scale no'
puts "graph_category search" puts 'graph_category search'
puts "graph_vlabel #{keys[key]['vlabel']}" puts "graph_vlabel #{keys[key]['vlabel']}"
for data in keys[key]['values'] do keys[key]['values'].each do |data|
puts "#{data}.type #{keys[key]['type']}" puts "#{data}.type #{keys[key]['type']}"
puts "#{data}.label #{data.gsub("_", " ")}" puts "#{data}.label #{data.gsub('_', ' ')}"
end end
puts puts
end end
exit 0 exit 0
elsif ARGV[0] == "autoconf" when 'autoconf'
puts "yes" puts 'yes'
exit 0 exit 0
else else
@ -49,16 +47,18 @@ else
# Make the platform MBean server able to work with JBossAS MBeans # Make the platform MBean server able to work with JBossAS MBeans
# JAVA_OPTS="$JAVA_OPTS -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl" # JAVA_OPTS="$JAVA_OPTS -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl"
# JBOSS_CLASSPATH="/opt/webtrends/jboss/bin/mbean" # JBOSS_CLASSPATH="/opt/webtrends/jboss/bin/mbean"
JMX::MBean.establish_connection :port => 5400 JMX::MBean.establish_connection port: 5400
vs = JMX::MBean.find_by_name "voldemort.store.stats.aggregate:type=aggregate-perf" vs = JMX::MBean.find_by_name 'voldemort.store.stats.aggregate:type=aggregate-perf'
keys.each_key do |key| keys.each_key do |key|
puts "multigraph voldemort_#{key.gsub(" ", "_")}" puts "multigraph voldemort_#{key.gsub(' ', '_')}"
for data in keys[key]['values'] do for data in keys[key]['values'] do
puts "#{data}.value #{begin vs.send("#{data}") rescue 0 end}" puts "#{data}.value #{begin begin
vs.send(data.to_s)
rescue StandardError
0
end end}"
end end
puts puts
end end
end end