forked from ripienaar/graphite-graph-dsl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheck_graph.rb
123 lines (93 loc) · 3.21 KB
/
check_graph.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env ruby
require 'rubygems'
require 'json'
require 'graphite_graph'
require 'net/http'
require 'uri'
require 'optparse'
require 'pp'
crits = []
warns = []
check_data = {}
url = "http://localhost/render/?"
graph = nil
check_number = 3
opt = OptionParser.new
opt.on("--graphite [URL]", "Base URL for the Graphite installation") do |v|
url = v
end
opt.on("--graph [GRAPH]", "Graph defintition") do |v|
graph = v
end
opt.on("--warning [WARN]", "Warning threshold, can be specified multiple times") do |v|
warns << Float(v)
end
opt.on("--critical [CRITICAL]", "Critical threshold, can be specified multiple times") do |v|
crits << Float(v)
end
opt.on("--check [NUM]", Integer, "Number of past data items to check") do |v|
check_number = v
end
opt.parse!
def status_exit(msg, code)
puts msg
exit code
end
unless (graph && File.exist?(graph))
status_exit "UNKNOWN - Can't find graph defintion #{graph}", 3
end
def check_data(data, min, max)
fails = []
data.keys.each do |target|
if min == max # we got just one value to compare against
if min < 0
# if the threshold is < 0 we check for values below the threshold but have no way to say that
# critical / warning is above -0.5 for example unless you specify a 2 value band
if (data[target].min <= min)
fails << {:target => target, :item => data[target].min, :operator => "<=", :expected => min}
end
else
if (data[target].max >= max)
fails << {:target => target, :item => data[target].max, :operator => ">=", :expected => max}
end
end
else # we have a range of values to compare against and the values must be between
if (data[target].min <= min)
fails << {:target => target, :item => data[target].min, :operator => "<=", :expected => min}
end
if (data[target].max >= max)
fails << {:target => target, :item => data[target].max, :operator => ">=", :expected => max}
end
end
end
fails.empty? ? false : fails
end
def print_and_exit(results, code)
exitcodes = ["OK", "WARNING", "CRITICAL", "UNKNOWN"]
msg = results.map do |r|
"%s %s %s %s" % [r[:target], r[:item], r[:operator], r[:expected]]
end.join(", ")
status_exit "%s - %s" % [exitcodes[code], msg], code
end
graphite = GraphiteGraph.new(graph)
uri = URI.parse("%s?%s" % [ url, graphite.url(:json) ])
json = Net::HTTP.get_response(uri)
status_exit("UNKNOWN - Could not request graph data for HTTP code #{json.code}", 3) unless json.code == "200"
data = JSON.load(json.body)
data.each do |d|
unless d["target"] =~ /(warn|crit)_[01]$/
check_data[ d["target"] ] = d["datapoints"].last(check_number).map{|i| i.first}
end
end
crits = graphite.critical_threshold if crits.empty? and graphite.critical_threshold
warns = graphite.warning_threshold if warns.empty? and graphite.warning_threshold
if crits.empty? || warns.empty? || check_data.empty?
status_exit "UNKNOWN: Graph does not have Data, Warning and Critical information", 3
end
if results = check_data(check_data, crits.min, crits.max)
print_and_exit results, 2
elsif results = check_data(check_data, warns.min, warns.max)
print_and_exit results, 1
else
status_exit "OK - All data within expected ranges", 0
end