munin_manager 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|