munin2graphite 0.1.0

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.
@@ -0,0 +1,30 @@
1
+ require 'net/http'
2
+
3
+ module Graphite
4
+ class Base
5
+
6
+
7
+ # connection instance (shared with every instance of the class)
8
+ def self.connection
9
+ @@init_header ||= {}
10
+ @@connection ||= Net::HTTP.new(@@endpoint)
11
+ end
12
+
13
+ # If the operation needs authentication you have to call this first
14
+ def self.authenticate(user = @@user,password = @@password)
15
+ response = self.connection.post("/account/login","nextPage=/&password=#{password}&username=#{user}")
16
+ @@init_header = {"Cookie" => response.get_fields('Set-Cookie').first}
17
+ end
18
+
19
+ def self.set_connection(endpoint,user = "",password = "")
20
+ @@endpoint = endpoint
21
+ @@user ||= user
22
+ @@password ||= password
23
+ end
24
+
25
+ # Get
26
+ def self.get(path,args)
27
+ self.connection.get(path + "?" + args.map { |i,j| i.to_s + "=" + j }.join("&"),@@init_header)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ require 'json'
2
+
3
+ module Graphite
4
+ class Graph < Graphite::Base
5
+ attr_accessor :name,:id,:allow_children,:leaf,:url
6
+
7
+ def self.find_by_query_and_path(query,path)
8
+ graph_type = "#{self}" == "Graphite::MyGraph" ? "mygraph" : "usergraph"
9
+ return JSON.parse(self.get("/browser/#{graph_type}/",{:format => "treejson",:query => query,:path =>path}).body).map do |graphic_hash|
10
+ graphic = MyGraph.new
11
+ graphic.url = graphic_hash["graphUrl"]
12
+ graphic.name = graphic_hash["id"]
13
+ graphic.leaf = graphic_hash["leaf"] == 1
14
+ graphic.allow_children = graphic_hash["allowChildren"] == 1
15
+ graphic
16
+ end
17
+ end
18
+
19
+
20
+ def self.descend_to_leaf(query,path)
21
+ result = []
22
+ self.find_by_query_and_path(query,path).each do |graph|
23
+ if graph.leaf
24
+ return graph
25
+ else
26
+ result << self.descend_to_leaf(graph.name + "*",graph.name)
27
+ end
28
+ end
29
+ return result
30
+ end
31
+
32
+ def self.find_all_by_query(query)
33
+ result = []
34
+ self.find_by_query_and_path(query,"").each do |graph|
35
+ result << self.descend_to_leaf(graph.name + "*",graph.name)
36
+ end
37
+ return result.flatten
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ require 'json'
2
+
3
+ module Graphite
4
+ class Metric < Graphite::Base
5
+ attr_accessor :name,:id,:allow_children,:leaf
6
+
7
+ def self.find_by_query(query)
8
+
9
+ return JSON.parse(self.get("/metrics/find",{:format => "treejson",:query => query}).body).map do |metric_hash|
10
+ metric = Metric.new
11
+ metric.name = metric_hash["text"]
12
+ metric.id = metric_hash["id"]
13
+ metric.allow_children = metric_hash["allowChildren"] == 1
14
+ metric.leaf = metric_hash["leaf"] == 1
15
+ metric
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ require 'json'
2
+
3
+ module Graphite
4
+ class MyGraph < Graph
5
+
6
+ def save!
7
+ MyGraph.get("/composer/mygraph/",:action => "save", :graphName => name,:url => url.gsub("&","%26"))
8
+ Munin2Graphite::Config.log.debug("Saving: #{name} ")
9
+ Munin2Graphite::Config.log.debug(" url: #{url} ")
10
+
11
+ end
12
+
13
+ def delete!
14
+ MyGraph.get("/composer/mygraph/",:action => "delete", :graphName => name,:url => url.gsub("&","%26"))
15
+ end
16
+
17
+ # Returns a graph by name
18
+ def self.find_by_name(name)
19
+ MyGraph.find_by_query_and_path(name,name.split(".").first).first
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ module Graphite
2
+ class UserGraph < Graph
3
+ end
4
+ end
data/lib/graphite.rb ADDED
@@ -0,0 +1,8 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+ $:.unshift(File.join(File.dirname(__FILE__)),"graphite")
3
+ require 'graphite/base'
4
+ require 'graphite/metric'
5
+ require 'graphite/graph'
6
+ require 'graphite/my_graph'
7
+ require 'graphite/user_graph'
8
+
@@ -0,0 +1,117 @@
1
+ require 'parseconfig'
2
+ require 'logger'
3
+ module Munin2Graphite
4
+
5
+ class Config
6
+
7
+ class NotConfiguredException < Exception; end
8
+ class ConfigFileNotFoundException < Exception; end
9
+ class MalformedConfigFileException < Exception; end
10
+ class RequiredFieldMissingException < Exception; end
11
+
12
+ class << self
13
+
14
+ # Returns the config for a given class
15
+ def config_for_class(klass)
16
+ return @config[klass.to_s.decamelize.to_sym]
17
+ end
18
+
19
+ def workers
20
+ return @config.groups
21
+ end
22
+
23
+ attr_accessor :config
24
+
25
+ # This method will return a config class but for a given worker, so everything will be the same as in the original class
26
+ # but the config changes made in this worker
27
+ def config_for_worker(worker)
28
+ return self if worker == "global"
29
+ cloned = self.clone
30
+ cloned.config = @config.clone
31
+ cloned.config.params = @config.params.merge(@config.params[worker])
32
+ return cloned
33
+ end
34
+
35
+ def deconfigure!
36
+ @config = nil
37
+ @config_file = nil
38
+ end
39
+
40
+ def configured?
41
+ return @config_file != nil
42
+ end
43
+
44
+ def parse_config
45
+ begin
46
+ @config = ParseConfig.new(@config_file)
47
+ rescue Errno::ENOENT
48
+ raise ConfigFileNotFoundException.new("Error, trying to open the config file #{@config_file}")
49
+ rescue ArgumentError => exception
50
+ raise MalformedConfigFileException.new("Malformed config file '#{@config_file}' #{exception.message}")
51
+ rescue
52
+ raise "Unknown error when trying to open config file '#{@config_file}'"
53
+ end
54
+ @config
55
+ end
56
+
57
+ def check_config
58
+ fields={:carbon => [:hostname,:port],:graphite => [:endpoint,:metric_prefix,:user,:password],:scheduler => [:metrics_period,:graphs_period]}
59
+ fields.each do |k,v|
60
+ v.each do |inner_field|
61
+ field = "#{k}_#{inner_field}"
62
+ if !@config.params[field]
63
+ workers.each do |worker|
64
+ raise RequiredFieldMissingException.new("Error, required field not found in config ':#{field}' for worker #{worker}") unless @config.params[worker][field]
65
+ end
66
+
67
+ raise RequiredFieldMissingException.new("Error, required field not found in config ':#{field}'") if workers.empty?
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def method_missing(method_name,*args)
74
+ if !@config
75
+ if @config_file
76
+ parse_and_check!
77
+ end
78
+ raise NotConfiguredException.new("Not Configured") unless @config
79
+ end
80
+
81
+ if method_name == :"[]"
82
+ if @config.params.has_key?(args.first.to_s)
83
+ return @config.params[args.first.to_s]
84
+ end
85
+ end
86
+ if @config.params.respond_to?method_name
87
+ return @config.params.send(method_name,*args)
88
+ end
89
+ super
90
+ end
91
+
92
+ def log
93
+ @log ||= if self["log"] == "STDOUT"
94
+ Logger.new(STDOUT)
95
+ else
96
+ Logger.new(self["log"])
97
+ end
98
+ @log.level = self["log_level"] == "DEBUG" ? Logger::DEBUG : Logger::INFO
99
+ @log
100
+ end
101
+
102
+ def config_file=(config_file)
103
+ @config_file = config_file
104
+ end
105
+
106
+ def config=(config)
107
+ @config = config
108
+ check_config
109
+ end
110
+
111
+ def parse_and_check!
112
+ parse_config
113
+ check_config
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,169 @@
1
+ #
2
+ # Author:: Jose Fernandez (@magec)
3
+ # Copyright:: Copyright (c) 2011 UOC (Universitat Oberta de Catalunya)
4
+ #
5
+ # This program and entire repository is free software; you can
6
+ # redistribute it and/or modify it under the terms of the GNU
7
+ # General Public License as published by the Free Software
8
+ # Foundation; either version 2 of the License, or any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General putsPublic License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ require 'rufus/scheduler'
19
+ module Munin2Graphite
20
+ ##
21
+ # This class holds the main scheduler of the system, it will perform the applicacion loops
22
+ class Scheduler
23
+
24
+ attr_accessor :scheduler
25
+
26
+ def initialize(config)
27
+ @config = config
28
+ end
29
+
30
+ def category_from_config(config)
31
+ config.each_line do |configline|
32
+ if configline =~ /^graph_category ([0-9A-Za-z_-]+)$/
33
+ return configline.split[1]
34
+ end
35
+ end
36
+ return "other"
37
+ raise "CategoryNotFound in #{config}"
38
+ end
39
+
40
+ def munin_config
41
+ return @munin_config if @munin_config
42
+ @munin_config = {}
43
+
44
+ workers.each do |worker|
45
+ @munin_config[worker] = {}
46
+ config = @config.config_for_worker(worker)
47
+ munin = Munin::Node.new(config["munin_hostname"],config["munin_port"])
48
+ nodes = config["munin_nodes"] ? config["munin_nodes"].split(",") : munin.nodes
49
+ @munin_config[worker][:nodes] = {}
50
+ nodes.each do |node|
51
+
52
+ @munin_config[worker][:nodes][node] = {:metrics => munin.list(node)}
53
+ @munin_config[worker][:nodes][node][:categories] = {}
54
+
55
+ @munin_config[worker][:nodes][node][:metrics].each do |metric|
56
+ @munin_config[worker][:nodes][node][:config] = munin.config(metric)[metric]
57
+ @munin_config[worker][:nodes][node][:raw_config] = munin.config(metric,true)[metric]
58
+ @munin_config[worker][:nodes][node][:categories][metric] = category_from_config(@munin_config[worker][:nodes][node][:raw_config])
59
+ end
60
+ end
61
+ munin.disconnect
62
+ end
63
+ @munin_config
64
+ end
65
+
66
+ def workers
67
+ @workers ||= (@config.workers.empty? ? ["global"] : @config.workers )
68
+ end
69
+
70
+ #
71
+ # This is the loop of the metrics scheduling
72
+ def obtain_metrics
73
+ config = @config.config_for_worker("global")
74
+ config.log.info("Obtaining metrics configuration")
75
+ munin_config
76
+ config.log.info("Getting metrics")
77
+ time = Time.now
78
+ workers.each do |worker|
79
+ config = @config.config_for_worker(worker)
80
+ config.log.info("Worker #{worker}")
81
+
82
+ metric_base = config["graphite_metric_prefix"]
83
+
84
+ threads = []
85
+ munin_config[worker][:nodes].keys.each do |node|
86
+ threads << Thread.new do
87
+ node_name = metric_base + "." + node.split(".").first
88
+ config.log.debug("Doing #{node_name}")
89
+ values = {}
90
+ config.log.debug("Asking for: #{node}")
91
+ metric_time = Time.now
92
+ metrics = munin_config[worker][:nodes][node][:metrics]
93
+ config.log.debug("Metrics " + metrics.join(","))
94
+ metrics_threads = []
95
+ categories = {}
96
+ metrics.each do |metric|
97
+ metrics_threads << Thread.new do
98
+ local_munin = Munin::Node.new(config["munin_hostname"],config["munin_port"])
99
+ values[metric] = local_munin.fetch metric
100
+ local_munin.disconnect
101
+ end
102
+ end
103
+ metrics_threads.each {|i| i.join;i.kill}
104
+ config.log.info("Done with: #{node} (#{Time.now - metric_time} s)")
105
+ carbon = Carbon.new(config["carbon_hostname"],config["carbon_port"])
106
+ string_to_send = ""
107
+ values.each do |metric,results|
108
+ category = munin_config[worker][:nodes][node][:categories][metric]
109
+ results.each do |k,v|
110
+ v.each do |c_metric,c_value|
111
+ string_to_send += "#{node_name}.#{category}.#{metric}.#{c_metric} #{c_value} #{Time.now.to_i}\n".gsub("-","_") if c_value != "U"
112
+ end
113
+ end
114
+ end
115
+ send_time = Time.now
116
+ carbon.send(string_to_send)
117
+ carbon.flush
118
+ carbon.close
119
+ end
120
+ end
121
+ threads.each { |i| i.join }
122
+ end
123
+ @config.log.info("End getting metrics, elapsed time (#{Time.now - time}s)")
124
+ end
125
+
126
+ ##
127
+ # The loop of the graphics creation
128
+ def obtain_graphs
129
+
130
+ workers = @config.workers
131
+ workers = ["global"] if workers.empty?
132
+
133
+ workers.each do |worker|
134
+ time = Time.now
135
+ config = @config.config_for_worker worker
136
+ config.log.info("Begin : Sending Graph Information to Graphite for worker #{worker}")
137
+ munin = Munin::Node.new(config["munin_hostname"],config["munin_port"])
138
+ nodes = config["munin_nodes"] ? config["munin_nodes"].split(",") : munin.nodes
139
+ nodes.each do |node|
140
+ config.log.info("Graphs for #{node}")
141
+ munin.list(node).each do |metric|
142
+ config.log.info("Configuring #{metric}")
143
+ Graphite::Base.set_connection(config["carbon_hostname"])
144
+ Graphite::Base.authenticate(config["graphite_user"],config["graphite_password"])
145
+ munin_graph = MuninGraph.graph_for munin.config(metric,true)[metric]
146
+
147
+ munin_graph.config = config.merge("metric" => "#{metric}","hostname" => node.split(".").first)
148
+ config.log.debug("Saving graph #{metric}")
149
+ munin_graph.to_graphite.save!
150
+ end
151
+ end
152
+ config.log.info("End : Sending Graph Information to Graphite for worker #{worker}, elapsed time (#{Time.now - time}s)")
153
+ munin.disconnect
154
+ end
155
+
156
+ end
157
+
158
+ def start
159
+ @config.log.info("Scheduler started")
160
+ @scheduler = Rufus::Scheduler.start_new
161
+ obtain_metrics
162
+ @scheduler.every @config["scheduler_metrics_period"] do
163
+ obtain_metrics
164
+ end
165
+ obtain_graphs
166
+ end
167
+
168
+ end
169
+ end
@@ -0,0 +1,8 @@
1
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__),"munin2graphite")))
2
+ require 'rubygems'
3
+ require 'munin-ruby'
4
+ require 'carbon'
5
+ require 'graphite'
6
+ require 'munin_graph'
7
+ require 'munin2graphite/config'
8
+ require 'munin2graphite/scheduler'
@@ -0,0 +1,136 @@
1
+ require 'ast_node'
2
+ require 'graphite'
3
+ #
4
+ # Author:: Jose Fernandez (@magec)
5
+ # Copyright:: Copyright (c) 2011 UOC (Universitat Oberta de Catalunya)
6
+ # License:: GNU General Public License version 2 or later
7
+ #
8
+ # This program and entire repository is free software; you can
9
+ # redistribute it and/or modify it under the terms of the GNU
10
+ # General Public License as published by the Free Software
11
+ # Foundation; either version 2 of the License, or any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+
22
+
23
+ ##
24
+ # This class allows the transformation between graphite and munin config. It constructs an AST parsing the munin config information and
25
+ # allows to output a valid graphic in graphite url format
26
+ # Jose Fernandez 2011
27
+ #
28
+ class MuninGraph
29
+
30
+ def self.graph_for(config)
31
+ MuninGraph.new(config)
32
+ end
33
+
34
+ def initialize(config)
35
+ @raw_config = config
36
+ parse_config
37
+ end
38
+
39
+ def config=(config)
40
+ @config = config
41
+ self.root.config = config
42
+ end
43
+
44
+ def to_graphite
45
+ graph = Graphite::MyGraph.new
46
+ self.root.compile
47
+ graph.url = self.root.url
48
+ self.root.properties[:category] ||= "other"
49
+
50
+ graph.name = "#{@config["hostname"]}.#{self.root.properties["category"]}.#{self.root.properties["metric"]}"
51
+ graph.name = "#{@config["graphite_graph_prefix"]}.#{graph.name}" if @config["graphite_graph_prefix"] && @config["graphite_graph_prefix"] != ""
52
+ return graph
53
+ end
54
+
55
+ attr_reader :root
56
+
57
+ # This array of hashes will be used to match what kind of line we are dealing with and
58
+ # to know the corresponding ast node class
59
+ TOKENS = [
60
+ {:matcher => /^graph_title .*/, :klass => GraphTitleGlobalDeclarationNode},
61
+ {:matcher => /^create_args .*/, :klass => CreateArgsGlobalDeclarationNode},
62
+ {:matcher => /^graph_args .*/, :klass => GraphArgsGlobalDeclarationNode},
63
+ {:matcher => /^graph_category .*/, :klass => GraphCategoryGlobalDeclarationNode},
64
+ {:matcher => /^graph_info .*/, :klass => GraphInfoGlobalDeclarationNode},
65
+ {:matcher => /^graph_order .*/, :klass => GraphOrderGlobalDeclarationNode},
66
+ {:matcher => /^graph_vlabel .*/, :klass => GraphVLabelGlobalDeclarationNode},
67
+ {:matcher => /^graph_total .*/, :klass => GraphTotalGlobalDeclarationNode},
68
+ {:matcher => /^graph_scale .*/, :klass => GraphScaleGlobalDeclarationNode},
69
+ {:matcher => /^graph .*/, :klass => GraphGlobalDeclarationNode},
70
+ {:matcher => /^host_name .*/, :klass => HostNameGlobalDeclarationNode},
71
+ {:matcher => /^update .*/, :klass => UpdateGlobalDeclarationNode},
72
+ {:matcher => /^graph_period .*/, :klass => GraphPeriodGlobalDeclarationNode},
73
+ {:matcher => /^graph_vtitle .*/, :klass => GraphVTitleGlobalDeclarationNode},
74
+ {:matcher => /^service_order .*/, :klass => ServiceOrderGlobalDeclarationNode},
75
+ {:matcher => /^graph_width .*/, :klass => GraphWidthGlobalDeclarationNode},
76
+ {:matcher => /^graph_height .*/, :klass => GraphHeightGlobalDeclarationNode},
77
+ {:matcher => /^graph_printfformat .*/, :klass => GraphPrintFormatGlobalDeclarationNode},
78
+ {:matcher => /([\w_]+)\.label\ .*$/,:klass => LabelFieldPropertyNode},
79
+ {:matcher => /([\w_]+)\.cdef\ .*$/,:klass => CDefFieldPropertyNode},
80
+ {:matcher => /([\w_]+)\.draw\ .*$/,:klass => DrawFieldPropertyNode},
81
+ {:matcher => /([\w_]+)\.graph\ .*$/,:klass => GraphFieldPropertyNode},
82
+ {:matcher => /([\w_]+)\.info\ .*$/,:klass => InfoFieldPropertyNode},
83
+ {:matcher => /([\w_]+)\.extinfo\ .*$/,:klass => ExtInfoFieldPropertyNode},
84
+ {:matcher => /([\w_]+)\.max\ .*$/,:klass => MaxFieldPropertyNode},
85
+ {:matcher => /([\w_]+)\.min\ .*$/,:klass => MinFieldPropertyNode},
86
+ {:matcher => /([\w_]+)\.negative\ .*$/,:klass => NegativeFieldPropertyNode},
87
+ {:matcher => /([\w_]+)\.type\ .*$/,:klass => TypeFieldPropertyNode},
88
+ {:matcher => /([\w_]+)\.warning\ .*$/,:klass => WarningFieldPropertyNode},
89
+ {:matcher => /([\w_]+)\.critical\ .*$/,:klass => CriticalFieldPropertyNode},
90
+ {:matcher => /([\w_]+)\.colour\ .*$/,:klass => ColourFieldPropertyNode},
91
+ {:matcher => /([\w_]+)\.skipdraw\ .*$/,:klass => SkipDrawFieldPropertyNode},
92
+ {:matcher => /([\w_]+)\.sum\ .*$/,:klass => SumFieldPropertyNode},
93
+ {:matcher => /([\w_]+)\.stack\ .*$/,:klass => StackFieldPropertyNode},
94
+ {:matcher => /([\w_]+)\.linevalue\[:color\[:label\]\]\ .*$/,:klass => LineValueFieldPropertyNode},
95
+ {:matcher => /([\w_]+)\.oldname\ .*$/,:klass => OldNameFieldPropertyNode},
96
+ {:matcher => /([\w_]+)\.value\ .*$/,:klass => ValueFieldPropertyNode}
97
+ ]
98
+
99
+ def parse_config
100
+ @root = ASTNode.new("")
101
+ @root.parent = nil
102
+ current_node = @root
103
+ @raw_config.each_line do |line|
104
+ # For every line of config we match against every token
105
+ TOKENS.each do |token|
106
+ if line =~ token[:matcher]
107
+ # When we find a match...
108
+ if token[:klass].new("").is_a? FieldPropertyNode
109
+ # In Property field we have to set it to a FieldDeclarationNode (an artificial node grouping those fields)
110
+ if !current_node.is_a? FieldDeclarationNode
111
+ # A new FieldDeclaration has to ve created
112
+ node = FieldDeclarationNode.new("")
113
+ node.properties[:field_name] = $1
114
+ current_node.add_child node
115
+ current_node = node
116
+ elsif current_node.properties[:field_name] != $1
117
+ if (aux = @root.children_of_class(FieldDeclarationNode).find { |i| i.properties[:field_name] == $1 } )
118
+ current_node = aux
119
+ else
120
+ # We use the one declared before (note that different metrics could not be interlaced)
121
+ node = FieldDeclarationNode.new("")
122
+ node.properties[:field_name] = $1
123
+ current_node.parent.add_child node
124
+ current_node = node
125
+ end
126
+ end
127
+ current_node.add_child token[:klass].send("new",line)
128
+ else
129
+ @root.add_child token[:klass].send("new",line)
130
+ end
131
+ break
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,96 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "munin2graphite"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jose Fernandez (magec)"]
12
+ s.date = "2011-12-09"
13
+ s.description = "This gem will install as a daemon and can be used to connect to a graphite and a carbon backend. It will not only post the data for the metrics but also create graphs into graphite, by means of a translation from munin-node."
14
+ s.email = "jfernandezperez@gmail.com"
15
+ s.executables = ["munin2graphite", "munin2graphite-daemon"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.markdown"
19
+ ]
20
+ s.files = [
21
+ "Gemfile",
22
+ "LICENSE.txt",
23
+ "README.markdown",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bin/munin2graphite",
27
+ "bin/munin2graphite-daemon",
28
+ "conf/munin2graphite.conf.example",
29
+ "etc/munin2graphite/munin2graphite.conf.example",
30
+ "lib/ast_node.rb",
31
+ "lib/carbon.rb",
32
+ "lib/graphite.rb",
33
+ "lib/graphite/base.rb",
34
+ "lib/graphite/graph.rb",
35
+ "lib/graphite/metric.rb",
36
+ "lib/graphite/my_graph.rb",
37
+ "lib/graphite/user_graph.rb",
38
+ "lib/munin2graphite.rb",
39
+ "lib/munin2graphite/config.rb",
40
+ "lib/munin2graphite/scheduler.rb",
41
+ "lib/munin_graph.rb",
42
+ "munin2graphite.gemspec",
43
+ "test/munin2graphite/config_test.rb",
44
+ "test/test_config.rb",
45
+ "test/test_init.rb",
46
+ "test/test_munin.rb",
47
+ "test/test_munin_graph.rb",
48
+ "test/test_my_graph.rb",
49
+ "test/test_scheduler.rb"
50
+ ]
51
+ s.homepage = "http://github.com/magec/munin2graphite"
52
+ s.licenses = ["MIT"]
53
+ s.require_paths = ["lib"]
54
+ s.rubygems_version = "1.8.10"
55
+ s.summary = "Allows to post both data and graphic info from munin to graphite (https://launchpad.net/graphite)"
56
+ s.test_files = [
57
+ "test/munin2graphite/config_test.rb",
58
+ "test/test_config.rb",
59
+ "test/test_init.rb",
60
+ "test/test_munin.rb",
61
+ "test/test_munin_graph.rb",
62
+ "test/test_my_graph.rb",
63
+ "test/test_scheduler.rb"
64
+ ]
65
+
66
+ if s.respond_to? :specification_version then
67
+ s.specification_version = 3
68
+
69
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
70
+ s.add_runtime_dependency(%q<rufus-scheduler>, ["= 2.0.10"])
71
+ s.add_runtime_dependency(%q<daemons>, ["= 1.1.4"])
72
+ s.add_runtime_dependency(%q<parseconfig>, [">= 0"])
73
+ s.add_runtime_dependency(%q<munin-ruby>, ["~> 0.2.1"])
74
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
75
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
76
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
77
+ else
78
+ s.add_dependency(%q<rufus-scheduler>, ["= 2.0.10"])
79
+ s.add_dependency(%q<daemons>, ["= 1.1.4"])
80
+ s.add_dependency(%q<parseconfig>, [">= 0"])
81
+ s.add_dependency(%q<munin-ruby>, ["~> 0.2.1"])
82
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
83
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
84
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
85
+ end
86
+ else
87
+ s.add_dependency(%q<rufus-scheduler>, ["= 2.0.10"])
88
+ s.add_dependency(%q<daemons>, ["= 1.1.4"])
89
+ s.add_dependency(%q<parseconfig>, [">= 0"])
90
+ s.add_dependency(%q<munin-ruby>, ["~> 0.2.1"])
91
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
92
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
93
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
94
+ end
95
+ end
96
+