graphite-api-middleware 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2d8f0e57a178f384b38405f15f092e986e88fa5585055cdbe65e893da2db4fa4
4
+ data.tar.gz: b278408d5aab2272821259e5f3dc3a4d03e4b63b74ccdc0f69adcef5ba64c4e8
5
+ SHA512:
6
+ metadata.gz: 2e21491fcc8861de88a3b1756da647302aaf0fea3f7bcdf6d87361a6027abf4b82e0a584d857a6e589c567d33d5d55ceff739f6b25c511160257c0fcfb1c9cd2
7
+ data.tar.gz: 5a04645a1a4531549134266d76cae67d5777dd35d23a4cbfb4f068ae8a337c25a02c56dfde05506470dcb054362afb250fc9d5b512aa7561c92828205269e616
data/LICENSE.txt ADDED
@@ -0,0 +1,11 @@
1
+ This program is free software: you can redistribute it and/or modify
2
+ it under the terms of the GNU Lesser General Public License V3 as published by
3
+ the Free Software Foundation.
4
+
5
+ This program is distributed in the hope that it will be useful,
6
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
7
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8
+ GNU Lesser General Public License for more details.
9
+
10
+ You should have received a copy of the GNU Lesser General Public License
11
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # Description
2
+ **GraphiteAPI Middleware** provides a way to interacting with **Graphite's Carbon Daemon**, by setting up the **GraphiteAPI-Middleware** daemon. This method implements Graphite's [plaintext protocol](http://graphite.readthedocs.org/en/1.0/feeding-carbon.html) for communication.
3
+
4
+ ## Key Features
5
+ * **Multiple Graphite Servers Support** - GraphiteAPI-Middleware supports sending aggregated data to multiple graphite servers, in a multiplex fashion, useful for large data centers and backup purposes
6
+ * **Reanimation mode** - support cases which the same keys (same timestamps as well) can be received simultaneously and asynchronously from multiple input sources, in these cases GraphiteAPI-Middleware will "reanimate" old records (records that were already sent to Graphite server), and will send the sum of the reanimated record value + the value of the record that was just received to the graphite server; this new summed record should override the key with the new value on Graphite database.
7
+ * **non-blocking I/O** ( EventMachine aware ).
8
+ * **Thread-Safe** client.
9
+
10
+ ## Status
11
+ [![Gem Version](https://badge.fury.io/rb/graphite-api-middleware.svg)](https://badge.fury.io/rb/graphite-api-middleware)
12
+ [![Build Status](https://travis-ci.org/kontera-technologies/graphite-api-middleware.svg?branch=master)](https://travis-ci.org/kontera-technologies/graphite-api-middleware)
13
+ [![Test Coverage](https://codecov.io/gh/kontera-technologies/graphite-api-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/kontera-technologies/graphite-api-middleware)
14
+
15
+ ## Installation
16
+ Install stable version
17
+
18
+ ```
19
+ gem install graphite-api-middleware
20
+ ```
21
+
22
+ ## Usage
23
+ * After installing this gem, the `graphite-api-middleware` command should be available.
24
+ ```
25
+ workspace $ graphite-api-middleware -h
26
+ GraphiteAPI Middleware Server
27
+ Usage:
28
+ graphite-api-middleware <graphite-uri>...
29
+ [-d | --daemonize]
30
+ [-p=<port> | --port=<port>]
31
+ [-l=<log-file> | --log-file=<log-file>]
32
+ [-L=<log-level> | --log-level=<log-leve>]
33
+ [-P=<pid-file> | --pid-file=<pid-file>]
34
+ [-i=<interval> | --interval=<interval>]
35
+ [-s=<slice> | --slice=<slice>]
36
+ [-r=<reanimation> | --reanimation=<reanimation>]
37
+ [-m=<aggregation-method> | --aggregation-method=<aggregation-method>]
38
+ graphite-api-middleware -v | --version
39
+ graphite-api-middleware -h | --help
40
+
41
+
42
+ Arguments:
43
+ <graphite-uri> List of URIs (seperated by spaces) that point to graphite API servers [udp,tcp]://host:port
44
+
45
+ Options:
46
+ -h, --help Show this screen.
47
+ -v, --version Show version.
48
+ -d, --daemonize Run as a daemon.
49
+ -p=<port>, --port=<port> Listening port for this server.
50
+ -l=<log-file>, --log-file=<log-file> Listening port for this server.
51
+ -L=<log-level>, --log-level=<log-level> Log level (defaults to warn).
52
+ -P=<pid-file>, --pid-file=<pid-file> Path to the PID to use (defaults to /var/run/graphite-api-middleware.pid).
53
+ -i=<interval>, --interval=<interval> The interval to wait between each report (defaults to 60).
54
+ -s=<slice>, --slice=<slice> This middleware will send reports to graphite in slices of X seconds (defaults to 60).
55
+ -r=<reanimation>, --reanimation=<reanimation> Reanimate records that are younger than X hours, please see README.
56
+ -m=<aggregation-method>, --aggregation-method=<aggregation-method> The aggregation method (sum, avg or replace) for multiple reports in the same time slice (defaults to s
57
+ um).
58
+
59
+ More Info @ https://github.com/kontera-technologies/graphite-api-middleware
60
+ ```
61
+
62
+ * launch **GraphiteAPI-Middleware** daemon
63
+ ```
64
+ workspace $ graphite-api-middleware graphite-server:2003 graphite-backup-server:2003 \
65
+ --port 2005 \
66
+ --interval 60 \
67
+ --log-level debug \
68
+ --log-file /tmp/graphite-api-middleware.out \
69
+ --daemonize
70
+ ```
71
+
72
+ * Send metrics via **UDP/TCP sockets**
73
+ ```
74
+ workspace $ telnet localhost 2005
75
+ Trying 127.0.0.1...
76
+ Connected to localhost.
77
+ Escape character is '^]'.
78
+ example.middleware.value 10.2 1335008343
79
+ example.middleware.value2 99 1334929231
80
+ ^C
81
+ workspace $
82
+ ```
83
+
84
+ ## Example Setup
85
+ ![example setup](/examples/middleware_t1.png)
86
+
87
+ ## Development
88
+ After checking out the repo, run `bundle install` to install dependencies.
89
+ Before submitting a pull request, run `rake test` to run the tests.
90
+
91
+ To install this gem onto your local machine, run `bundle exec rake install`.
92
+
93
+ ### Releasing a new version of this gem
94
+ 1. Run `gem bump -v [major|minor|patch|alpha|beta|pre]` to bump the version number of this gem and create a new git commit for it.
95
+ 2. Run `git push` to push the changes.
96
+ 3. Run `gem tag` to create a git tag for this version.
97
+ 4. Run `git push --tags` to push the tag to git.
98
+ 5. Run `gem release` to build the gem and push it to rubygems.
99
+
100
+ ## Contributing
101
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Eyal_Shalev/graphite-api-middleware. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
102
+
103
+ ## Bugs
104
+ If you find a bug, feel free to report it @ our [issues tracker](https://github.com/kontera-technologies/graphite-api-middleware/issues) on github.
105
+
106
+ ## License
107
+ It is free software, and may be redistributed under the terms specified in [LICENSE](/LICENSE.txt).
108
+
109
+ ## Code of Conduct
110
+ Everyone interacting in the graphite-api-middleware project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
111
+
112
+ ## Warranty
113
+ 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,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib',__FILE__)
3
+
4
+ require 'graphite-api-middleware'
5
+ require 'docopt'
6
+
7
+ FILE_NAME = File.basename(__FILE__)
8
+ options = GraphiteApiMiddleware::Server.default_options
9
+
10
+ doc = <<DOCOPT
11
+ Graphite API Middleware Server
12
+ Usage:
13
+ #{FILE_NAME} <graphite-uri>...
14
+ [-d | --daemonize]
15
+ [-p=<port> | --port=<port>]
16
+ [-l=<log-file> | --log-file=<log-file>]
17
+ [-L=<log-level> | --log-level=<log-leve>]
18
+ [-P=<pid-file> | --pid-file=<pid-file>]
19
+ [-i=<interval> | --interval=<interval>]
20
+ [-s=<slice> | --slice=<slice>]
21
+ [-r=<reanimation> | --reanimation=<reanimation>]
22
+ [-m=<aggregation-method> | --aggregation-method=<aggregation-method>]
23
+ #{FILE_NAME} -v | --version
24
+ #{FILE_NAME} -h | --help
25
+
26
+ Arguments:
27
+ <graphite-uri> List of URIs (seperated by spaces) that point to graphite API servers [udp,tcp]:\/\/host:port
28
+
29
+ Options:
30
+ -h, --help Show this screen.
31
+ -v, --version Show version.
32
+ -d, --daemonize Run as a daemon.
33
+ -p=<port>, --port=<port> Listening port for this server.
34
+ -l=<log-file>, --log-file=<log-file> Listening port for this server.
35
+ -L=<log-level>, --log-level=<log-level> Log level (defaults to warn).
36
+ -P=<pid-file>, --pid-file=<pid-file> Path to the PID to use (defaults to #{options[:pid]}).
37
+ -i=<interval>, --interval=<interval> The interval to wait between each report (defaults to #{options[:interval]}).
38
+ -s=<slice>, --slice=<slice> This middleware will send reports to graphite in slices of X seconds (defaults to #{options[:slice]}).
39
+ -r=<reanimation>, --reanimation=<reanimation> Reanimate records that are younger than X hours, please see README.
40
+ -m=<aggregation-method>, --aggregation-method=<aggregation-method> The aggregation method (sum, avg or replace) for multiple reports in the same time slice (defaults to #{options[:default_aggregation_method]}).
41
+
42
+ More Info @ https://github.com/kontera-technologies/graphite-api-middleware
43
+ DOCOPT
44
+
45
+ begin
46
+ opts = Docopt::docopt(doc)
47
+
48
+ if opts["--version"]
49
+ puts "GraphiteAPI Middleware #{GraphiteApiMiddleware::VERSION}"
50
+ exit 0
51
+ end
52
+
53
+ raise "Invalid aggregation method. Valid values are sum, avg or replace." unless ["sum", "avg", "replace", nil].include? opts["--aggregation-method"]
54
+
55
+ options[:backends] = opts["<graphite-uri>"]
56
+ options[:port] = opts["--port"] if opts["--port"]
57
+ options[:log_file] = File::expand_path opts["--log-file"] if opts["--log-file"]
58
+ options[:log_level] = opts["--log-level"] if opts["--log-level"]
59
+ options[:pid] = opts["<pid>"] if opts["<pid>"]
60
+ options[:daemonize] = opts["--daemonize"]
61
+ options[:interval] = opts["--interval"].to_i if opts["--interval"].to_i > 0
62
+ options[:slice] = opts["--slice"].to_i if opts["--slice"].to_i > 0
63
+ options[:cache] = opts["--cache"].to_i * 3600 if opts["--cache"].to_i > 0
64
+ options[:default_aggregation_method] = opts["--aggregation-method"].to_sym if opts["--aggregation-method"]
65
+
66
+ logger = Logger.new options[:log_file] || STDOUT
67
+ logger.level= Logger.const_get options[:log_level].to_s.upcase
68
+ Process.daemon if options[:daemonize]
69
+ GraphiteApiMiddleware::Server.start options, logger
70
+ rescue Docopt::Exit => e
71
+ puts e.message
72
+ rescue Interrupt
73
+ logger.info "Shutting down..."
74
+ Zscheduler.stop
75
+ rescue StandardError => e
76
+ puts (Docopt::Exit.new e.message).message
77
+ end
@@ -0,0 +1,3 @@
1
+ module GraphiteAPIMiddleware
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,82 @@
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
+ # GraphiteApiMiddleware::Server.start(options)
10
+ #
11
+ # Options:
12
+ # graphite target graphite hostname
13
+ # reanimation_exp cache lifetime in seconds (default is 43200 seconds)
14
+ # prefix add prefix to each key
15
+ # interval report to graphite every X seconds (default is 60)
16
+ # slice send to graphite in X seconds slices (default is 60)
17
+ # log_level info
18
+ # -----------------------------------------------------
19
+ require "graphite-api-middleware/version"
20
+ require 'graphite-api'
21
+ require 'eventmachine'
22
+ require 'socket'
23
+ require 'logger'
24
+
25
+ module GraphiteApiMiddleware
26
+ class Server < EventMachine::Connection
27
+
28
+ def initialize buffer, logger
29
+ @buffer = buffer and super
30
+ @logger = logger
31
+ end
32
+
33
+ attr_reader :buffer, :client_id
34
+
35
+ def post_init
36
+ @client_id = peername
37
+ @logger.debug [:middleware, :connecting, client_id]
38
+ end
39
+
40
+ def receive_data data
41
+ @logger.debug [:middleware, :message, client_id, data]
42
+ buffer.stream data, client_id
43
+ end
44
+
45
+ def unbind
46
+ @logger.debug [:middleware, :disconnecting, client_id]
47
+ end
48
+
49
+ def peername
50
+ port, *ip = get_peername[2,6].unpack "nC4"
51
+ [ip.join("."),port].join ":"
52
+ end
53
+
54
+ private :peername
55
+
56
+ def self.default_options
57
+ GraphiteAPI::Client.default_options.merge interval: 60, pid: '/var/run/graphite-api-middleware.pid'
58
+ end
59
+
60
+ def self.start options, logger
61
+ EventMachine.run do
62
+ GraphiteAPI::Logger.logger = logger
63
+ logger.info "Server running on port #{options[:port]}"
64
+
65
+ buffer = GraphiteAPI::Buffer.new options
66
+ group = GraphiteAPI::Connector::Group.new options
67
+
68
+ # Starting server
69
+ [:start_server, :open_datagram_socket].each do |m|
70
+ EventMachine.send(m, '0.0.0.0', options[:port], self, buffer, logger)
71
+ end
72
+
73
+ # Send metrics to graphite every X seconds
74
+ Zscheduler.every(options[:interval], :on_shutdown => true) do
75
+ group.publish buffer.pull :string if buffer.new_records?
76
+ end
77
+
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,86 @@
1
+ require "test_helper"
2
+ require 'eventmachine'
3
+ require 'socket'
4
+
5
+ module GraphiteApiMiddleware::Tests
6
+ class MiddlewareSanityTest < TestCase
7
+ EM_STOP_AFTER = 4
8
+ MIDDLEWARE_STARTUP_WAIT = 1
9
+ MIDDLEWARE_STOP_WAIT = 1
10
+ MIDDLEWARE_BIN_FILE = File.expand_path("../../../bin/graphite-api-middleware", __FILE__)
11
+
12
+ def setup
13
+ @middleware_port = Utils.random_non_repeating_port
14
+ @mock_server_port = Utils.random_non_repeating_port
15
+ @data = []
16
+ Utils.stop_em_if_running
17
+ end
18
+
19
+ def start_middleware middleware_port, mock_server_port, aggregation_method=nil, interval=2
20
+ options = %W(tcp://localhost:#{mock_server_port} --port #{middleware_port} --interval #{interval} -L error)
21
+ options += ["--aggregation-method", aggregation_method] if aggregation_method
22
+ @pid = Process.spawn("ruby", MIDDLEWARE_BIN_FILE, *options)
23
+ sleep MIDDLEWARE_STARTUP_WAIT
24
+ end
25
+
26
+ def teardown
27
+ Process.kill(:KILL, @pid)
28
+ sleep MIDDLEWARE_STOP_WAIT
29
+ end
30
+
31
+ def test_with_defaults
32
+ start_middleware @middleware_port, @mock_server_port
33
+ EventMachine.run {
34
+ EventMachine.start_server("0.0.0.0", @mock_server_port, MockServer, @data)
35
+ socket = TCPSocket.new("0.0.0.0", @middleware_port)
36
+ 1.upto(1000) do
37
+ socket.puts("shuki.tuki1 1.1 123456789\n")
38
+ socket.puts("shuki.tuki2 10 123456789\n")
39
+ socket.puts("shuki.tuki3 10 123456789\n")
40
+ end
41
+ EventMachine::Timer.new(EM_STOP_AFTER, &EM.method(:stop))
42
+ }
43
+
44
+ expected = [
45
+ "shuki.tuki1 1100.0 123456780",
46
+ "shuki.tuki2 10000.0 123456780",
47
+ "shuki.tuki3 10000.0 123456780"
48
+ ]
49
+ assert_expected_equals_data expected
50
+ end
51
+
52
+ def test_with_avg
53
+ start_middleware @middleware_port, @mock_server_port, 'avg'
54
+ EventMachine.run {
55
+ EventMachine.start_server("0.0.0.0", @mock_server_port, MockServer, @data)
56
+ socket = TCPSocket.new("0.0.0.0", @middleware_port)
57
+ 1.upto(1000) do
58
+ socket.puts("shuki.tuki1 1.0 123456789\n")
59
+ socket.puts("shuki.tuki1 1.2 123456789\n")
60
+ end
61
+ EventMachine::Timer.new(EM_STOP_AFTER, &EM.method(:stop))
62
+ }
63
+
64
+ assert_expected_equals_data ["shuki.tuki1 1.1 123456780"]
65
+ end
66
+
67
+ def test_with_replace
68
+ start_middleware @middleware_port, @mock_server_port, 'replace'
69
+ EventMachine.run {
70
+ EventMachine.start_server("0.0.0.0", @mock_server_port, MockServer, @data)
71
+ socket = TCPSocket.new("0.0.0.0", @middleware_port)
72
+ 1.upto(1000) do
73
+ socket.puts("shuki.tuki1 10.0 123456789\n")
74
+ socket.puts("shuki.tuki1 5.0 123456789\n")
75
+ end
76
+ EventMachine::Timer.new(EM_STOP_AFTER, &EM.method(:stop))
77
+ }
78
+
79
+ assert_expected_equals_data ["shuki.tuki1 5.0 123456780"]
80
+ end
81
+
82
+ def assert_expected_equals_data expected
83
+ assert_equal expected, @data.map {|o| o.split("\n")}.flatten(1).map(&:strip)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,42 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+
3
+ require 'simplecov'
4
+ require 'simplecov-rcov'
5
+ require 'codecov'
6
+ require "minitest/autorun"
7
+
8
+ SimpleCov.start { add_filter "/tests/" }
9
+ SimpleCov.formatter = Class.new do
10
+ def format(result)
11
+ SimpleCov::Formatter::Codecov.new.format(result) if ENV["CODECOV_TOKEN"]
12
+ SimpleCov::Formatter::RcovFormatter.new.format(result) unless ENV["CI"]
13
+ end
14
+ end
15
+
16
+ require "graphite-api-middleware"
17
+
18
+ module GraphiteApiMiddleware::Tests
19
+ class TestCase < Minitest::Test
20
+ end
21
+
22
+ module Utils
23
+ def self.random_non_repeating_port
24
+ @ports ||= (1000..9999).to_a.shuffle
25
+ @ports.pop
26
+ end
27
+
28
+ def self.stop_em_if_running
29
+ EM.stop if EM.reactor_running?
30
+ sleep 0.1 while EM.reactor_running?
31
+ end
32
+ end
33
+
34
+ module MockServer
35
+ def initialize db
36
+ @db = db
37
+ end
38
+ def receive_data data
39
+ @db.push data
40
+ end
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: graphite-api-middleware
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Eran Levi
8
+ - Eyal Shalev
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-03-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: docopt
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: eventmachine
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.3.3
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 0.3.3
42
+ - !ruby/object:Gem::Dependency
43
+ name: zscheduler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 0.0.7
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 0.0.7
56
+ - !ruby/object:Gem::Dependency
57
+ name: graphite-api
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.0.0
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.0
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '10.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '10.0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: minitest
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '5.0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '5.0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: simplecov
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '0.16'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '0.16'
112
+ - !ruby/object:Gem::Dependency
113
+ name: codecov
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '0.1'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '0.1'
126
+ - !ruby/object:Gem::Dependency
127
+ name: simplecov-rcov
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '0.2'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '0.2'
140
+ - !ruby/object:Gem::Dependency
141
+ name: gem-release
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - "~>"
145
+ - !ruby/object:Gem::Version
146
+ version: '2.0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: '2.0'
154
+ description: Interact with Graphite's Carbon Daemon through this middleware
155
+ email:
156
+ - eran@kontera.com
157
+ - eyalsh@gmail.com
158
+ executables:
159
+ - graphite-api-middleware
160
+ extensions: []
161
+ extra_rdoc_files: []
162
+ files:
163
+ - LICENSE.txt
164
+ - README.md
165
+ - Rakefile
166
+ - bin/graphite-api-middleware
167
+ - lib/graphite-api-middleware.rb
168
+ - lib/graphite-api-middleware/version.rb
169
+ - test/functional/middleware_sanity_test.rb
170
+ - test/test_helper.rb
171
+ homepage: https://github.com/kontera-technologies/graphite-api-middleware
172
+ licenses:
173
+ - LGPL-3.0
174
+ metadata: {}
175
+ post_install_message:
176
+ rdoc_options: []
177
+ require_paths:
178
+ - lib
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '2.3'
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ requirements: []
190
+ rubygems_version: 3.0.3
191
+ signing_key:
192
+ specification_version: 4
193
+ summary: Aggregator daemon for Graphite API
194
+ test_files: []