munin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-12-09
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,9 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ lib/munin.rb
7
+ script/console
8
+ script/destroy
9
+ script/generate
data/PostInstall.txt ADDED
@@ -0,0 +1,4 @@
1
+
2
+ For more information on munin, see http://github.com/albanpeignier/munin/
3
+
4
+
data/README.rdoc ADDED
@@ -0,0 +1,72 @@
1
+ = munin
2
+
3
+ * http://github.com/albanpeignier/munin/
4
+
5
+ == DESCRIPTION:
6
+
7
+ The munin gem provides a base class to create munin plugins in ruby.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * create munin plugin config output from class attributes
12
+ * format munin plugin output from a map of values
13
+ * support configuration based on filename
14
+
15
+ == SYNOPSIS:
16
+
17
+ require 'rubygems'
18
+ require 'munin'
19
+
20
+ class FetchmailMailVolume < Munin::Plugin
21
+
22
+ graph_attributes "Fetchmail bytes throughput",
23
+ :category => 'Mail',
24
+ :info => 'This graph shows the volume of mails retrieved by fetchmail'
25
+
26
+ declare_field :volume,
27
+ :label => 'throughput', :type => :derive, :min => 0
28
+
29
+ def retrieve_values
30
+ volume = 0
31
+ File.open('/var/log/mail.log','r') do |f|
32
+ while line = f.gets
33
+ if line.match(/fetchmail\[[0-9]+\]: reading message .*\(([0-9]+) octets\)/)
34
+ volume = volume + $1.to_i
35
+ end
36
+ end
37
+ end
38
+ { :volume => volume }
39
+ end
40
+
41
+ end
42
+
43
+ FetchmailMailVolume.new.run
44
+
45
+ == INSTALL:
46
+
47
+ * sudo gem install munin
48
+
49
+ == LICENSE:
50
+
51
+ (The MIT License)
52
+
53
+ Copyright (c) 2008 Alban Peignier
54
+
55
+ Permission is hereby granted, free of charge, to any person obtaining
56
+ a copy of this software and associated documentation files (the
57
+ 'Software'), to deal in the Software without restriction, including
58
+ without limitation the rights to use, copy, modify, merge, publish,
59
+ distribute, sublicense, and/or sell copies of the Software, and to
60
+ permit persons to whom the Software is furnished to do so, subject to
61
+ the following conditions:
62
+
63
+ The above copyright notice and this permission notice shall be
64
+ included in all copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
67
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
69
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
71
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
72
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen hoe].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/munin'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.spec('munin') do |p|
7
+ p.version = Munin::VERSION
8
+ p.developer('Alban Peignier', 'alban@tryphon.eu')
9
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
10
+ p.rubyforge_name = p.name # TODO this is default value
11
+ p.summary = "Create munin plugins in ruby"
12
+
13
+ # p.extra_deps = [
14
+ # ['activesupport','>= 2.0.2'],
15
+ # ]
16
+ # p.extra_dev_deps = [
17
+ # ['newgem', ">= #{::Newgem::VERSION}"]
18
+ # ]
19
+
20
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
21
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
22
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
23
+ p.rsync_args = '-av --delete --ignore-errors'
24
+ end
25
+
26
+ require 'newgem/tasks' # load /tasks/*.rake
27
+ Dir['tasks/**/*.rake'].each { |t| load t }
28
+
29
+ # TODO - want other tests/tasks run by default? Add them to the list
30
+ # task :default => [:spec, :features]
data/lib/munin.rb ADDED
@@ -0,0 +1,281 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module Munin
5
+ VERSION = '0.0.1'
6
+
7
+ # Base class to create Munin plugin
8
+ #
9
+ # class ActiveRecordSessionPlugin << Munin::Plugin
10
+ # graph_attributes "Rails Sessions",
11
+ # :category => 'Application',
12
+ # :info => 'This graph shows the rails application session count'
13
+ #
14
+ # declare_field :count, :label => 'session count', :min => 0
15
+ #
16
+ # def retrieve_values
17
+ # count = ...
18
+ # { :count => count }
19
+ # end
20
+ # end
21
+ #
22
+ # ActiveRecordSessionPlugin.run
23
+ class Plugin
24
+
25
+ class << self
26
+
27
+ @@fields = []
28
+
29
+ # Sets the graph attributes of the plugin
30
+ #
31
+ # ==== Attributes
32
+ # * +title+: - The title of the graph, defaults to the plugin's name (munin global attribute graph_title)
33
+ # * +options+: - Other graph attributes for the plugin (munin global attribute graph_*)
34
+ #
35
+ # ==== Examples
36
+ #
37
+ # # Set classic graph attributes
38
+ # graph_attributes "Fetchmail bytes throughput",
39
+ # :category => 'Mail',
40
+ # :info => 'This graph shows the volume of mails retrieved by fetchmail'
41
+ def graph_attributes(title, options = {})
42
+ @@graph_options = { :title => title, :args => '--base 1000' }.merge(options)
43
+ end
44
+
45
+ # Declare a data source / field of the plugin
46
+ #
47
+ # ==== Attributes
48
+ # * +name+: - The field name
49
+ # * +options+: - The field attributes
50
+ #
51
+ # ==== Examples
52
+ #
53
+ # # Set a derive field
54
+ # declare_field :volume, :label => 'throughput', :type => :derive, :min => 0
55
+ def declare_field(name, options = {})
56
+ @@fields << Field.new(name, options)
57
+ end
58
+
59
+ # An elegant way to share common options
60
+ #
61
+ # ==== Attributes
62
+ # * +options+: - The common options
63
+ #
64
+ # ==== Examples
65
+ #
66
+ # # Share field attributes
67
+ # with :type => :derive, :min => 0 do
68
+ # declare_field :input, :label => "download"
69
+ # declare_field :output, :label => "upload"
70
+ # end
71
+ def with_options(options)
72
+ yield OptionMerger.new(self, options)
73
+ end
74
+
75
+ end
76
+
77
+ attr_reader :fields
78
+
79
+ def initialize(config = {})
80
+ @config = config.symbolize_keys
81
+
82
+ if self.class.respond_to?(:config_from_filename)
83
+ @config.merge!(self.class.config_from_filename.symbolize_keys)
84
+ end
85
+
86
+ @fields = @@fields.dup
87
+
88
+ after_initialize if respond_to?(:after_initialize)
89
+ end
90
+
91
+ # Prints plugin configuration by using the munin format
92
+ def print_config
93
+ output 'host_name', hostname unless hostname.nil?
94
+
95
+ GRAPH_ATTRIBUTES.each do |graph_attribute|
96
+ graph_option = @@graph_options[graph_attribute.to_sym]
97
+ output "graph_#{graph_attribute}", graph_option unless graph_option.nil?
98
+ end
99
+
100
+ fields.each do |field|
101
+ field.config.each_pair { |key, value| output key, value }
102
+ end
103
+ end
104
+
105
+ # Prints plugin values by using the munin format
106
+ def print_values
107
+ retrieve_values.each_pair do |name, value|
108
+ output "#{name}.value", value
109
+ end
110
+ end
111
+
112
+ # Create and executes the plugin
113
+ def self.run
114
+ self.new.run
115
+ end
116
+
117
+ # Executes the plugin
118
+ def run
119
+ case ARGV.first
120
+ when "config"
121
+ print_config
122
+ else
123
+ print_values
124
+ end
125
+ end
126
+
127
+ def declare_field(name, options = {})
128
+ @fields << Field.new(name, options)
129
+ end
130
+
131
+ protected
132
+
133
+ attr_accessor :hostname
134
+
135
+ def output(key, value)
136
+ puts "#{key} #{value}"
137
+ end
138
+
139
+ def config_value(key)
140
+ @config[key]
141
+ end
142
+
143
+ GRAPH_ATTRIBUTES = %w{ title args category info order vlabel total scale period vtitle width height printf }
144
+
145
+ private
146
+
147
+ def method_missing(method, *arguments, &block)
148
+ case method.id2name
149
+ when /^graph_([_a-z]+)$/
150
+ @@graph_options[$1.to_sym]
151
+ when /^graph_([_a-z]+)=$/
152
+ @@graph_options[$1.to_sym] = arguments
153
+ else super
154
+ end
155
+ end
156
+
157
+ end
158
+
159
+ class Field
160
+
161
+ attr_reader :name, :options
162
+
163
+ def initialize(name, options = {})
164
+ @name, @options = name.to_s, options
165
+
166
+ @options[:label] ||= default_label(name)
167
+ end
168
+
169
+ def default_label(name)
170
+ name.to_s.gsub('_',' ')
171
+ end
172
+
173
+ def option(key)
174
+ @options[key]
175
+ end
176
+
177
+ DATA_SOURCE_ATTRIBUTES = %w{ label cdef draw graph extinfo max min negative type warning critical colour skipdraw sum stack line }
178
+
179
+ def config
180
+ DATA_SOURCE_ATTRIBUTES.inject({}) do |config, attribute|
181
+ attribute = attribute.to_sym
182
+ attribute_value = @options[attribute]
183
+
184
+ unless attribute_value.nil?
185
+ case attribute
186
+ when :type
187
+ attribute_value = attribute_value.to_s.upcase
188
+ end
189
+ config["#{name}.#{attribute}"] = attribute_value
190
+ end
191
+
192
+ config
193
+ end
194
+ end
195
+
196
+ def ==(other)
197
+ other and name == other.name and options == other.options
198
+ end
199
+
200
+ end
201
+
202
+ class OptionMerger # from ActiveSupport
203
+ instance_methods.each do |method|
204
+ undef_method(method) if method !~ /^(__|instance_eval|class|object_id)/
205
+ end
206
+
207
+ def initialize(context, options)
208
+ @context, @options = context, options
209
+ end
210
+
211
+ private
212
+ def method_missing(method, *arguments, &block)
213
+ merge_argument_options! arguments
214
+ @context.send(method, *arguments, &block)
215
+ end
216
+
217
+ def merge_argument_options!(arguments)
218
+ arguments << if arguments.last.respond_to? :to_hash
219
+ @options.merge(arguments.pop)
220
+ else
221
+ @options.dup
222
+ end
223
+ end
224
+ end
225
+
226
+ module Hash
227
+ module Keys
228
+ # Return a new hash with all keys converted to strings.
229
+ def stringify_keys
230
+ inject({}) do |options, (key, value)|
231
+ options[key.to_s] = value
232
+ options
233
+ end
234
+ end
235
+
236
+ # Destructively convert all keys to strings.
237
+ def stringify_keys!
238
+ keys.each do |key|
239
+ unless key.class.to_s == "String" # weird hack to make the tests run when string_ext_test.rb is also running
240
+ self[key.to_s] = self[key]
241
+ delete(key)
242
+ end
243
+ end
244
+ self
245
+ end
246
+
247
+ # Return a new hash with all keys converted to symbols.
248
+ def symbolize_keys
249
+ inject({}) do |options, (key, value)|
250
+ options[key.to_sym || key] = value
251
+ options
252
+ end
253
+ end
254
+
255
+ # Destructively convert all keys to symbols.
256
+ def symbolize_keys!
257
+ self.replace(self.symbolize_keys)
258
+ end
259
+
260
+ alias_method :to_options, :symbolize_keys
261
+ alias_method :to_options!, :symbolize_keys!
262
+
263
+ # Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
264
+ # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbol
265
+ # as keys, this will fail.
266
+ # examples:
267
+ # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
268
+ # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): years, name"
269
+ # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
270
+ def assert_valid_keys(*valid_keys)
271
+ unknown_keys = keys - [valid_keys].flatten
272
+ raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
273
+ end
274
+ end
275
+ end
276
+
277
+ end
278
+
279
+ class Hash #:nodoc:
280
+ include Munin::Hash::Keys
281
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/munin.rb'}"
9
+ puts "Loading munin gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: munin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alban Peignier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-04 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubyforge
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: gemcutter
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.5.0
44
+ version:
45
+ description: ""
46
+ email:
47
+ - alban@tryphon.eu
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - PostInstall.txt
56
+ files:
57
+ - History.txt
58
+ - Manifest.txt
59
+ - PostInstall.txt
60
+ - README.rdoc
61
+ - Rakefile
62
+ - lib/munin.rb
63
+ - script/console
64
+ - script/destroy
65
+ - script/generate
66
+ has_rdoc: true
67
+ homepage:
68
+ licenses: []
69
+
70
+ post_install_message:
71
+ rdoc_options:
72
+ - --main
73
+ - README.txt
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ requirements: []
89
+
90
+ rubyforge_project: munin
91
+ rubygems_version: 1.3.5
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: Create munin plugins in ruby
95
+ test_files: []
96
+