munin_manager 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +30 -0
- data/README.markdown +0 -0
- data/Rakefile +29 -0
- data/VERSION +1 -0
- data/bin/munin_manager +95 -0
- data/bin/runner +18 -0
- data/lib/munin_manager.rb +9 -0
- data/lib/munin_manager/acts_as_munin_plugin.rb +82 -0
- data/lib/munin_manager/log_reader.rb +85 -0
- data/lib/munin_manager/plugins.rb +29 -0
- data/lib/munin_manager/plugins/fbproxy_latency.rb +78 -0
- data/lib/munin_manager/plugins/haproxy_app_response_time.rb +104 -0
- data/lib/munin_manager/plugins/haproxy_response_time.rb +87 -0
- data/lib/munin_manager/plugins/haproxy_rps.rb +95 -0
- data/lib/munin_manager/plugins/network_latency.rb +53 -0
- data/lib/munin_manager/plugins/notification_classification.rb +27 -0
- data/lib/munin_manager/plugins/packet_loss.rb +53 -0
- data/lib/munin_manager/plugins/rails_rendering.rb +82 -0
- data/lib/munin_manager/plugins/rails_response_time.rb +103 -0
- data/lib/munin_manager/plugins/scribe_net.rb +81 -0
- data/lib/munin_manager/plugins/starling_age.rb +77 -0
- data/lib/munin_manager/plugins/starling_net.rb +81 -0
- data/lib/munin_manager/plugins/starling_ops.rb +85 -0
- data/lib/munin_manager/plugins/starling_queue.rb +84 -0
- data/lib/munin_manager/starling/starling_stats.rb +66 -0
- data/test/haproxy_response_time_test.rb +37 -0
- data/test/log_reader_test.rb +31 -0
- data/test/rails_response_time_test.rb +51 -0
- data/test/test_helper.rb +32 -0
- metadata +86 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
module MuninManager
|
2
|
+
class Plugins::RailsResponseTime < LogReader
|
3
|
+
include ActsAsMuninPlugin
|
4
|
+
attr_accessor :search_pattern
|
5
|
+
|
6
|
+
def initialize(log_file, options = {})
|
7
|
+
super(log_file)
|
8
|
+
@search_pattern = options[:search_pattern] || /.*/
|
9
|
+
@search_pattern = Regexp.new(@search_pattern) if @search_pattern.is_a?(String)
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
@data ||= Hash.new {|h, k| h[k] = Array.new}
|
14
|
+
end
|
15
|
+
|
16
|
+
def scan(log_file)
|
17
|
+
current_action = nil
|
18
|
+
loop do
|
19
|
+
line = log_file.readline
|
20
|
+
|
21
|
+
if line.starts_with?("Processing ")
|
22
|
+
cols = line.split(/\s+/)
|
23
|
+
current_action = cols[1] if self.search_pattern.match(cols[1])
|
24
|
+
|
25
|
+
elsif line.starts_with?("Completed in ") && !current_action.nil?
|
26
|
+
cols = line.split(/\s+/)
|
27
|
+
data[current_action] << cols[2].to_f
|
28
|
+
current_action = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def process!
|
35
|
+
data.each_pair do |action_name, response_times|
|
36
|
+
data[action_name] = response_times.inject(0) {|sum, i| sum + i} / data[action_name].length rescue 0
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def config
|
41
|
+
configs = {
|
42
|
+
"graph_title" => "Rails Response Times (by Controller->Action)",
|
43
|
+
"graph_vlabel" => "time (secs)",
|
44
|
+
"graph_category" => "Performance",
|
45
|
+
"graph_args" => "--upper-limit 1.0 --lower-limit 0.100 --rigid"
|
46
|
+
}
|
47
|
+
self.collect!(:save_state => false)
|
48
|
+
self.data.each do |action_name, respose_time|
|
49
|
+
configs["#{format_for_munin(action_name)}.label"] = action_name.sub("#", "->")
|
50
|
+
configs["#{format_for_munin(action_name)}.draw"] = "LINE2"
|
51
|
+
end
|
52
|
+
|
53
|
+
configs["graph_order"] = self.data.to_a.
|
54
|
+
sort {|lhs, rhs| rhs[1] <=> lhs[1]}.
|
55
|
+
collect {|tuple| format_for_munin(tuple[0])}
|
56
|
+
|
57
|
+
configs.map {|key_value_pair| key_value_pair.join(" ")}.join("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
def values
|
61
|
+
data.map {|k, v| "#{format_for_munin(k)}.value #{"%.10f" % v}"}.join("\n")
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.run
|
65
|
+
log_file = ENV['log_file'] || "/var/log/rails.log"
|
66
|
+
allowed_commands = ['config']
|
67
|
+
|
68
|
+
rails = new(log_file, :search_pattern => ENV['search_pattern'])
|
69
|
+
|
70
|
+
if cmd = ARGV[0] and allowed_commands.include? cmd then
|
71
|
+
puts rails.send(cmd.to_sym)
|
72
|
+
else
|
73
|
+
rails.collect!
|
74
|
+
puts rails.values
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.help_text(options = {})
|
79
|
+
%Q{
|
80
|
+
#{plugin_name.capitalize} Munin Plugin
|
81
|
+
===========================
|
82
|
+
|
83
|
+
Please remember to add something like the lines below to /etc/munin/plugin-conf.d/munin-node
|
84
|
+
if the rails log file is not at /var/log/rails.log
|
85
|
+
|
86
|
+
[#{options[:symlink] || plugin_name}]
|
87
|
+
env.log_file /var/log/custom/rails.log
|
88
|
+
env.search_pattern UsersController.*
|
89
|
+
|
90
|
+
Also, make sure that the '/var/lib/munin/plugin-state' is writable by munin.
|
91
|
+
|
92
|
+
$ sudo chmod 777 /var/lib/munin/plugin-state
|
93
|
+
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def format_for_munin(str)
|
100
|
+
str.to_s.gsub(/[^A-Za-z0-9_]/, "_")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# Munin plugin for starling.
|
3
|
+
require 'rubygems'
|
4
|
+
require 'ruby_scribe_client'
|
5
|
+
|
6
|
+
#Monkey patched so the namespaced queues are included in stats
|
7
|
+
module MuninManager
|
8
|
+
class Plugins::ScribeNet
|
9
|
+
include ActsAsMuninPlugin
|
10
|
+
|
11
|
+
def initialize(host, port)
|
12
|
+
@scribe = FB303::Client.new(host, port)
|
13
|
+
@category = 'scribe'
|
14
|
+
end
|
15
|
+
|
16
|
+
def config
|
17
|
+
graph_config = <<-END.gsub(/ +/, '')
|
18
|
+
graph_title Scribe Traffic
|
19
|
+
graph_args --base 1000
|
20
|
+
graph_vlabel bits per second
|
21
|
+
graph_category #{@category}
|
22
|
+
END
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
graph_order = 'graph_order'
|
27
|
+
stat_config = ''
|
28
|
+
counters.keys.each do |stat|
|
29
|
+
stat_name = format_for_munin(stat)
|
30
|
+
graph_order << " "+ stat_name
|
31
|
+
stat_config = "#{stat_name}.label #{stat_name}"
|
32
|
+
net_stats.each do |var,value|
|
33
|
+
value = "#{stat_name}," + value if var == :cdef
|
34
|
+
stat_config << "#{stat_name}.#{var} #{value}\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
return graph_config + graph_order+"\n" + stat_config
|
39
|
+
end
|
40
|
+
|
41
|
+
def values
|
42
|
+
ret = ""
|
43
|
+
@scribe.getCounters.each do |k, v|
|
44
|
+
ret << "#{format_for_munin(k)}.value #{v}\n"
|
45
|
+
end
|
46
|
+
ret
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.run
|
50
|
+
host = ENV['SCRIBE_HOST'] || 'localhost';
|
51
|
+
port = ENV['SCRIBE_PORT'] || 1463;
|
52
|
+
scribe = new(host, port)
|
53
|
+
allowed_commands = ['config']
|
54
|
+
|
55
|
+
if cmd = ARGV[0] and allowed_commands.include? cmd then
|
56
|
+
puts scribe.send(cmd.to_sym)
|
57
|
+
else
|
58
|
+
puts scribe.values
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def format_for_munin(str)
|
65
|
+
str.to_s.gsub(/[^A-Za-z0-9_]/, "_")
|
66
|
+
end
|
67
|
+
|
68
|
+
def counters
|
69
|
+
@scribe.getCounters
|
70
|
+
end
|
71
|
+
|
72
|
+
def net_stats
|
73
|
+
stats = {
|
74
|
+
:type => 'COUNTER',
|
75
|
+
:cdef => '8,*'
|
76
|
+
}
|
77
|
+
return stats
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# Munin plugin for starling.
|
3
|
+
require 'rubygems'
|
4
|
+
require 'starling'
|
5
|
+
#Monkey patched so the namespaced queues are included in stats
|
6
|
+
require File.join(File.dirname(__FILE__), '..','starling', 'starling_stats')
|
7
|
+
|
8
|
+
module MuninManager
|
9
|
+
class Plugins::StarlingAge
|
10
|
+
include ActsAsMuninPlugin
|
11
|
+
|
12
|
+
def initialize(host, port)
|
13
|
+
@host = "#{host}:#{port}"
|
14
|
+
@starling = Starling.new(@host)
|
15
|
+
@category = 'starling'
|
16
|
+
end
|
17
|
+
|
18
|
+
def age_stats
|
19
|
+
defaults = {
|
20
|
+
:type => 'GAUGE',
|
21
|
+
:draw => 'AREA'
|
22
|
+
}
|
23
|
+
stats = @starling.available_queues.inject({}) do |stats, queue_name|
|
24
|
+
queue,item = queue_name.split(/:/, 2)
|
25
|
+
stats["queue_#{queue_name}_age"] = defaults.merge({
|
26
|
+
:label => "#{queue}[#{item}] age"
|
27
|
+
})
|
28
|
+
stats
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def config
|
34
|
+
graph_names = age_stats.keys.map{|n| n.to_s.tr(':', '_')}
|
35
|
+
graph_config = <<-END.gsub(/ +/, '')
|
36
|
+
graph_title Starling Queues Age
|
37
|
+
graph_vlabel seconds in queue
|
38
|
+
graph_category #{@category}
|
39
|
+
graph_order #{graph_names.sort.join(' ')}
|
40
|
+
END
|
41
|
+
|
42
|
+
age_stats.inject(graph_config) do |stat_config, stat|
|
43
|
+
stat[1].each do |var,value|
|
44
|
+
graph_config << "#{format_for_munin(stat[0])}.#{var} #{value}\n"
|
45
|
+
end
|
46
|
+
graph_config
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def values
|
51
|
+
age_stats.inject("") do |ret, stat|
|
52
|
+
ret << "#{format_for_munin(stat[0])}.value #{@starling.stats[@host][stat[0]]/1000.0}\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.run
|
57
|
+
host = ENV['HOST'] || '127.0.0.1';
|
58
|
+
port = ENV['PORT'] || 22122;
|
59
|
+
starling = new(host, port)
|
60
|
+
|
61
|
+
|
62
|
+
allowed_commands = ['config']
|
63
|
+
|
64
|
+
if cmd = ARGV[0] and allowed_commands.include? cmd then
|
65
|
+
puts starling.send(cmd.to_sym)
|
66
|
+
else
|
67
|
+
puts starling.values
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def format_for_munin(str)
|
74
|
+
str.to_s.gsub(/[^A-Za-z0-9_]/, "_")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# Munin plugin for starling.
|
3
|
+
require 'rubygems'
|
4
|
+
require 'starling'
|
5
|
+
#Monkey patched so the namespaced queues are included in stats
|
6
|
+
require File.join(File.dirname(__FILE__), '..','starling', 'starling_stats')
|
7
|
+
|
8
|
+
module MuninManager
|
9
|
+
class Plugins::StarlingNet
|
10
|
+
include ActsAsMuninPlugin
|
11
|
+
|
12
|
+
def initialize(host, port)
|
13
|
+
@host = "#{host}:#{port}"
|
14
|
+
@starling = Starling.new(@host)
|
15
|
+
@category = 'starling'
|
16
|
+
end
|
17
|
+
|
18
|
+
def net_stats
|
19
|
+
stats = {
|
20
|
+
:bytes_read => {
|
21
|
+
:label => 'read',
|
22
|
+
:type => 'COUNTER',
|
23
|
+
:graph => 'no',
|
24
|
+
:cdef => 'bytes_read,8,*'
|
25
|
+
},
|
26
|
+
:bytes_written => {
|
27
|
+
:label => 'bps',
|
28
|
+
:type => 'COUNTER',
|
29
|
+
:cdef => 'bytes_written,8,*',
|
30
|
+
:negative => 'bytes_read'
|
31
|
+
}
|
32
|
+
}
|
33
|
+
return stats
|
34
|
+
end
|
35
|
+
|
36
|
+
def config
|
37
|
+
graph_config = <<-END.gsub(/ +/, '')
|
38
|
+
graph_title Starling traffic
|
39
|
+
graph_args --base 1000
|
40
|
+
graph_vlabel bits read(-) / written(+) per second
|
41
|
+
graph_category #{@category}
|
42
|
+
graph_order bytes_read bytes_written
|
43
|
+
END
|
44
|
+
|
45
|
+
stat_config = ''
|
46
|
+
net_stats.each do |stat,config|
|
47
|
+
config.each do |var,value|
|
48
|
+
stat_config << "#{stat}.#{var} #{value}\n"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return graph_config + stat_config
|
52
|
+
end
|
53
|
+
|
54
|
+
def values
|
55
|
+
ret = "bytes_read.value #{@starling.stats[@host]['bytes_read']}\n"
|
56
|
+
ret << "bytes_written.value #{@starling.stats[@host]['bytes_written']}\n"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.run
|
60
|
+
host = ENV['HOST'] || '127.0.0.1';
|
61
|
+
port = ENV['PORT'] || 22122;
|
62
|
+
starling = new(host, port)
|
63
|
+
|
64
|
+
|
65
|
+
allowed_commands = ['config']
|
66
|
+
|
67
|
+
if cmd = ARGV[0] and allowed_commands.include? cmd then
|
68
|
+
puts starling.send(cmd.to_sym)
|
69
|
+
else
|
70
|
+
puts starling.values
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def format_for_munin(str)
|
77
|
+
str.to_s.gsub(/[^A-Za-z0-9_]/, "_")
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# Munin plugin for starling.
|
3
|
+
require 'rubygems'
|
4
|
+
require 'starling'
|
5
|
+
#Monkey patched so the namespaced queues are included in stats
|
6
|
+
require File.join(File.dirname(__FILE__), '..','starling', 'starling_stats')
|
7
|
+
|
8
|
+
module MuninManager
|
9
|
+
class Plugins::StarlingOps
|
10
|
+
include ActsAsMuninPlugin
|
11
|
+
|
12
|
+
def initialize(host, port)
|
13
|
+
@host = "#{host}:#{port}"
|
14
|
+
@starling = Starling.new(@host)
|
15
|
+
@category = 'starling'
|
16
|
+
end
|
17
|
+
|
18
|
+
def ops_stats
|
19
|
+
defaults = {
|
20
|
+
'min' => 0,
|
21
|
+
'max' => 5000,
|
22
|
+
'type' => 'DERIVE',
|
23
|
+
'draw' => 'LINE2',
|
24
|
+
}
|
25
|
+
stats = {
|
26
|
+
'cmd_get' => {:label => 'GETs'},
|
27
|
+
'cmd_set' => {:label => 'SETs'},
|
28
|
+
'get_hits' => {:label => 'Hits'},
|
29
|
+
'get_misses' => {:label => 'Misses'}
|
30
|
+
}
|
31
|
+
|
32
|
+
stats.each_key do |k|
|
33
|
+
stats[k] = defaults.merge(stats[k])
|
34
|
+
end
|
35
|
+
return stats
|
36
|
+
end
|
37
|
+
|
38
|
+
def config
|
39
|
+
graph_config = <<-END.gsub(/ +/, '')
|
40
|
+
graph_title Starling Operations
|
41
|
+
graph_args --base 1000
|
42
|
+
graph_vlabel ops/${graph_period}
|
43
|
+
graph_category #{@category}
|
44
|
+
graph_order cmd_set cmd_get get_hits get_misses
|
45
|
+
END
|
46
|
+
|
47
|
+
stat_config = []
|
48
|
+
ops_stats.each do |stat,config|
|
49
|
+
config.each do |var,value|
|
50
|
+
stat_config << "#{stat}.#{var} #{value}\n"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return graph_config + stat_config.sort.join
|
54
|
+
end
|
55
|
+
|
56
|
+
def values
|
57
|
+
ret = ''
|
58
|
+
ops_stats.each_key do |stat|
|
59
|
+
ret << "#{stat}.value #{@starling.stats[@host][stat]}\n"
|
60
|
+
end
|
61
|
+
return ret
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.run
|
65
|
+
host = ENV['HOST'] || '127.0.0.1';
|
66
|
+
port = ENV['PORT'] || 22122;
|
67
|
+
starling = new(host, port)
|
68
|
+
|
69
|
+
allowed_commands = ['config']
|
70
|
+
|
71
|
+
if cmd = ARGV[0] and allowed_commands.include? cmd then
|
72
|
+
puts starling.send(cmd.to_sym)
|
73
|
+
else
|
74
|
+
puts starling.values
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def format_for_munin(str)
|
81
|
+
str.to_s.gsub(/[^A-Za-z0-9_]/, "_")
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# Munin plugin for starling.
|
3
|
+
require 'rubygems'
|
4
|
+
require 'starling'
|
5
|
+
#Monkey patched so the namespaced queues are included in stats
|
6
|
+
require File.join(File.dirname(__FILE__), '..','starling', 'starling_stats')
|
7
|
+
|
8
|
+
module MuninManager
|
9
|
+
class Plugins::StarlingQueue
|
10
|
+
include ActsAsMuninPlugin
|
11
|
+
|
12
|
+
def initialize(host, port)
|
13
|
+
@host = "#{host}:#{port}"
|
14
|
+
@starling = Starling.new(@host)
|
15
|
+
@category = 'starling'
|
16
|
+
end
|
17
|
+
|
18
|
+
def queues_stats
|
19
|
+
defaults = {
|
20
|
+
'type' => 'GAUGE',
|
21
|
+
'draw' => 'LINE2'
|
22
|
+
}
|
23
|
+
stats = @starling.available_queues.inject({}) do |stats, queue_name|
|
24
|
+
queue,item = queue_name.split(/:/, 2)
|
25
|
+
stats["queue_#{queue_name}_items"] = defaults.merge({
|
26
|
+
:label => "#{queue}[#{item}] items"
|
27
|
+
})
|
28
|
+
stats["queue_#{queue_name}_expired_items"] = defaults.merge({
|
29
|
+
:label => "#{queue}[#{item}] expired"
|
30
|
+
})
|
31
|
+
stats
|
32
|
+
end
|
33
|
+
|
34
|
+
return stats
|
35
|
+
end
|
36
|
+
|
37
|
+
def config
|
38
|
+
graph_names = queues_stats.keys.map{|n| n.to_s.tr(':', '_')}
|
39
|
+
graph_config = <<-END.gsub(/ +/, '')
|
40
|
+
graph_title Starling queues
|
41
|
+
graph_args --base 1000
|
42
|
+
graph_vlabel items
|
43
|
+
graph_category #{@category}
|
44
|
+
graph_order #{graph_names.sort.join(' ')}
|
45
|
+
END
|
46
|
+
|
47
|
+
queues_stats.inject(graph_config) do |stat_config, stat|
|
48
|
+
stat[1].each do |var,value|
|
49
|
+
graph_config << "#{format_for_munin(stat[0])}.#{var} #{value}\n"
|
50
|
+
end
|
51
|
+
graph_config
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def values
|
56
|
+
queues_stats.inject("") do |ret, stat|
|
57
|
+
ret << "#{format_for_munin(stat[0])}.value #{@starling.stats[@host][stat[0]]}\n"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.run
|
62
|
+
host = ENV['HOST'] || '127.0.0.1';
|
63
|
+
port = ENV['PORT'] || 22122;
|
64
|
+
starling = new(host, port)
|
65
|
+
|
66
|
+
|
67
|
+
allowed_commands = ['config']
|
68
|
+
|
69
|
+
if cmd = ARGV[0] and allowed_commands.include? cmd then
|
70
|
+
puts starling.send(cmd.to_sym)
|
71
|
+
else
|
72
|
+
puts starling.values
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def format_for_munin(str)
|
79
|
+
str.to_s.gsub(/[^A-Za-z0-9_]/, "_")
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|