graphite-api 0.0.0.21

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # GraphiteAPI
2
+
3
+ A Ruby API toolkit for [Graphite](http://graphite.wikidot.com/)
4
+
5
+ * Graphite ruby client.
6
+ * Graphite middleware server, a lightweight, event-driven, aggregator daemon.
7
+
8
+ ## Why using it?
9
+ Written in ruby
10
+ Simple and light-width (only one gem dependency)
11
+ Comes with built-in middleware server
12
+
13
+ ## Client Usage
14
+ ```ruby
15
+ require 'graphite-api'
16
+
17
+ client = GraphiteAPI::Client.new(
18
+ :host => "graphite.example.com",
19
+ :port => 2003,
20
+ :prefix => ["example","prefix"], # add example.prefix to each key
21
+ :interval => 60 # send to graphite every 60 seconds
22
+ )
23
+
24
+ # Simple:
25
+ client.add_metrics("webServer.web01.loadAvg" => 10.7)
26
+ # => example.prefix.webServer.web01.loadAvg 10.7 time.now.stamp
27
+
28
+ # Multiple with time:
29
+ client.add_metrics({
30
+ "webServer.web01.loadAvg" => 10.7,
31
+ "webServer.web01.memUsage" => 40
32
+ },Time.at(1326067060))
33
+ # => example.prefix.webServer.web01.loadAvg 10.7 1326067060
34
+ # => example.prefix.webServer.web01.memUsage 40 1326067060
35
+
36
+ # Every 10 sec
37
+ client.every(10) do
38
+ client.add_metrics("webServer.web01.uptime" => `uptime`.split.first.to_i)
39
+ end
40
+
41
+ client.join # wait...
42
+ ```
43
+ ## Middleware Usage
44
+
45
+ `graphite-middleware --help`
46
+
47
+ ```
48
+ Graphite Middleware Server
49
+
50
+ Usage: graphite-middleware [options]
51
+ -g, --graphite HOST graphite host
52
+ -p, --port PORT listening port (default 2003)
53
+ -l, --log-file FILE log file
54
+ -L, --log-level LEVEL log level (default warn)
55
+ -P, --pid-file FILE pid file (default /var/run/graphite-middleware.pid)
56
+ -d, --daemonize run in background
57
+ -i, --interval INT report every X seconds (default 60)
58
+ -s, --slice SECONDS send to graphite in X seconds slices (default is 60)
59
+ -c, --cache HOURS cache expiration time in hours (default is 12 hours)
60
+ ```
61
+
62
+ ## Installation
63
+ install the latest from github
64
+
65
+ ```
66
+ git clone git://github.com/kontera-technologies/graphite-api.git
67
+ cd graphite-api
68
+ rake install
69
+ ```
70
+
71
+ ## Bugs
72
+
73
+ If you find a bug, feel free to report it @ our [issues tracker](https://github.com/kontera-technologies/graphite-api/issues) on github.
74
+
75
+ ## License
76
+
77
+ It is free software, and may be redistributed under the terms specified in [LICENSE](https://github.com/kontera-technologies/graphite-api/blob/master/LICENSE).
78
+
79
+ ## Warranty
80
+ This software is provided “as is” and without any express or implied warranties, including, without limitation, the implied warranties of merchantability and fitness for a particular purpose.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ Dir.chdir File.dirname __FILE__
3
+
4
+ require 'graphite-api'
5
+ require 'bundler/setup'
6
+
7
+ def msg m
8
+ $stderr.puts "[*] #{m}"
9
+ end
10
+
11
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.join(File.dirname(__FILE__), '..','lib')
3
+ require 'graphite-api'
4
+
5
+ GraphiteAPI::Runner.new(ARGV).run
@@ -0,0 +1,18 @@
1
+ module GraphiteAPI
2
+ ROOT = File.expand_path(File.dirname(__FILE__))
3
+
4
+ autoload :Version, "#{ROOT}/graphite-api/version"
5
+ autoload :Client, "#{ROOT}/graphite-api/client"
6
+ autoload :Scheduler, "#{ROOT}/graphite-api/scheduler"
7
+ autoload :Connector, "#{ROOT}/graphite-api/connector"
8
+ autoload :Middleware, "#{ROOT}/graphite-api/middleware"
9
+ autoload :Runner, "#{ROOT}/graphite-api/runner"
10
+ autoload :Utils, "#{ROOT}/graphite-api/utils"
11
+ autoload :Buffer, "#{ROOT}/graphite-api/buffer"
12
+ autoload :Logger, "#{ROOT}/graphite-api/logger"
13
+
14
+ def self.version
15
+ GraphiteAPI::Version.string
16
+ end
17
+
18
+ end
@@ -0,0 +1,110 @@
1
+ # -----------------------------------------------------
2
+ # Buffer Object
3
+ # Handle Socket & Client data streams
4
+ # -----------------------------------------------------
5
+ # Usage:
6
+ # buff = GraphiteAPI::Buffer.new(GraphiteAPI::Utils.default_options)
7
+ # buff << {:metric => {"load_avg" => 10},:time => Time.now}
8
+ # buff << {:metric => {"load_avg" => 30},:time => Time.now}
9
+ # buff.stream "mem.usage 1"
10
+ # buff.stream "90 1326842563\n"
11
+ # buff.stream "shuki.tuki 999 1326842563\n"
12
+ # buff.each {|o| p o}
13
+ #
14
+ # Produce:
15
+ # ["load_avg", 40.0, 1326881160]
16
+ # ["mem.usage", 190.0, 1326842520]
17
+ # ["shuki.tuki", 999.0, 1326842520]
18
+ # -----------------------------------------------------
19
+ module GraphiteAPI
20
+ class Buffer
21
+ attr_reader :leftovers,:options,:new_records,:in_cache_mode
22
+
23
+ def initialize(options)
24
+ @options = options
25
+ @leftovers = Hash.new {|h,k| h[k] = Array.new}
26
+ @new_records = []
27
+ @in_cache_mode = !options[:cache_exp].nil?
28
+ start_cleaner if in_cache_mode
29
+ end
30
+
31
+ def << hash
32
+ time = Utils.normalize_time(hash[:time],options[:slice])
33
+ hash[:metric].each do |k,v|
34
+ buffer[time][k] += v.to_f
35
+ new_records << [time,k]
36
+ end
37
+ end
38
+
39
+ def stream(data,client_id = nil)
40
+ got_leftovers = data[-1,1] != "\n"
41
+ data = data.split(/\n/)
42
+ unless leftovers[client_id].empty?
43
+ if (valid leftovers[client_id].last + data.first rescue nil)
44
+ data.unshift(leftovers[client_id].pop + data.shift)
45
+ end
46
+ leftovers[client_id].clear
47
+ end
48
+
49
+ leftovers[client_id] << data.pop if got_leftovers
50
+ data.each do |line|
51
+ next unless valid line
52
+ key,val,time = line.split
53
+ self << {:metric => {key => val},:time => (Time.at(time.to_i) rescue Time.now)}
54
+ end
55
+ end
56
+
57
+ def each
58
+ new_records.uniq.each do |time,key|
59
+ yield [prefix + key,buffer[time][key],time]
60
+ end and clear
61
+ end
62
+
63
+ def empty?
64
+ buffer.empty?
65
+ end
66
+
67
+ def got_new_records?
68
+ !new_records.empty?
69
+ end
70
+
71
+ def size
72
+ buffer.values.map(&:values).flatten.size
73
+ end
74
+
75
+ private
76
+ def clear
77
+ new_records.clear
78
+ buffer.clear unless in_cache_mode
79
+ end
80
+
81
+ def valid(data)
82
+ data =~ /^[\w|\.]+ \d+(?:\.|\d)* \d+$/
83
+ end
84
+
85
+ def prefix
86
+ @prefix ||= options[:prefix].empty? ? String.new : prefix_to_s
87
+ end
88
+
89
+ def prefix_to_s
90
+ [options[:prefix]].flatten.join('.') << "."
91
+ end
92
+
93
+ def buffer
94
+ @buffer ||= Hash.new {|h,k| h[k] = Hash.new {|h1,k1| h1[k1] = 0}}
95
+ end
96
+
97
+ def clean(age)
98
+ [buffer,new_records].each {|o| o.delete_if {|t,k| now - t > age}}
99
+ end
100
+
101
+ def now
102
+ Time.now.to_i
103
+ end
104
+
105
+ def start_cleaner
106
+ Scheduler.every(options[:cleaner_interval]) { clean options[:cache_exp] }
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,70 @@
1
+ # -----------------------------------------------------
2
+ # Graphite Client
3
+ # Send metrics to graphite (or to some kind of middleware/proxy)
4
+ # -----------------------------------------------------
5
+ # Usage
6
+ #
7
+ # client = GraphiteAPI::Client.new(
8
+ # :host => "graphite.example.com",
9
+ # :port => 2003,
10
+ # :prefix => ["example","prefix"], # add example.prefix to each key
11
+ # :interval => 60 # send to graphite every 60 seconds
12
+ # )
13
+ #
14
+ # # Simple:
15
+ # client.add_metrics("webServer.web01.loadAvg" => 10.7)
16
+ # # => example.prefix.webServer.web01.loadAvg 10.7 time.now.stamp
17
+ #
18
+ # # Multiple with time:
19
+ # client.add_metrics({
20
+ # "webServer.web01.loadAvg" => 10.7,
21
+ # "webServer.web01.memUsage" => 40
22
+ # },Time.at(1326067060))
23
+ # # => example.prefix.webServer.web01.loadAvg 10.7 1326067060
24
+ # # => example.prefix.webServer.web01.memUsage 40 1326067060
25
+ #
26
+ # # Every 10 sec
27
+ # client.every(10) do
28
+ # client.add_metrics("webServer.web01.uptime" => `uptime`.split.first.to_i)
29
+ # end
30
+ #
31
+ # client.join # wait...
32
+ # -----------------------------------------------------
33
+ module GraphiteAPI
34
+ class Client
35
+ attr_reader :options,:buffer,:connector
36
+
37
+ def initialize(opt)
38
+ @options = GraphiteAPI::Utils.default_options.merge opt
39
+ @buffer = GraphiteAPI::Buffer.new(options)
40
+ @connector = GraphiteAPI::Connector.new(*options.values_at(:host,:port))
41
+ start_scheduler
42
+ end
43
+
44
+ def add_metrics(m,time = Time.now)
45
+ buffer << {:metric => m, :time => time}
46
+ end
47
+
48
+ def join
49
+ sleep 1 while buffer.got_new_records?
50
+ end
51
+
52
+ def stop
53
+ Scheduler.stop
54
+ end
55
+
56
+ def every(frequency,&block)
57
+ Scheduler.every(frequency,&block)
58
+ end
59
+
60
+ protected
61
+ def start_scheduler
62
+ Scheduler.every(options[:interval]) {send_metrics}
63
+ end
64
+
65
+ def send_metrics
66
+ buffer.each {|arr| connector.puts arr.join(" ")}
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,41 @@
1
+ # -----------------------------------------------------
2
+ # TCP Socket connection
3
+ # -----------------------------------------------------
4
+ # Usage:
5
+ # connector = GraphiteAPI::Connector.new("localhost",2003)
6
+ # connector.puts("my.metric 1092 1232123231")
7
+ #
8
+ # Socket:
9
+ # => my.metric 1092 1232123231\n
10
+ # -----------------------------------------------------
11
+ require 'socket'
12
+ module GraphiteAPI
13
+ class Connector
14
+ attr_reader :options
15
+
16
+ def initialize(host,port)
17
+ @host = host
18
+ @port = port
19
+ end
20
+
21
+ def puts(msg)
22
+ begin
23
+ Logger.debug msg
24
+ socket.puts(msg)
25
+ rescue Errno::EPIPE
26
+ @socket = nil
27
+ retry
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def socket
34
+ if @socket.nil? || @socket.closed?
35
+ @socket = TCPSocket.new(@host,@port)
36
+ end
37
+ @socket
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,18 @@
1
+ # -----------------------------------------------------
2
+ # GraphiteAPI Logger
3
+ # -----------------------------------------------------
4
+ # Usage:
5
+ # Graphite::Logger.logger = ::Logger.new(STDOUT)
6
+ # Graphite::Logger.info "shuki tuki"
7
+ # Graphite::Logger.debug "hihi"
8
+ # -----------------------------------------------------
9
+ module GraphiteAPI
10
+ class Logger
11
+ class << self
12
+ attr_accessor :logger
13
+ def method_missing(m,*args,&block)
14
+ if logger.respond_to? m then logger.send(m,*args,&block) end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,74 @@
1
+ # -----------------------------------------------------
2
+ # Graphite Middleware Server
3
+ # Should be placed between graphite server and graphite clients
4
+ # - Data Aggregator
5
+ # - Caching
6
+ # - Data Manipulation
7
+ # -----------------------------------------------------
8
+ # Usage:
9
+ # GraphiteAPI::Middleware.start(options)
10
+ #
11
+ # Options:
12
+ # graphite_host target graphite hostname
13
+ # graphite_port target graphite listening port (default 2003)
14
+ # cache_exp cache lifetime in seconds (default is 43200 seconds)
15
+ # prefix add prefix to each key
16
+ # interval report to graphite every X seconds (default is 60)
17
+ # slice send to graphite in X seconds slices (default is 60)
18
+ # log_level info # TODO: move this to runner.rb
19
+ # -----------------------------------------------------
20
+ require 'rubygems'
21
+ require 'eventmachine'
22
+ require 'logger'
23
+ require 'socket'
24
+
25
+ module GraphiteAPI
26
+ class Middleware < EventMachine::Connection
27
+
28
+ attr_reader :logger,:buffer,:client_id
29
+
30
+ def initialize(logger,buffer)
31
+ @logger = logger
32
+ @buffer = buffer
33
+ super
34
+ end
35
+
36
+ def post_init
37
+ logger.debug "Client connecting"
38
+ @client_id = Socket.unpack_sockaddr_in(get_peername).join(":")
39
+ end
40
+
41
+ def receive_data(data)
42
+ buffer.stream(data,client_id)
43
+ end
44
+
45
+ def unbind
46
+ logger.debug "Client disconnecting"
47
+ end
48
+
49
+ def self.start(options)
50
+ EventMachine.run do
51
+ # Resources
52
+ GraphiteAPI::Logger.logger = ::Logger.new(options[:log_file] || STDOUT)
53
+ GraphiteAPI::Logger.level = eval "::Logger::#{options[:log_level].to_s.upcase}"
54
+
55
+ buffer = GraphiteAPI::Buffer.new(options)
56
+ connector = GraphiteAPI::Connector.new(*options.values_at(:graphite_host,:graphite_port))
57
+
58
+ # Starting server
59
+ EventMachine.start_server('0.0.0.0',options[:listening_port],self,GraphiteAPI::Logger.logger,buffer)
60
+ GraphiteAPI::Logger.info "Server running on port #{options[:listening_port]}"
61
+
62
+ # Send metrics to graphite every X seconds
63
+ GraphiteAPI::Scheduler.every(options[:interval]) do
64
+ if buffer.got_new_records?
65
+ Logger.debug "Sending #{buffer.size} records to graphite (@#{options[:graphite_host]}:#{options[:graphite_port]})"
66
+ buffer.each { |arr| connector.puts arr.join(" ") }
67
+ end # if got_new_records?
68
+ end # every
69
+ end # run
70
+ end # start
71
+ end # Middleware
72
+ end # GraphiteAPI
73
+ #require File.dirname(__FILE__) + "/../graphite-api"
74
+ #GraphiteAPI::Middleware.start(GraphiteAPI::Utils.default_options)
@@ -0,0 +1,69 @@
1
+ require 'optparse'
2
+
3
+ module GraphiteAPI
4
+ class Runner
5
+ attr_reader :options
6
+
7
+ def initialize(argv)
8
+ parser.parse! argv
9
+ validate_options
10
+ end
11
+
12
+ def run
13
+ if options[:daemonize]
14
+ fork do
15
+ Process.setsid
16
+ exit if fork
17
+ Dir.chdir('/tmp')
18
+ STDOUT.reopen('/dev/null','a')
19
+ STDIN.reopen('/dev/null')
20
+ STDERR.reopen('/dev/null','a')
21
+ write_pid
22
+ run!
23
+ end
24
+ else
25
+ run!
26
+ end
27
+ end
28
+
29
+ private
30
+ def options
31
+ @options ||= Utils.default_options
32
+ end
33
+
34
+ def write_pid
35
+ begin
36
+ File.open(options[:pid], 'w') { |f| f.write(Process.pid) }
37
+ rescue Exception
38
+ end
39
+ end
40
+
41
+ def run!
42
+ GraphiteAPI::Middleware.start(options)
43
+ end
44
+
45
+ def validate_options
46
+ abort "You must specify graphite host" if options[:graphite_host].nil?
47
+ end
48
+
49
+ def parser
50
+ OptionParser.new do |opts|
51
+ opts.banner = "Graphite Middleware Server"
52
+ opts.define_head "Usage: graphite-middleware [options]"
53
+ opts.define_head ""
54
+ opts.on("-g", "--graphite HOST","graphite host") {|v| options[:graphite_host] = v}
55
+ opts.on("-p", "--port PORT","listening port (default 2003)"){|v| options[:listening_port] = v}
56
+ opts.on("-l", "--log-file FILE","log file") {|v| options[:log_file] = File.expand_path(v)}
57
+ opts.on("-L", "--log-level LEVEL","log level (default warn)") {|v|options[:log_level] = v}
58
+ opts.on("-P", "--pid-file FILE","pid file (default /var/run/graphite-middleware.pid)"){|v|options[:pid] = v}
59
+ opts.on("-d", "--daemonize","run in background"){options[:daemonize] = true}
60
+ opts.on("-i", "--interval INT","report every X seconds (default 60)"){|v|options[:interval] = v.to_i unless v.to_i == 0}
61
+ opts.on("-s", "--slice SECONDS","send to graphite in X seconds slices (default is 60)") {|v| options[:slice] = v.to_i unless v.to_i == 0}
62
+ opts.on("-c", "--cache HOURS","cache expiration time in hours (default is 12 hours)") {|v| (options[:cache_exp] = v.to_i * 3600) unless v.to_i == 0}
63
+ opts.define_tail ""
64
+ opts.define_tail ""
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'eventmachine'
3
+
4
+ module GraphiteAPI
5
+ class Scheduler
6
+ @@wrapper = nil
7
+ @@timers = []
8
+
9
+ class << self
10
+ def every(frequency,&block)
11
+ reactor_running? or start_reactor
12
+ timers << EventMachine::PeriodicTimer.new(frequency) { yield }
13
+ timers.last
14
+ end
15
+
16
+ def stop
17
+ timers.map(&:cancel)
18
+ wrapper and EventMachine.stop
19
+ end
20
+
21
+ def join
22
+ wrapper and wrapper.join
23
+ end
24
+
25
+ private
26
+ def start_reactor
27
+ @@wrapper = Thread.new { EventMachine.run }
28
+ wrapper.abort_on_exception = true
29
+ Thread.pass until reactor_running?
30
+ end
31
+
32
+ def reactor_running?
33
+ EventMachine.reactor_running?
34
+ end
35
+
36
+ def wrapper;@@wrapper end
37
+ def timers; @@timers end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module GraphiteAPI
2
+ module Utils
3
+ module_function
4
+
5
+ def normalize_time(time,slice = 60)
6
+ ((time || Time.now).to_i / slice * slice).to_i
7
+ end
8
+
9
+ def default_options
10
+ {
11
+ :cleaner_interval => 43200,
12
+ :graphite_port => 2003,
13
+ :listening_port => 2003,
14
+ :log_level => :info,
15
+ :cache_exp => nil,
16
+ :host => "localhost",
17
+ :port => 2003,
18
+ :prefix => [],
19
+ :interval => 60,
20
+ :slice => 60,
21
+ :pid => "/var/run/graphite-middleware.pid"
22
+ }
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module GraphiteAPI
2
+ class Version
3
+ PFILE = File.join(GraphiteAPI::ROOT,"..",".pre_version")
4
+ class << self
5
+ def string
6
+ [0,0,0,pre].join(".")
7
+ end
8
+
9
+ def increment_pre
10
+ new_version = pre + 1
11
+ File.open(PFILE,"w") { |f| f.puts new_version }
12
+ end
13
+
14
+ private
15
+ def pre
16
+ File.read(PFILE).to_i
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
data/tasks/build.rake ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems/package_task'
2
+
3
+ GraphiteAPI::GemSpec = Gem::Specification.new do |s|
4
+ s.name = "graphite-api"
5
+ s.version = GraphiteAPI.version
6
+ s.platform = Gem::Platform::RUBY
7
+ s.summary = "GraphiteAPI"
8
+ s.description = "GraphiteAPI - Graphite API tools"
9
+ s.author = "Eran Levi"
10
+ s.email = 'eran@kontera.com'
11
+ s.homepage = 'http://www.kontera.com'
12
+ s.executables = %w(graphite-middleware)
13
+ s.required_ruby_version = '>= 1.8.7'
14
+ s.rubyforge_project = "graphite-api"
15
+ s.files = %w(README.md Rakefile) + Dir.glob("{bin,lib,test,tasks}/**/*")
16
+ s.require_path = "lib"
17
+ s.bindir = "bin"
18
+
19
+ s.add_dependency 'eventmachine','>= 0.3.3'
20
+ end
21
+
22
+ task :gem => [:clobber_package]
23
+ Gem::PackageTask.new(GraphiteAPI::GemSpec) do |p|
24
+ p.gem_spec = GraphiteAPI::GemSpec
25
+ end
26
+
27
+ task :install => [:gem] do
28
+ sh "gem install pkg/graphite-api"
29
+ Rake::Task['clobber_package'].execute
30
+ end
31
+
32
+ namespace :gem do
33
+ desc "Update GraphiteAPI gem version"
34
+ task :update_version do
35
+ GraphiteAPI::Version.increment_pre
36
+ msg "Incrementing version to #{GraphiteAPI::Version.string}..."
37
+ end
38
+
39
+ desc "Upload GraphiteAPI to Kontera's repo"
40
+ task :upload => [:build] do
41
+ sh "gem inabox --host http://gems.kontera.com pkg/graphite-api-#{GraphiteAPI.version}.gem"
42
+ end
43
+
44
+ desc "Update GraphiteAPI gem version and build gem"
45
+ task :build => [:test,:update_version] do
46
+ sh "rake gem"
47
+ end
48
+
49
+ end
data/tasks/tests.rake ADDED
@@ -0,0 +1,3 @@
1
+ task :test do
2
+ # tests here
3
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: graphite-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0.21
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eran Levi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-27 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: eventmachine
16
+ requirement: &2152684380 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.3.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2152684380
25
+ description: GraphiteAPI - Graphite API tools
26
+ email: eran@kontera.com
27
+ executables:
28
+ - graphite-middleware
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - README.md
33
+ - Rakefile
34
+ - bin/graphite-middleware
35
+ - lib/graphite-api/buffer.rb
36
+ - lib/graphite-api/client.rb
37
+ - lib/graphite-api/connector.rb
38
+ - lib/graphite-api/logger.rb
39
+ - lib/graphite-api/middleware.rb
40
+ - lib/graphite-api/runner.rb
41
+ - lib/graphite-api/scheduler.rb
42
+ - lib/graphite-api/utils.rb
43
+ - lib/graphite-api/version.rb
44
+ - lib/graphite-api.rb
45
+ - tasks/build.rake
46
+ - tasks/tests.rake
47
+ homepage: http://www.kontera.com
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: 1.8.7
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project: graphite-api
67
+ rubygems_version: 1.8.13
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: GraphiteAPI
71
+ test_files: []