Commit 435949eb55fc30edb208025f99b2bc31f1e110b3
0 parents
监控脚本
Showing
17 changed files
with
1382 additions
and
0 deletions
check-cpu.rb
0 → 100755
1 | +++ a/check-cpu.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# | |
3 | +# check-cpu | |
4 | +# | |
5 | +# DESCRIPTION: | |
6 | +# Check cpu usage | |
7 | +# | |
8 | +# OUTPUT: | |
9 | +# plain text | |
10 | +# | |
11 | +# PLATFORMS: | |
12 | +# Linux | |
13 | +# | |
14 | +# DEPENDENCIES: | |
15 | +# gem: sensu-plugin | |
16 | +# | |
17 | +# USAGE: | |
18 | +# #YELLOW | |
19 | +# | |
20 | +# NOTES: | |
21 | +# | |
22 | +# LICENSE: | |
23 | +# Copyright 2014 Sonian, Inc. and contributors. <support@sensuapp.org> | |
24 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
25 | +# for details. | |
26 | +# | |
27 | + | |
28 | +require 'sensu-plugin/check/cli' | |
29 | +require 'json' | |
30 | + | |
31 | +# | |
32 | +# Check CPU | |
33 | +# | |
34 | +class CheckCPU < Sensu::Plugin::Check::CLI | |
35 | + CPU_METRICS = [:user, :nice, :system, :idle, :iowait, :irq, :softirq, :steal, :guest, :guest_nice].freeze | |
36 | + | |
37 | + option :less_than, | |
38 | + description: 'Change whether value is less than check', | |
39 | + short: '-l', | |
40 | + long: '--less_than', | |
41 | + default: false, | |
42 | + boolean: true | |
43 | + | |
44 | + option :warn, | |
45 | + short: '-w WARN', | |
46 | + proc: proc(&:to_f), | |
47 | + default: 80 | |
48 | + | |
49 | + option :crit, | |
50 | + short: '-c CRIT', | |
51 | + proc: proc(&:to_f), | |
52 | + default: 100 | |
53 | + | |
54 | + option :sleep, | |
55 | + long: '--sleep SLEEP', | |
56 | + proc: proc(&:to_f), | |
57 | + default: 1 | |
58 | + | |
59 | + option :cache_file, | |
60 | + long: '--cache-file CACHEFILE', | |
61 | + default: nil | |
62 | + | |
63 | + option :proc_path, | |
64 | + long: '--proc-path /proc', | |
65 | + proc: proc(&:to_s), | |
66 | + default: '/proc' | |
67 | + | |
68 | + option :idle_metrics, | |
69 | + long: '--idle-metrics METRICS', | |
70 | + description: 'Treat the specified metrics as idle. Defaults to idle,iowait,steal,guest,guest_nice', | |
71 | + proc: proc { |x| x.split(/,/).map { |y| y.strip.to_sym } }, | |
72 | + default: [:idle, :iowait, :steal, :guest, :guest_nice] | |
73 | + | |
74 | + CPU_METRICS.each do |metric| | |
75 | + option metric, | |
76 | + long: "--#{metric}", | |
77 | + description: "Check cpu #{metric} instead of total cpu usage", | |
78 | + boolean: true, | |
79 | + default: false | |
80 | + end | |
81 | + | |
82 | + def acquire_cpu_stats | |
83 | + File.open("#{config[:proc_path]}/stat", 'r').each_line do |line| | |
84 | + info = line.split(/\s+/) | |
85 | + name = info.shift | |
86 | + return info.map(&:to_f) if name =~ /^cpu$/ | |
87 | + end | |
88 | + end | |
89 | + | |
90 | + def acquire_stats_with_sleeping(sec) | |
91 | + before = acquire_cpu_stats | |
92 | + sleep sec | |
93 | + after = acquire_cpu_stats | |
94 | + | |
95 | + [before, after] | |
96 | + end | |
97 | + | |
98 | + def acquire_stats_with_cache_file | |
99 | + before = JSON.parse(File.read(config[:cache_file])) | |
100 | + now = acquire_cpu_stats | |
101 | + | |
102 | + [before, now] | |
103 | + end | |
104 | + | |
105 | + def write_stats_to_cache_file(data) | |
106 | + File.write(config[:cache_file], data) | |
107 | + end | |
108 | + | |
109 | + def acquire_stats(sec) | |
110 | + if config[:cache_file] && File.exist?(config[:cache_file]) | |
111 | + (before, now) = acquire_stats_with_cache_file | |
112 | + else | |
113 | + (before, now) = acquire_stats_with_sleeping(sec) | |
114 | + end | |
115 | + | |
116 | + write_stats_to_cache_file(now) if config[:cache_file] | |
117 | + | |
118 | + [before, now] | |
119 | + end | |
120 | + | |
121 | + def run | |
122 | + (cpu_stats_before, cpu_stats_now) = acquire_stats(config[:sleep]) | |
123 | + | |
124 | + # Some kernels don't have 'guest' and 'guest_nice' values | |
125 | + metrics = CPU_METRICS.slice(0, cpu_stats_now.length) | |
126 | + | |
127 | + cpu_total_diff = 0.to_f | |
128 | + cpu_stats_diff = [] | |
129 | + metrics.each_index do |i| | |
130 | + cpu_stats_diff[i] = cpu_stats_now[i] - cpu_stats_before[i] | |
131 | + cpu_total_diff += cpu_stats_diff[i] | |
132 | + end | |
133 | + | |
134 | + cpu_stats = [] | |
135 | + metrics.each_index do |i| | |
136 | + cpu_stats[i] = 100 * (cpu_stats_diff[i] / cpu_total_diff) | |
137 | + end | |
138 | + | |
139 | + idle_diff = metrics.each_with_index.map { |metric, i| config[:idle_metrics].include?(metric) ? cpu_stats_diff[i] : 0.0 }.reduce(0.0, :+) | |
140 | + | |
141 | + cpu_usage = 100 * (cpu_total_diff - idle_diff) / cpu_total_diff | |
142 | + checked_usage = cpu_usage | |
143 | + | |
144 | + self.class.check_name 'CheckCPU TOTAL' | |
145 | + metrics.each do |metric| | |
146 | + if config[metric] | |
147 | + self.class.check_name "CheckCPU #{metric.to_s.upcase}" | |
148 | + checked_usage = cpu_stats[metrics.find_index(metric)] | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + msg = "total=#{(cpu_usage * 100).round / 100.0}" | |
153 | + cpu_stats.each_index { |i| msg += " #{metrics[i]}=#{(cpu_stats[i] * 100).round / 100.0}" } | |
154 | + | |
155 | + message msg | |
156 | + | |
157 | + if config[:less_than] | |
158 | + critical if checked_usage <= config[:crit] | |
159 | + warning if checked_usage <= config[:warn] | |
160 | + else | |
161 | + critical if checked_usage >= config[:crit] | |
162 | + warning if checked_usage >= config[:warn] | |
163 | + end | |
164 | + ok | |
165 | + end | |
166 | +end | ... | ... |
check-cpu.sh
0 → 100755
1 | +++ a/check-cpu.sh | |
1 | +#!/bin/bash | |
2 | +# | |
3 | +# Check CPU usage | |
4 | +# | |
5 | +# === | |
6 | +# | |
7 | +# Examples: | |
8 | +# | |
9 | +# check-cpu.sh -w 85 -c 95 | |
10 | +# | |
11 | +# Date: 2014-09-12 | |
12 | +# Author: Jun Ichikawa <jun1ka0@gmail.com> | |
13 | +# | |
14 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
15 | +# for details. | |
16 | + | |
17 | +# get arguments | |
18 | +while getopts ':w:c:h' OPT; do | |
19 | + case $OPT in | |
20 | + w) WARN=$OPTARG;; | |
21 | + c) CRIT=$OPTARG;; | |
22 | + h) hlp="yes";; | |
23 | + *) unknown="yes";; | |
24 | + esac | |
25 | +done | |
26 | + | |
27 | +PROC_PATH=${PROC_PATH:-'/proc'} | |
28 | + | |
29 | +# usage | |
30 | +HELP=" | |
31 | + usage: $0 [ -w value -c value -p -h ] | |
32 | + | |
33 | + -w --> Warning percentage < value | |
34 | + -c --> Critical percentage < value | |
35 | + -h --> print this help screen | |
36 | +" | |
37 | + | |
38 | +if [ "$hlp" = "yes" ]; then | |
39 | + echo "$HELP" | |
40 | + exit 0 | |
41 | +fi | |
42 | + | |
43 | +cpuusage1=(`cat /proc/stat | head -1`) | |
44 | +if [ ${#cpuusage1} -eq 0 ]; then | |
45 | + echo "CRITICAL - CPU UNKNOWN" | |
46 | + exit 2 | |
47 | +fi | |
48 | +sleep 1 | |
49 | +cpuusage2=(`cat $PROC_PATH/stat | head -1`) | |
50 | +if [ ${#cpuusage2} -eq 0 ]; then | |
51 | + echo "CRITICAL - CPU UNKNOWN" | |
52 | + exit 2 | |
53 | +fi | |
54 | + | |
55 | +WARN=${WARN:=90} | |
56 | +CRIT=${CRIT:=95} | |
57 | + | |
58 | +cpu_diff=(0) | |
59 | +total=0 | |
60 | +usage_diff=0 | |
61 | +for i in `seq 1 9` | |
62 | +do | |
63 | + cpu_diff=("${cpu_diff[@]}" `echo "${cpuusage2[$i]}-${cpuusage1[$i]}" | bc`) | |
64 | + total=`echo "$total+${cpu_diff[$i]}" | bc` | |
65 | + if [ $i -ne "4" ]; then | |
66 | + usage_diff=`echo "$usage_diff+${cpu_diff[$i]}" | bc` | |
67 | + else | |
68 | + idl=$cpu_diff[$i] | |
69 | + fi | |
70 | +done | |
71 | +cpu_usage=`echo "scale=2; 100*$usage_diff/$total" | bc` | |
72 | + | |
73 | +if [ "$(echo "${cpu_usage} > ${CRIT}" | bc)" -eq 1 ]; then | |
74 | + echo "CPU CRITICAL - ${cpu_usage}% is greater than critical point.[${CRIT}]" | |
75 | + exit 2 | |
76 | +fi | |
77 | + | |
78 | +if [ "$(echo "${cpu_usage} > ${WARN}" | bc)" -eq 1 ]; then | |
79 | + echo "CPU WARNING - ${cpu_usage}% is greater than warning point.[${WARN}]" | |
80 | + exit 1 | |
81 | +fi | |
82 | + | |
83 | +echo "CPU OK - Usage:${cpu_usage}" | |
84 | +exit 0 | ... | ... |
check-disk.sh
0 → 100755
1 | +++ a/check-disk.sh | |
1 | +#!/bin/bash | |
2 | + | |
3 | +while getopts 'w:c:h:' OPT | |
4 | +do | |
5 | + case $OPT in | |
6 | + w) WARN=$OPTARG;; | |
7 | + c) CRIT=$OPTARG;; | |
8 | + h) hlp="yes";; | |
9 | + *) unknown="yes";; | |
10 | + esac | |
11 | +done | |
12 | + | |
13 | +# usage | |
14 | +HELP=" | |
15 | + usage: $0 [ -w value -c value -h ] | |
16 | + | |
17 | + -w --> Warning percentage < value | |
18 | + -c --> Critical percentage < value | |
19 | + -h --> print this help screen | |
20 | +" | |
21 | +hlp=${hlp:=no} | |
22 | +if [ ${hlp} == "yes" ] | |
23 | +then | |
24 | + echo ${HELP} | |
25 | + exit 0 | |
26 | +fi | |
27 | + | |
28 | +WARN=${WARN:=90} | |
29 | +CRIT=${CRIT:=95} | |
30 | + | |
31 | +disk_message=$(df -h | awk 'NR>1') | |
32 | + | |
33 | +warn_flag=$(echo "$disk_message" | awk -v warn=${WARN} 'int($5)>warn' | wc -l) | |
34 | +crit_flag=$(echo "$disk_message" | awk -v crit=${CRIT} 'int($5)>crit' | wc -l) | |
35 | + | |
36 | +if [ ${crit_flag} -ge 1 ] | |
37 | +then | |
38 | + echo "$disk_message" | awk -v crit=${CRIT} 'int($5)>crit{print "CRITICAL: disk "$NF" used "$5}' | |
39 | + exit 2 | |
40 | +elif [ ${warn_flag} -ge 1 ] | |
41 | +then | |
42 | + echo "$disk_message" | awk -v warn=${WARN} 'int($5)>warn{print "WARNING: disk "$NF" used "$5}' | |
43 | + exit 1 | |
44 | +else | |
45 | + echo "OK: all disk is ok" | |
46 | + exit 0 | |
47 | +fi | ... | ... |
check-io.sh
0 → 100755
1 | +++ a/check-io.sh | |
1 | +#!/bin/bash | |
2 | + | |
3 | +while getopts 'w:c:h:' OPT | |
4 | +do | |
5 | + case $OPT in | |
6 | + w) WARN=$OPTARG;; | |
7 | + c) CRIT=$OPTARG;; | |
8 | + h) hlp="yes";; | |
9 | + *) unknown="yes";; | |
10 | + esac | |
11 | +done | |
12 | + | |
13 | +# usage | |
14 | +HELP=" | |
15 | + usage: $0 [ -w value -c value -h ] | |
16 | + | |
17 | + -w --> Warning percentage < value | |
18 | + -c --> Critical percentage < value | |
19 | + -h --> print this help screen | |
20 | +" | |
21 | +hlp=${hlp:=no} | |
22 | +if [ ${hlp} == "yes" ] | |
23 | +then | |
24 | + echo ${HELP} | |
25 | +fi | |
26 | + | |
27 | +WARN=${WARN:=90} | |
28 | +CRIT=${CRIT:=95} | |
29 | + | |
30 | +io_message=$(iostat -x 1 1 | egrep [0-9] | awk 'NR>2') | |
31 | + | |
32 | +warn_flag=$(echo "$io_message" | awk -v warn=${WARN} '$NF>warn' | wc -l) | |
33 | +crit_flag=$(echo "$io_message" | awk -v crit=${CRIT} '$NF>crit' | wc -l) | |
34 | + | |
35 | +if [ ${crit_flag} -ge 1 ] | |
36 | +then | |
37 | + echo "$io_message" | awk -v crit=${CRIT} '$NF>crit{print "CRITICAL: disk "$1" io used "$NF"%"}' | |
38 | + exit 2 | |
39 | +elif [ ${warn_flag} -ge 1 ] | |
40 | +then | |
41 | + echo "$io_message" | awk -v warn=${WARN} '$NF>warn{print "WARNING: disk "$1" io used "$NF"%"}' | |
42 | + exit 1 | |
43 | +else | |
44 | + echo "OK: all disk io is ok" | |
45 | + exit 0 | |
46 | +fi | ... | ... |
check-load.rb
0 → 100755
1 | +++ a/check-load.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# | |
3 | +# check-load | |
4 | +# | |
5 | +# DESCRIPTION: | |
6 | +# | |
7 | +# OUTPUT: | |
8 | +# plain text | |
9 | +# | |
10 | +# PLATFORMS: | |
11 | +# Linux, BSD, Solaris, etc | |
12 | +# | |
13 | +# DEPENDENCIES: | |
14 | +# gem: sensu-plugin | |
15 | +# | |
16 | +# USAGE: | |
17 | +# ./bin/check-load.rb --help | |
18 | +# NOTES: | |
19 | +# | |
20 | +# LICENSE: | |
21 | +# Copyright 2012 Sonian, Inc <chefs@sonian.net> | |
22 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
23 | +# for details. | |
24 | +# | |
25 | + | |
26 | +require 'sensu-plugin/check/cli' | |
27 | +require_relative '../lib/sensu-plugins-load-checks/load-average.rb' | |
28 | + | |
29 | +class CheckLoad < Sensu::Plugin::Check::CLI | |
30 | + option :warn, | |
31 | + short: '-w L1,L5,L15', | |
32 | + long: '--warn L1,L5,L15', | |
33 | + description: 'Load WARNING threshold, 1/5/15 min average', | |
34 | + proc: proc { |a| a.split(',').map(&:to_f) }, | |
35 | + default: [2.75, 2.5, 2.0] | |
36 | + | |
37 | + option :crit, | |
38 | + short: '-c L1,L5,L15', | |
39 | + long: '--crit L1,L5,L15', | |
40 | + description: 'Load CRITICAL threshold, 1/5/15 min average', | |
41 | + proc: proc { |a| a.split(',').map(&:to_f) }, | |
42 | + default: [3.5, 3.25, 3.0] | |
43 | + | |
44 | + def run | |
45 | + data = LoadAverage.new | |
46 | + unknown 'Could not read load average from /proc or `uptime`' if data.failed? | |
47 | + | |
48 | + message "Per core load average (#{data.cpu_count} CPU): #{data.load_avg}" | |
49 | + | |
50 | + critical if data.exceed?(config[:crit]) | |
51 | + warning if data.exceed?(config[:warn]) | |
52 | + ok | |
53 | + end | |
54 | +end | ... | ... |
check-memory-percent.rb
0 → 100755
check-memory-percent.sh
0 → 100755
1 | +++ a/check-memory-percent.sh | |
1 | +#!/usr/bin/env bash | |
2 | +# | |
3 | +# Evaluate free system memory from Linux based systems based on percentage | |
4 | +# This was forked from Sensu Community Plugins | |
5 | +# | |
6 | +# Date: 2007-11-12 | |
7 | +# Author: Thomas Borger - ESG | |
8 | +# Date: 2012-04-02 | |
9 | +# Modified: Norman Harman - norman.harman@mutualmobile.com | |
10 | +# Date: 2013-9-30 | |
11 | +# Modified: Mario Harvey - Zumetrics | |
12 | +# Date: 2015-01-10 | |
13 | +# Modified Ollie Armstrong <ollie@armstrong.io> | |
14 | +# Date: 2016-02-15 | |
15 | +# Modified: J. Brandt Buckley <brandt.buckley@sendgrid.com> | |
16 | + | |
17 | +# set lang | |
18 | +LANG=C | |
19 | + | |
20 | +# get arguments | |
21 | + | |
22 | +# #RED | |
23 | +while getopts 'w:c:hp' OPT; do | |
24 | + case $OPT in | |
25 | + w) WARN=$OPTARG;; | |
26 | + c) CRIT=$OPTARG;; | |
27 | + h) hlp="yes";; | |
28 | + p) perform="yes";; | |
29 | + *) unknown="yes";; | |
30 | + esac | |
31 | +done | |
32 | + | |
33 | +# usage | |
34 | +HELP=" | |
35 | + usage: $0 [ -w value -c value -p -h ] | |
36 | + | |
37 | + -w --> Warning Percentage < value | |
38 | + -c --> Critical Percentage < value | |
39 | + -p --> print out performance data | |
40 | + -h --> print this help screen | |
41 | +" | |
42 | + | |
43 | +if [ "$hlp" = "yes" ]; then | |
44 | + echo "$HELP" | |
45 | + exit 0 | |
46 | +fi | |
47 | + | |
48 | +WARN=${WARN:=80} | |
49 | +CRIT=${CRIT:=90} | |
50 | + | |
51 | +#Get total memory available on machine | |
52 | +TotalMem=$(free -m | grep Mem | awk '{ print $2 }') | |
53 | +#Determine amount of free memory on the machine | |
54 | +set -o pipefail | |
55 | +FreeMem=$(free -m | grep buffers/cache | awk '{ print $4 }') | |
56 | +if [ $? -ne 0 ]; | |
57 | + then | |
58 | + FreeMem=$(free -m | grep Mem | awk '{ print $7 }') | |
59 | +fi | |
60 | +#Get percentage of free memory | |
61 | +FreePer=$(awk -v total="$TotalMem" -v free="$FreeMem" 'BEGIN { printf("%-10f\n", (free / total) * 100) }' | cut -d. -f1) | |
62 | +#Get actual memory usage percentage by subtracting free memory percentage from 100 | |
63 | +UsedPer=$((100-$FreePer)) | |
64 | + | |
65 | + | |
66 | +if [ "$UsedPer" = "" ]; then | |
67 | + echo "MEM UNKNOWN -" | |
68 | + exit 3 | |
69 | +fi | |
70 | + | |
71 | +if [ "$perform" = "yes" ]; then | |
72 | + output="system memory usage: $UsedPer% | free memory="$UsedPer"%;$WARN;$CRIT;0" | |
73 | +else | |
74 | + output="system memory usage: $UsedPer%" | |
75 | +fi | |
76 | + | |
77 | +if (( $UsedPer >= $CRIT )); then | |
78 | + echo "MEM CRITICAL - $output" | |
79 | + exit 2 | |
80 | +elif (( $UsedPer >= $WARN )); then | |
81 | + echo "MEM WARNING - $output" | |
82 | + exit 1 | |
83 | +else | |
84 | + echo "MEM OK - $output" | |
85 | + exit 0 | |
86 | +fi | ... | ... |
check-process.sh
0 → 100755
1 | +++ a/check-process.sh | |
1 | +#!/bin/bash | |
2 | + | |
3 | +while getopts 'n:p:h' OPT | |
4 | +do | |
5 | + case $OPT in | |
6 | + n) name=$OPTARG;; | |
7 | + p) port=$OPTARG;; | |
8 | + h) hlp="yes";; | |
9 | + *) unknown="yes";; | |
10 | + esac | |
11 | +done | |
12 | + | |
13 | +# usage | |
14 | +HELP=" | |
15 | + usage: $0 [ -n process name -p process port -h ] | |
16 | + | |
17 | + -n --> process name < value | |
18 | + -p --> process port < value | |
19 | + -h --> print this help screen | |
20 | +" | |
21 | +hlp=${hlp:=no} | |
22 | +if [ ${hlp} == "yes" ] || [ "${name}" == "" ] | |
23 | +then | |
24 | + echo "${HELP}" | |
25 | + exit 0 | |
26 | +fi | |
27 | + | |
28 | +function getpid(){ | |
29 | + pid=$(sudo ps -ef | grep "${name}" | grep -v grep | grep -v $0 | awk 'NR==1{print $2}' ) | |
30 | +} | |
31 | + | |
32 | +if [ "${name}" == "" ] | |
33 | +then | |
34 | + exit 0 | |
35 | +else | |
36 | + process_flag=$(sudo ps -ef | grep ${name} | grep -v grep | grep -v $0 | wc -l) | |
37 | +fi | |
38 | + | |
39 | +if [ "${port}" == "" ] | |
40 | +then | |
41 | + port_flag=1 | |
42 | +else | |
43 | + port_flag=$(sudo netstat -lntp | grep ":${port} " | wc -l) | |
44 | +fi | |
45 | + | |
46 | +if [ ${process_flag} -ge 1 ] && [ ${port_flag} -ge 1 ] | |
47 | +then | |
48 | + echo "Ok: ${name} is ok,port is ${port}." | |
49 | + exit 0 | |
50 | +else | |
51 | + echo "ERROR: ${name} is error,port is ${port}." | |
52 | + exit 2 | |
53 | +fi | ... | ... |
metrics-cpu-pcnt-usage.rb
0 → 100755
1 | +++ a/metrics-cpu-pcnt-usage.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# encoding: UTF-8 | |
3 | +# | |
4 | +# cpu-pct-usage-metrics | |
5 | +# | |
6 | +# DESCRIPTION: | |
7 | +# | |
8 | +# OUTPUT: | |
9 | +# metric data | |
10 | +# | |
11 | +# PLATFORMS: | |
12 | +# Linux | |
13 | +# | |
14 | +# DEPENDENCIES: | |
15 | +# gem: sensu-plugin | |
16 | +# | |
17 | +# USAGE: | |
18 | +# | |
19 | +# NOTES: | |
20 | +# | |
21 | +# LICENSE: | |
22 | +# Copyright 2012 Sonian, Inc <chefs@sonian.net> | |
23 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
24 | +# for details. | |
25 | +# | |
26 | +require 'sensu-plugin/metric/cli' | |
27 | +require 'socket' | |
28 | + | |
29 | +# | |
30 | +# CPU Graphite | |
31 | +# | |
32 | +class CpuGraphite < Sensu::Plugin::Metric::CLI::Graphite | |
33 | + option :scheme, | |
34 | + description: 'Metric naming scheme, text to prepend to metric', | |
35 | + short: '-s SCHEME', | |
36 | + long: '--scheme SCHEME', | |
37 | + default: "#{Socket.gethostname}.cpu" | |
38 | + | |
39 | + option :proc_path, | |
40 | + long: '--proc-path /proc', | |
41 | + proc: proc(&:to_s), | |
42 | + default: '/proc' | |
43 | + | |
44 | + def acquire_proc_stats | |
45 | + cpu_metrics = %w(user nice system idle iowait irq softirq steal guest) | |
46 | + File.open("#{config[:proc_path]}/stat", 'r').each_line do |line| | |
47 | + info = line.split(/\s+/) | |
48 | + next if info.empty? | |
49 | + name = info.shift | |
50 | + | |
51 | + # we are matching TOTAL stats and returning a hash of values | |
52 | + if name =~ /^cpu$/ | |
53 | + # return the CPU metrics sample as a hash | |
54 | + # filter out nil values, as some kernels don't have a 'guest' value | |
55 | + return Hash[cpu_metrics.zip(info.map(&:to_i))].reject { |_key, value| value.nil? } | |
56 | + end | |
57 | + end | |
58 | + end | |
59 | + | |
60 | + def sum_cpu_metrics(metrics) | |
61 | + # #YELLOW | |
62 | + metrics.values.reduce { |sum, metric| sum + metric } # rubocop:disable SingleLineBlockParams | |
63 | + end | |
64 | + | |
65 | + def run | |
66 | + cpu_sample1 = acquire_proc_stats | |
67 | + sleep(1) | |
68 | + cpu_sample2 = acquire_proc_stats | |
69 | + cpu_metrics = cpu_sample2.keys | |
70 | + | |
71 | + # we will sum all jiffy counts read in acquire_proc_stats | |
72 | + cpu_total1 = sum_cpu_metrics(cpu_sample1) | |
73 | + cpu_total2 = sum_cpu_metrics(cpu_sample2) | |
74 | + # total cpu usage in last second in CPU jiffs (1/100 s) | |
75 | + cpu_total_diff = cpu_total2 - cpu_total1 | |
76 | + # per CPU metric diff | |
77 | + cpu_sample_diff = Hash[cpu_sample2.map { |k, v| [k, v - cpu_sample1[k]] }] | |
78 | + | |
79 | + cpu_metrics.each do |metric| | |
80 | + metric_val = sprintf('%.02f', (cpu_sample_diff[metric] / cpu_total_diff.to_f) * 100) | |
81 | + output "#{config[:scheme]}.#{metric}", metric_val | |
82 | + end | |
83 | + ok | |
84 | + end | |
85 | +end | ... | ... |
metrics-disk-usage.rb
0 → 100755
1 | +++ a/metrics-disk-usage.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# encoding: UTF-8 | |
3 | +# | |
4 | +# disk-usage-metrics | |
5 | +# | |
6 | +# DESCRIPTION: | |
7 | +# This plugin uses df to collect disk capacity metrics | |
8 | +# disk-usage-metrics.rb looks at /proc/stat which doesnt hold capacity metricss. | |
9 | +# | |
10 | +# OUTPUT: | |
11 | +# metric data | |
12 | +# | |
13 | +# PLATFORMS: | |
14 | +# Linux | |
15 | +# | |
16 | +# DEPENDENCIES: | |
17 | +# gem: sensu-plugin | |
18 | +# gem: socket | |
19 | +# | |
20 | +# USAGE: | |
21 | +# | |
22 | +# NOTES: | |
23 | +# Based on disk-capacity-metrics.rb by bhenerey and nstielau | |
24 | +# The difference here being how the key is defined in graphite and the | |
25 | +# size we emit to graphite(now using megabytes). Also i dropped inode info. | |
26 | +# Using this as an example | |
27 | +# Filesystem Size Used Avail Use% Mounted on | |
28 | +# /dev/mapper/precise64-root 79G 3.5G 72G 5% / | |
29 | +# /dev/sda1 228M 25M 192M 12% /boot | |
30 | +# /dev/sdb1 99G 2G 97G 2% /media/sda1 | |
31 | +# The keys with this plugin will be | |
32 | +# disk_usage.root, disk_usage.root.boot, and disk_usage.root.media.sda1 | |
33 | +# instead of disk.dev.mapper.precise64-root, disk.sda1, and disk.sda2 | |
34 | +# | |
35 | +# Use --flatten option to reduce graphite "tree" by using underscores rather | |
36 | +# then dots for subdirs. Also eliminates 'root' on mounts other than '/'. | |
37 | +# Keys with --flatten option would be | |
38 | +# disk_usage.root, disk_usage.boot, and disk_usage.media_sda1 | |
39 | +# | |
40 | +# Mountpoints can be specifically included or ignored using -i or -I options: | |
41 | +# e.g. disk-usage-metric.rb -i ^/boot,^/media | |
42 | +# | |
43 | +# LICENSE: | |
44 | +# Copyright 2012 Sonian, Inc <chefs@sonian.net> | |
45 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
46 | +# for details. | |
47 | +# | |
48 | + | |
49 | +require 'sensu-plugin/metric/cli' | |
50 | +require 'socket' | |
51 | + | |
52 | +# | |
53 | +# Disk Usage Metrics | |
54 | +# | |
55 | +class DiskUsageMetrics < Sensu::Plugin::Metric::CLI::Graphite | |
56 | + option :scheme, | |
57 | + description: 'Metric naming scheme, text to prepend to .$parent.$child', | |
58 | + long: '--scheme SCHEME', | |
59 | + default: "#{Socket.gethostname}.disk_usage" | |
60 | + | |
61 | + option :ignore_mnt, | |
62 | + description: 'Ignore mounts matching pattern(s)', | |
63 | + short: '-i MNT[,MNT]', | |
64 | + long: '--ignore-mount', | |
65 | + proc: proc { |a| a.split(',') } | |
66 | + | |
67 | + option :include_mnt, | |
68 | + description: 'Include only mounts matching pattern(s)', | |
69 | + short: '-I MNT[,MNT]', | |
70 | + long: '--include-mount', | |
71 | + proc: proc { |a| a.split(',') } | |
72 | + | |
73 | + option :flatten, | |
74 | + description: 'Output mounts with underscore rather than dot', | |
75 | + short: '-f', | |
76 | + long: '--flatten', | |
77 | + boolean: true, | |
78 | + default: false | |
79 | + | |
80 | + option :local, | |
81 | + description: 'Only check local filesystems (df -l option)', | |
82 | + short: '-l', | |
83 | + long: '--local', | |
84 | + boolean: true, | |
85 | + default: false | |
86 | + | |
87 | + option :block_size, | |
88 | + description: 'Set block size for sizes printed', | |
89 | + short: '-B BLOCK_SIZE', | |
90 | + long: '--block-size BLOCK_SIZE', | |
91 | + default: 'M' | |
92 | + | |
93 | + # Main function | |
94 | + # | |
95 | + def run | |
96 | + delim = config[:flatten] == true ? '_' : '.' | |
97 | + # Get disk usage from df with used and avail in megabytes | |
98 | + # #YELLOW | |
99 | + `df -PB#{config[:block_size]} #{config[:local] ? '-l' : ''}`.split("\n").drop(1).each do |line| | |
100 | + _, _, used, avail, used_p, mnt = line.split | |
101 | + | |
102 | + unless %r{/sys[/|$]|/dev[/|$]|/run[/|$]} =~ mnt | |
103 | + next if config[:ignore_mnt] && config[:ignore_mnt].find { |x| mnt.match(x) } | |
104 | + next if config[:include_mnt] && !config[:include_mnt].find { |x| mnt.match(x) } | |
105 | + mnt = if config[:flatten] | |
106 | + mnt.eql?('/') ? 'root' : mnt.gsub(/^\//, '') | |
107 | + else | |
108 | + # If mnt is only / replace that with root if its /tmp/foo | |
109 | + # replace first occurance of / with root. | |
110 | + mnt.length == 1 ? 'root' : mnt.gsub(/^\//, 'root.') | |
111 | + end | |
112 | + # Fix subsequent slashes | |
113 | + mnt = mnt.gsub '/', delim | |
114 | + output [config[:scheme], mnt, 'used'].join('.'), used.gsub(config[:block_size], '') | |
115 | + output [config[:scheme], mnt, 'avail'].join('.'), avail.gsub(config[:block_size], '') | |
116 | + output [config[:scheme], mnt, 'used_percentage'].join('.'), used_p.delete('%') | |
117 | + end | |
118 | + end | |
119 | + ok | |
120 | + end | |
121 | +end | ... | ... |
metrics-iostat-extended.rb
0 → 100755
1 | +++ a/metrics-iostat-extended.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# encoding: UTF-8 | |
3 | +# | |
4 | +# metrics-iostat-extended | |
5 | +# | |
6 | +# DESCRIPTION: | |
7 | +# This plugin collects iostat data for a specified disk or all disks. | |
8 | +# Output is in Graphite format. See `man iostat` for detailed | |
9 | +# explaination of each field. | |
10 | +# | |
11 | +# OUTPUT: | |
12 | +# metric data | |
13 | +# | |
14 | +# PLATFORMS: | |
15 | +# Linux | |
16 | +# | |
17 | +# DEPENDENCIES: | |
18 | +# gem: sensu-plugin | |
19 | +# gem: socket | |
20 | +# | |
21 | +# USAGE: | |
22 | +# Collect metrics for all disks | |
23 | +# metrics-iostat-extended.rb | |
24 | +# | |
25 | +# Collect metrics for /dev/sda for 3 seconds | |
26 | +# metrics-iostat-extended.rb -d /dev/sda -i 3 | |
27 | +# | |
28 | +# NOTES: | |
29 | +# The iostat command must be installed. On Debian/Redhat systems | |
30 | +# iostat is part of the sysstat package. | |
31 | +# | |
32 | +# LICENSE: | |
33 | +# Peter Fern <ruby@0xc0dedbad.com> | |
34 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
35 | +# for details. | |
36 | +# | |
37 | + | |
38 | +require 'sensu-plugin/metric/cli' | |
39 | +require 'open3' | |
40 | +require 'socket' | |
41 | + | |
42 | +class IOStatExtended < Sensu::Plugin::Metric::CLI::Graphite | |
43 | + option :scheme, | |
44 | + description: 'Metric naming scheme, text to prepend to .$parent.$child', | |
45 | + long: '--scheme SCHEME', | |
46 | + default: "#{Socket.gethostname}.iostat" | |
47 | + | |
48 | + option :disk, | |
49 | + description: 'Disk to gather stats for', | |
50 | + short: '-d DISK', | |
51 | + long: '--disk DISK', | |
52 | + required: false | |
53 | + | |
54 | + option :excludedisk, | |
55 | + description: 'List of disks to exclude', | |
56 | + short: '-x DISK[,DISK]', | |
57 | + long: '--exclude-disk', | |
58 | + proc: proc { |a| a.split(',') } | |
59 | + | |
60 | + option :interval, | |
61 | + description: 'Period over which statistics are calculated (in seconds)', | |
62 | + short: '-i SECONDS', | |
63 | + long: '--interval SECONDS', | |
64 | + default: 1 | |
65 | + | |
66 | + option :mappernames, | |
67 | + description: 'Display the registered device mapper names for any device mapper devices. Useful for viewing LVM2 statistics', | |
68 | + short: '-N', | |
69 | + long: '--show-dm-names', | |
70 | + boolean: true | |
71 | + | |
72 | + def parse_results(raw) | |
73 | + stats = {} | |
74 | + key = nil | |
75 | + headers = nil | |
76 | + stage = :initial | |
77 | + raw.each_line do |line| | |
78 | + line.chomp! | |
79 | + next if line.empty? | |
80 | + | |
81 | + case line | |
82 | + when /^(avg-cpu):/ | |
83 | + stage = :cpu | |
84 | + key = Regexp.last_match[1] | |
85 | + headers = line.gsub(/%/, 'pct_').split(/\s+/) | |
86 | + headers.shift | |
87 | + next | |
88 | + when /^(Device):/ | |
89 | + stage = :device | |
90 | + headers = line.gsub(/%/, 'pct_').split(/\s+/).map { |h| h.gsub(/\//, '_per_') } | |
91 | + headers.shift | |
92 | + next | |
93 | + end | |
94 | + next if stage == :initial | |
95 | + | |
96 | + fields = line.split(/\s+/) | |
97 | + | |
98 | + key = fields.shift if stage == :device | |
99 | + fields.shift if stage == :cpu | |
100 | + stats[key] = Hash[headers.zip(fields.map(&:to_f))] | |
101 | + end | |
102 | + stats | |
103 | + end | |
104 | + | |
105 | + def run | |
106 | + cmd = 'iostat' | |
107 | + args = ['-x', config[:interval].to_s, '2'] | |
108 | + args.push('-N') if config[:mappernames] | |
109 | + args.push(File.basename(config[:disk])) if config[:disk] | |
110 | + | |
111 | + exclude_disk = if config[:excludedisk] | |
112 | + config[:excludedisk].map { |d| File.basename(d) } | |
113 | + else | |
114 | + [] | |
115 | + end | |
116 | + | |
117 | + stdin, stdout, stderr = Open3.popen3(cmd, *args, unsetenv_others: true) | |
118 | + stdin.close | |
119 | + stderr.close | |
120 | + stats = parse_results(stdout.gets(nil)) | |
121 | + stdout.close | |
122 | + | |
123 | + timestamp = Time.now.to_i | |
124 | + | |
125 | + stats.each do |disk, metrics| | |
126 | + next if exclude_disk.include? disk | |
127 | + metrics.each do |metric, value| | |
128 | + output [config[:scheme], disk, metric].join('.'), value, timestamp | |
129 | + end | |
130 | + end | |
131 | + ok | |
132 | + end | |
133 | +end | ... | ... |
metrics-load.rb
0 → 100755
1 | +++ a/metrics-load.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# encoding: UTF-8 | |
3 | +# <script name> | |
4 | +# | |
5 | +# DESCRIPTION: | |
6 | +# This plugin uses uptime to collect load metrics | |
7 | +# Basically copied from sensu-community-plugins/plugins/system/vmstat-metrics.rb | |
8 | +# | |
9 | +# Load per processor | |
10 | +# ------------------ | |
11 | +# | |
12 | +# Optionally, with `--per-core`, this plugin will calculate load per | |
13 | +# processor from the raw load average by dividing load average by the number | |
14 | +# of processors. | |
15 | +# | |
16 | +# The number of CPUs is determined by reading `/proc/cpuinfo`. This makes the | |
17 | +# feature Linux specific. Other OSs can be supported by adding OS # detection | |
18 | +# and a method to determine the number of CPUs. | |
19 | +# | |
20 | +# OUTPUT: | |
21 | +# metric data | |
22 | +# | |
23 | +# PLATFORMS: | |
24 | +# Linux, BSD, Solaris, etc | |
25 | +# | |
26 | +# DEPENDENCIES: | |
27 | +# gem: sensu-plugin | |
28 | +# gem: socket | |
29 | +# | |
30 | +# USAGE: | |
31 | +# | |
32 | +# NOTES: | |
33 | +# | |
34 | +# LICENSE: | |
35 | +# Copyright 2012 Sonian, Inc <chefs@sonian.net> | |
36 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
37 | +# for details. | |
38 | +# | |
39 | + | |
40 | +require 'sensu-plugin/metric/cli' | |
41 | +require_relative '../lib/sensu-plugins-load-checks/load-average.rb' | |
42 | +require 'socket' | |
43 | + | |
44 | +class LoadStat < Sensu::Plugin::Metric::CLI::Graphite | |
45 | + option :scheme, | |
46 | + description: 'Metric naming scheme, text to prepend to .$parent.$child', | |
47 | + long: '--scheme SCHEME', | |
48 | + default: Socket.gethostname.to_s | |
49 | + | |
50 | + def run | |
51 | + data = LoadAverage.new | |
52 | + unknown 'Could not read load average from /proc or `uptime`' if data.failed? | |
53 | + | |
54 | + timestamp = Time.now.to_i | |
55 | + metrics = { | |
56 | + load_avg: { | |
57 | + one: data.load_avg[0].round(2), | |
58 | + five: data.load_avg[1].round(2), | |
59 | + fifteen: data.load_avg[2].round(2) | |
60 | + } | |
61 | + } | |
62 | + | |
63 | + metrics.each do |parent, children| | |
64 | + children.each do |child, value| | |
65 | + output [config[:scheme], parent, child].join('.'), value, timestamp | |
66 | + end | |
67 | + end | |
68 | + ok | |
69 | + end | |
70 | +end | ... | ... |
metrics-memory-percent.rb
0 → 100755
1 | +++ a/metrics-memory-percent.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# encoding: UTF-8 | |
3 | +# | |
4 | +# metrics-memory-percent | |
5 | +# | |
6 | +# DESCRIPTION: | |
7 | +# | |
8 | +# OUTPUT: | |
9 | +# metric data | |
10 | +# | |
11 | +# PLATFORMS: | |
12 | +# Linux | |
13 | +# | |
14 | +# DEPENDENCIES: | |
15 | +# gem: sensu-plugin | |
16 | +# | |
17 | +# USAGE: | |
18 | +# ./metrics-memory-percent.rb | |
19 | +# | |
20 | +# LICENSE: | |
21 | +# Copyright 2012 Sonian, Inc <chefs@sonian.net> | |
22 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
23 | +# for details. | |
24 | +# | |
25 | + | |
26 | +require 'sensu-plugin/metric/cli' | |
27 | +require 'socket' | |
28 | + | |
29 | +class MemoryGraphite < Sensu::Plugin::Metric::CLI::Graphite | |
30 | + option :scheme, | |
31 | + description: 'Metric naming scheme, text to prepend to metric', | |
32 | + short: '-s SCHEME', | |
33 | + long: '--scheme SCHEME', | |
34 | + default: "#{Socket.gethostname}.memory_percent" | |
35 | + | |
36 | + def run | |
37 | + # Based on memory-metrics.rb | |
38 | + | |
39 | + # Metrics borrowed from hoardd: https://github.com/coredump/hoardd | |
40 | + | |
41 | + mem = metrics_hash | |
42 | + | |
43 | + mem.each do |k, v| | |
44 | + output "#{config[:scheme]}.#{k}", v | |
45 | + end | |
46 | + | |
47 | + ok | |
48 | + end | |
49 | + | |
50 | + def metrics_hash | |
51 | + mem = {} | |
52 | + memp = {} | |
53 | + | |
54 | + meminfo_output.each_line do |line| | |
55 | + mem['total'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^MemTotal/ | |
56 | + mem['free'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^MemFree/ | |
57 | + mem['buffers'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^Buffers/ | |
58 | + mem['cached'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^Cached/ | |
59 | + mem['swapTotal'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^SwapTotal/ | |
60 | + mem['swapFree'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^SwapFree/ | |
61 | + mem['dirty'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^Dirty/ | |
62 | + end | |
63 | + | |
64 | + mem['swapUsed'] = mem['swapTotal'] - mem['swapFree'] | |
65 | + mem['used'] = mem['total'] - mem['free'] | |
66 | + mem['usedWOBuffersCaches'] = mem['used'] - (mem['buffers'] + mem['cached']) | |
67 | + mem['freeWOBuffersCaches'] = mem['free'] + (mem['buffers'] + mem['cached']) | |
68 | + | |
69 | + # to prevent division by zero | |
70 | + swptot = if mem['swapTotal'].zero? | |
71 | + 1 | |
72 | + else | |
73 | + mem['swapTotal'] | |
74 | + end | |
75 | + | |
76 | + mem.each do |k, _v| | |
77 | + # with percentages, used and free are exactly complementary | |
78 | + # no need to have both | |
79 | + # the one to drop here is "used" because "free" will | |
80 | + # stack up neatly to 100% with all the others (except swapUsed) | |
81 | + # #YELLOW | |
82 | + memp[k] = 100.0 * mem[k] / mem['total'] if k != 'total' && k !~ /swap/ && k != 'used' | |
83 | + | |
84 | + # with percentages, swapUsed and swapFree are exactly complementary | |
85 | + # no need to have both | |
86 | + memp[k] = 100.0 * mem[k] / swptot if k != 'swapTotal' && k =~ /swap/ && k != 'swapFree' | |
87 | + end | |
88 | + | |
89 | + memp | |
90 | + end | |
91 | + | |
92 | + def meminfo_output | |
93 | + File.open('/proc/meminfo', 'r') | |
94 | + end | |
95 | +end | ... | ... |
metrics-memory.rb
0 → 100755
1 | +++ a/metrics-memory.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# encoding: UTF-8 | |
3 | +# | |
4 | +# metrics-memory | |
5 | +# | |
6 | +# DESCRIPTION: | |
7 | +# | |
8 | +# OUTPUT: | |
9 | +# metric data | |
10 | +# | |
11 | +# PLATFORMS: | |
12 | +# Linux | |
13 | +# | |
14 | +# DEPENDENCIES: | |
15 | +# gem: sensu-plugin | |
16 | +# | |
17 | +# USAGE: | |
18 | +# ./metrics-memory.rb | |
19 | +# | |
20 | +# LICENSE: | |
21 | +# Copyright 2012 Sonian, Inc <chefs@sonian.net> | |
22 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
23 | +# for details. | |
24 | +# | |
25 | + | |
26 | +require 'sensu-plugin/metric/cli' | |
27 | +require 'socket' | |
28 | + | |
29 | +class MemoryGraphite < Sensu::Plugin::Metric::CLI::Graphite | |
30 | + option :scheme, | |
31 | + description: 'Metric naming scheme, text to prepend to metric', | |
32 | + short: '-s SCHEME', | |
33 | + long: '--scheme SCHEME', | |
34 | + default: "#{Socket.gethostname}.memory" | |
35 | + | |
36 | + def run | |
37 | + # Metrics borrowed from hoardd: https://github.com/coredump/hoardd | |
38 | + | |
39 | + mem = metrics_hash | |
40 | + | |
41 | + mem.each do |k, v| | |
42 | + output "#{config[:scheme]}.#{k}", v | |
43 | + end | |
44 | + | |
45 | + ok | |
46 | + end | |
47 | + | |
48 | + def metrics_hash | |
49 | + mem = {} | |
50 | + meminfo_output.each_line do |line| | |
51 | + mem['total'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^MemTotal/ | |
52 | + mem['free'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^MemFree/ | |
53 | + mem['buffers'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^Buffers/ | |
54 | + mem['cached'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^Cached/ | |
55 | + mem['swapTotal'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^SwapTotal/ | |
56 | + mem['swapFree'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^SwapFree/ | |
57 | + mem['dirty'] = line.split(/\s+/)[1].to_i * 1024 if line =~ /^Dirty/ | |
58 | + end | |
59 | + | |
60 | + mem['swapUsed'] = mem['swapTotal'] - mem['swapFree'] | |
61 | + mem['used'] = mem['total'] - mem['free'] | |
62 | + mem['usedWOBuffersCaches'] = mem['used'] - (mem['buffers'] + mem['cached']) | |
63 | + mem['freeWOBuffersCaches'] = mem['free'] + (mem['buffers'] + mem['cached']) | |
64 | + mem['swapUsedPercentage'] = 100 * mem['swapUsed'] / mem['swapTotal'] if mem['swapTotal'] > 0 | |
65 | + | |
66 | + mem | |
67 | + end | |
68 | + | |
69 | + def meminfo_output | |
70 | + File.open('/proc/meminfo', 'r') | |
71 | + end | |
72 | +end | ... | ... |
metrics-netif.rb
0 → 100755
1 | +++ a/metrics-netif.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# | |
3 | +# netif-metrics | |
4 | +# | |
5 | +# DESCRIPTION: | |
6 | +# Network interface throughput | |
7 | +# | |
8 | +# OUTPUT: | |
9 | +# metric data | |
10 | +# | |
11 | +# PLATFORMS: | |
12 | +# Linux | |
13 | +# | |
14 | +# DEPENDENCIES: | |
15 | +# gem: sensu-plugin | |
16 | +# | |
17 | +# USAGE: | |
18 | +# #YELLOW | |
19 | +# | |
20 | +# NOTES: | |
21 | +# | |
22 | +# LICENSE: | |
23 | +# Copyright 2014 Sonian, Inc. and contributors. <support@sensuapp.org> | |
24 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
25 | +# for details. | |
26 | +# | |
27 | + | |
28 | +require 'sensu-plugin/metric/cli' | |
29 | +require 'socket' | |
30 | + | |
31 | +# | |
32 | +# Netif Metrics | |
33 | +# | |
34 | +class NetIFMetrics < Sensu::Plugin::Metric::CLI::Graphite | |
35 | + option :scheme, | |
36 | + description: 'Metric naming scheme, text to prepend to .$parent.$child', | |
37 | + long: '--scheme SCHEME', | |
38 | + default: Socket.gethostname.to_s | |
39 | + | |
40 | + option :interval, | |
41 | + description: 'Interval to collect metrics over', | |
42 | + long: '--interval INTERVAL', | |
43 | + default: 1 | |
44 | + | |
45 | + option :average_key, | |
46 | + description: 'This key is used to `grep` for a key that corresponds to average. useful for different locales', | |
47 | + long: '--average-key', | |
48 | + default: 'Average' | |
49 | + | |
50 | + def run | |
51 | + sar = `/usr/bin/sar -n DEV #{config[:interval]} 1 | grep #{config[:average_key]} | grep -v IFACE` | |
52 | + if sar.nil? || sar.empty? | |
53 | + unknown 'sar is not installed or in $PATH' | |
54 | + end | |
55 | + sar.each_line do |line| | |
56 | + stats = line.split(/\s+/) | |
57 | + unless stats.empty? | |
58 | + stats.shift | |
59 | + nic = stats.shift | |
60 | + output "#{config[:scheme]}.#{nic}.rx_kB_per_sec", stats[2].to_f if stats[3] | |
61 | + output "#{config[:scheme]}.#{nic}.tx_kB_per_sec", stats[3].to_f if stats[3] | |
62 | + end | |
63 | + end | |
64 | + | |
65 | + ok | |
66 | + end | |
67 | +end | ... | ... |
metrics-netstat-tcp.rb
0 → 100755
1 | +++ a/metrics-netstat-tcp.rb | |
1 | +#! /usr/bin/env ruby | |
2 | +# | |
3 | +# metrics-netstat-tcp | |
4 | +# | |
5 | +# DESCRIPTION: | |
6 | +# Fetch metrics on TCP socket states from netstat. This is particularly useful | |
7 | +# on high-traffic web or proxy servers with large numbers of short-lived TCP | |
8 | +# connections coming and going. | |
9 | +# | |
10 | +# OUTPUT: | |
11 | +# metric data | |
12 | +# | |
13 | +# PLATFORMS: | |
14 | +# Linux | |
15 | +# | |
16 | +# DEPENDENCIES: | |
17 | +# gem: sensu-plugin | |
18 | +# | |
19 | +# USAGE: | |
20 | +# $ ./metrics-netstat-tcp.rb --scheme servers.hostname | |
21 | +# servers.hostname.UNKNOWN 0 1350496466 | |
22 | +# servers.hostname.ESTABLISHED 235 1350496466 | |
23 | +# servers.hostname.SYN_SENT 0 1350496466 | |
24 | +# servers.hostname.SYN_RECV 1 1350496466 | |
25 | +# servers.hostname.FIN_WAIT1 0 1350496466 | |
26 | +# servers.hostname.FIN_WAIT2 53 1350496466 | |
27 | +# servers.hostname.TIME_WAIT 10640 1350496466 | |
28 | +# servers.hostname.CLOSE 0 1350496466 | |
29 | +# servers.hostname.CLOSE_WAIT 7 1350496466 | |
30 | +# servers.hostname.LAST_ACK 1 1350496466 | |
31 | +# servers.hostname.LISTEN 16 1350496466 | |
32 | +# servers.hostname.CLOSING 0 1350496466 | |
33 | +# | |
34 | +# NOTES: | |
35 | +# - Code for parsing Linux /proc/net/tcp from Anthony Goddard's ruby-netstat: | |
36 | +# https://github.com/agoddard/ruby-netstat | |
37 | +# | |
38 | +# LICENSE: | |
39 | +# Copyright 2012 Joe Miller <https://github.com/joemiller> | |
40 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
41 | +# for details. | |
42 | +# | |
43 | + | |
44 | +require 'sensu-plugin/metric/cli' | |
45 | +require 'socket' | |
46 | + | |
47 | +TCP_STATES = { | |
48 | + '00' => 'UNKNOWN', # Bad state ... Impossible to achieve ... | |
49 | + 'FF' => 'UNKNOWN', # Bad state ... Impossible to achieve ... | |
50 | + '01' => 'ESTABLISHED', | |
51 | + '02' => 'SYN_SENT', | |
52 | + '03' => 'SYN_RECV', | |
53 | + '04' => 'FIN_WAIT1', | |
54 | + '05' => 'FIN_WAIT2', | |
55 | + '06' => 'TIME_WAIT', | |
56 | + '07' => 'CLOSE', | |
57 | + '08' => 'CLOSE_WAIT', | |
58 | + '09' => 'LAST_ACK', | |
59 | + '0A' => 'LISTEN', | |
60 | + '0B' => 'CLOSING' | |
61 | +}.freeze | |
62 | + | |
63 | +# | |
64 | +# Netstat TCP Metrics | |
65 | +# | |
66 | +class NetstatTCPMetrics < Sensu::Plugin::Metric::CLI::Graphite | |
67 | + option :scheme, | |
68 | + description: 'Metric naming scheme, text to prepend to metric', | |
69 | + short: '-s SCHEME', | |
70 | + long: '--scheme SCHEME', | |
71 | + default: "#{Socket.gethostname}.tcp" | |
72 | + | |
73 | + option :port, | |
74 | + description: 'Port you wish to get metrics for', | |
75 | + short: '-p PORT', | |
76 | + long: '--port PORT', | |
77 | + proc: proc(&:to_i) | |
78 | + | |
79 | + option :disabletcp6, | |
80 | + description: 'Disable tcp6 check', | |
81 | + short: '-d', | |
82 | + long: '--disabletcp6', | |
83 | + boolean: true | |
84 | + | |
85 | + def netstat(protocol, pattern, state_counts) | |
86 | + File.open('/proc/net/' + protocol).each do |line| | |
87 | + line.strip! | |
88 | + if m = line.match(pattern) # rubocop:disable AssignmentInCondition | |
89 | + connection_state = m[5] | |
90 | + connection_port = m[2].to_i(16) | |
91 | + connection_state = TCP_STATES[connection_state] | |
92 | + if config[:port] && config[:port] == connection_port | |
93 | + state_counts[connection_state] += 1 | |
94 | + elsif !config[:port] | |
95 | + state_counts[connection_state] += 1 | |
96 | + end | |
97 | + end | |
98 | + end | |
99 | + state_counts | |
100 | + end | |
101 | + | |
102 | + def run | |
103 | + timestamp = Time.now.to_i | |
104 | + state_counts = Hash.new(0) | |
105 | + TCP_STATES.each_pair { |_hex, name| state_counts[name] = 0 } | |
106 | + | |
107 | + tcp4_pattern = /^\s*\d+:\s+(.{8}):(.{4})\s+(.{8}):(.{4})\s+(.{2})/ | |
108 | + state_counts = netstat('tcp', tcp4_pattern, state_counts) | |
109 | + | |
110 | + unless config[:disabletcp6] | |
111 | + tcp6_pattern = /^\s*\d+:\s+(.{32}):(.{4})\s+(.{32}):(.{4})\s+(.{2})/ | |
112 | + state_counts = netstat('tcp6', tcp6_pattern, state_counts) | |
113 | + end | |
114 | + | |
115 | + state_counts.each do |state, count| | |
116 | + graphite_name = config[:port] ? "#{config[:scheme]}.#{config[:port]}.#{state}" : | |
117 | + "#{config[:scheme]}.#{state}" | |
118 | + output graphite_name.to_s, count, timestamp | |
119 | + end | |
120 | + ok | |
121 | + end | |
122 | +end | ... | ... |
metrics-numastat.rb
0 → 100755
1 | +++ a/metrics-numastat.rb | |
1 | +#!/usr/bin/env ruby | |
2 | +# | |
3 | +# metrics-numastat | |
4 | +# | |
5 | +# DESCRIPTION: | |
6 | +# Simple wrapper around `numastat` for getting per-NUMA-node memory stats. | |
7 | +# | |
8 | +# OUTPUT: | |
9 | +# metric data | |
10 | +# | |
11 | +# PLATFORMS: | |
12 | +# Linux | |
13 | +# | |
14 | +# DEPENDENCIES: | |
15 | +# gem: sensu-plugin | |
16 | +# | |
17 | +# USAGE: | |
18 | +# | |
19 | +# NOTES: | |
20 | +# | |
21 | +# LICENSE: | |
22 | +# Copyright 2016 Mitsutoshi Aoe | |
23 | +# Released under the same terms as Sensu (the MIT license); see LICENSE | |
24 | +# for details. | |
25 | +# | |
26 | + | |
27 | +require 'socket' | |
28 | +require 'sensu-plugin/metric/cli' | |
29 | + | |
30 | +class NumastatMetrics < Sensu::Plugin::Metric::CLI::Graphite | |
31 | + option :scheme, | |
32 | + description: 'Metric naming scheme, text to prepend to metric', | |
33 | + short: '-s SCHEME', | |
34 | + long: '--scheme SCHEME', | |
35 | + default: "#{Socket.gethostname}.numastat" | |
36 | + | |
37 | + def run | |
38 | + begin | |
39 | + output = `/usr/bin/numastat` | |
40 | + rescue Errno::ENOENT => err | |
41 | + unknown err | |
42 | + end | |
43 | + | |
44 | + nodes = [] | |
45 | + output.each_line do |line| | |
46 | + nodes = line.split(' ') if nodes.empty? | |
47 | + next unless /^([^\s]+)\s+(.+)$/ =~ line | |
48 | + key = Regexp.last_match[1] | |
49 | + vals = Regexp.last_match[2] | |
50 | + next if key.nil? || vals.nil? | |
51 | + nodes.zip(vals.split(' ')).each do |node, val| | |
52 | + output "#{config[:scheme]}.#{node}.#{key}", val | |
53 | + end | |
54 | + end | |
55 | + | |
56 | + ok | |
57 | + end | |
58 | +end | ... | ... |