munin 0.0.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/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
+