graphite-api 0.0.0.21

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/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: []