Skip to content

Commit

Permalink
Merge pull request #74 from blueboxgroup/disk_metrics
Browse files Browse the repository at this point in the history
metrics checks for disk usage
  • Loading branch information
paulczar committed Jun 2, 2016
2 parents d8d079e + f91c9dc commit 07bb186
Show file tree
Hide file tree
Showing 3 changed files with 321 additions and 0 deletions.
113 changes: 113 additions & 0 deletions sensu/plugins/metrics-disk-capacity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#! /usr/bin/env ruby
# encoding: UTF-8
#
# disk-capacity-metrics
#
# DESCRIPTION:
# This plugin uses df to collect disk capacity metrics
# disk-metrics.rb looks at /proc/stat which doesnt hold capacity metricss.
# could have intetrated this into disk-metrics.rb, but thought I'd leave it up to
# whomever implements the checks.
#
# OUTPUT:
# metric data
#
# PLATFORMS:
# Linux
#
# DEPENDENCIES:
# gem: sensu-plugin
# gem: socket
#
# USAGE:
#
# NOTES:
#
# LICENSE:
# Copyright 2012 Sonian, Inc <[email protected]>
# Released under the same terms as Sensu (the MIT license); see LICENSE
# for details.
#

require 'sensu-plugin/metric/cli'
require 'socket'

#
# Disk Capacity
#
class DiskCapacity < Sensu::Plugin::Metric::CLI::Graphite
option :scheme,
description: 'Metric naming scheme, text to prepend to .$parent.$child',
long: '--scheme SCHEME',
default: Socket.gethostname.to_s

# Unused ?
#
def convert_integers(values)
values.each_with_index do |value, index|
begin
converted = Integer(value)
values[index] = converted
rescue ArgumentError # rubocop:disable HandleExceptions
end
end
values
end

# Main function
#
def run
# Get capacity metrics from DF as they don't appear in /proc
`df -PT`.split("\n").drop(1).each do |line|
begin
fs, _type, _blocks, used, avail, capacity, _mnt = line.split

timestamp = Time.now.to_i
if fs =~ '/dev'
fs = fs.gsub('/dev/', '')
metrics = {
disk: {
"#{fs}.used" => used,
"#{fs}.avail" => avail,
"#{fs}.capacity" => capacity.delete('%')
}
}
metrics.each do |parent, children|
children.each do |child, value|
output [config[:scheme], parent, child].join('.'), value, timestamp
end
end
end
rescue
unknown "malformed line from df: #{line}"
end
end

# Get inode capacity metrics
`df -Pi`.split("\n").drop(1).each do |line|
begin
fs, _inodes, used, avail, capacity, _mnt = line.split

timestamp = Time.now.to_i
if fs =~ '/dev'
fs = fs.gsub('/dev/', '')
metrics = {
disk: {
"#{fs}.iused" => used,
"#{fs}.iavail" => avail,
"#{fs}.icapacity" => capacity.delete('%')
}
}
metrics.each do |parent, children|
children.each do |child, value|
output [config[:scheme], parent, child].join('.'), value, timestamp
end
end
end
rescue
unknown "malformed line from df: #{line}"
end
end
ok
end
end
121 changes: 121 additions & 0 deletions sensu/plugins/metrics-disk-usage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#! /usr/bin/env ruby
# encoding: UTF-8
#
# disk-usage-metrics
#
# DESCRIPTION:
# This plugin uses df to collect disk capacity metrics
# disk-usage-metrics.rb looks at /proc/stat which doesnt hold capacity metricss.
#
# OUTPUT:
# metric data
#
# PLATFORMS:
# Linux
#
# DEPENDENCIES:
# gem: sensu-plugin
# gem: socket
#
# USAGE:
#
# NOTES:
# Based on disk-capacity-metrics.rb by bhenerey and nstielau
# The difference here being how the key is defined in graphite and the
# size we emit to graphite(now using megabytes). Also i dropped inode info.
# Using this as an example
# Filesystem Size Used Avail Use% Mounted on
# /dev/mapper/precise64-root 79G 3.5G 72G 5% /
# /dev/sda1 228M 25M 192M 12% /boot
# /dev/sdb1 99G 2G 97G 2% /media/sda1
# The keys with this plugin will be
# disk_usage.root, disk_usage.root.boot, and disk_usage.root.media.sda1
# instead of disk.dev.mapper.precise64-root, disk.sda1, and disk.sda2
#
# Use --flatten option to reduce graphite "tree" by using underscores rather
# then dots for subdirs. Also eliminates 'root' on mounts other than '/'.
# Keys with --flatten option would be
# disk_usage.root, disk_usage.boot, and disk_usage.media_sda1
#
# Mountpoints can be specifically included or ignored using -i or -I options:
# e.g. disk-usage-metric.rb -i ^/boot,^/media
#
# LICENSE:
# Copyright 2012 Sonian, Inc <[email protected]>
# Released under the same terms as Sensu (the MIT license); see LICENSE
# for details.
#

require 'sensu-plugin/metric/cli'
require 'socket'

#
# Disk Usage Metrics
#
class DiskUsageMetrics < Sensu::Plugin::Metric::CLI::Graphite
option :scheme,
description: 'Metric naming scheme, text to prepend to .$parent.$child',
long: '--scheme SCHEME',
default: "#{Socket.gethostname}.disk_usage"

option :ignore_mnt,
description: 'Ignore mounts matching pattern(s)',
short: '-i MNT[,MNT]',
long: '--ignore-mount',
proc: proc { |a| a.split(',') }

option :include_mnt,
description: 'Include only mounts matching pattern(s)',
short: '-I MNT[,MNT]',
long: '--include-mount',
proc: proc { |a| a.split(',') }

option :flatten,
description: 'Output mounts with underscore rather than dot',
short: '-f',
long: '--flatten',
boolean: true,
default: false

option :local,
description: 'Only check local filesystems (df -l option)',
short: '-l',
long: '--local',
boolean: true,
default: false

option :block_size,
description: 'Set block size for sizes printed',
short: '-B BLOCK_SIZE',
long: '--block-size BLOCK_SIZE',
default: 'M'

# Main function
#
def run
delim = config[:flatten] == true ? '_' : '.'
# Get disk usage from df with used and avail in megabytes
# #YELLOW
`df -PB#{config[:block_size]} #{config[:local] ? '-l' : ''}`.split("\n").drop(1).each do |line|
_, _, used, avail, used_p, mnt = line.split

unless %r{/sys[/|$]|/dev[/|$]|/run[/|$]} =~ mnt
next if config[:ignore_mnt] && config[:ignore_mnt].find { |x| mnt.match(x) }
next if config[:include_mnt] && !config[:include_mnt].find { |x| mnt.match(x) }
mnt = if config[:flatten]
mnt.eql?('/') ? 'root' : mnt.gsub(/^\//, '')
else
# If mnt is only / replace that with root if its /tmp/foo
# replace first occurance of / with root.
mnt.length == 1 ? 'root' : mnt.gsub(/^\//, 'root.')
end
# Fix subsequent slashes
mnt = mnt.gsub '/', delim
output [config[:scheme], mnt, 'used'].join('.'), used.gsub(config[:block_size], '')
output [config[:scheme], mnt, 'avail'].join('.'), avail.gsub(config[:block_size], '')
output [config[:scheme], mnt, 'used_percentage'].join('.'), used_p.delete('%')
end
end
ok
end
end
87 changes: 87 additions & 0 deletions sensu/plugins/metrics-disk.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#! /usr/bin/env ruby
# encoding: UTF-8
#
# disk-metrics
#
# DESCRIPTION:
#
# OUTPUT:
# metric data
#
# PLATFORMS:
# Linux
#
# DEPENDENCIES:
# gem: sensu-plugin
# gem: socket
#
# USAGE:
#
# NOTES:
# Devices can be specifically included or ignored using -i or -I options:
# e.g. metrics-disk.rb -I [svx]d[a-z][0-9]*
#
# LICENSE:
# Copyright 2012 Sonian, Inc <[email protected]>
# Released under the same terms as Sensu (the MIT license); see LICENSE
# for details.
#

require 'sensu-plugin/metric/cli'
require 'socket'

#
# Disk Graphite
#
class DiskGraphite < Sensu::Plugin::Metric::CLI::Graphite
option :scheme,
description: 'Metric naming scheme, text to prepend to metric',
short: '-s SCHEME',
long: '--scheme SCHEME',
default: "#{Socket.gethostname}.disk"

# this option uses lsblk to convert the dm-<whatever> name to the LVM name.
# sample metric scheme without this:
# <hostname>.disk.dm-0
# sample metric scheme with this:
# <hostname>.disk.vg-root
option :convert,
description: 'Convert devicemapper to logical volume name',
short: '-c',
long: '--convert',
default: false

option :ignore_device,
description: 'Ignore devices matching pattern(s)',
short: '-i DEV[,DEV]',
long: '--ignore-device',
proc: proc { |a| a.split(',') }

option :include_device,
description: 'Include only devices matching pattern(s)',
short: '-I DEV[,DEV]',
long: '--include-device',
proc: proc { |a| a.split(',') }

# Main function
def run
# http://www.kernel.org/doc/Documentation/iostats.txt
metrics = %w(reads readsMerged sectorsRead readTime writes writesMerged sectorsWritten writeTime ioInProgress ioTime ioTimeWeighted)

File.open('/proc/diskstats', 'r').each_line do |line|
stats = line.strip.split(/\s+/)
_major, _minor, dev = stats.shift(3)
if config[:convert]
dev = `lsblk -P -o NAME /dev/"#{dev}"| cut -d\\" -f2`.lines.first.chomp! if dev =~ /^dm-.*$/
end
next if stats == ['0'].cycle.take(stats.size)

next if config[:ignore_device] && config[:ignore_device].find { |x| dev.match(x) }
next if config[:include_device] && !config[:include_device].find { |x| dev.match(x) }

metrics.size.times { |i| output "#{config[:scheme]}.#{dev}.#{metrics[i]}", stats[i] }
end

ok
end
end

0 comments on commit 07bb186

Please sign in to comment.