nutcracker-graphite 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ac51b5f953ef068101cc9c5b2f4aac6b0370eb2
4
+ data.tar.gz: 7f2d673e8982941ae96c2d65bb92f89e6ea116db
5
+ SHA512:
6
+ metadata.gz: 39344998867494f870f0c473533f13dbee63013ac3f8a0793ea9b4b8567390166603d4d411ab9a6d6dd2889ddded9b2c80ec13a997d65041e1d8d9883b9a93d1
7
+ data.tar.gz: aec3d483bbeaaeb8f8ac4514e7283a6ff33a1493d63c668e97fe93b38047ba4d200ccfd8def4b4f26403d256443f52465020d55ce853ddc9851e5a198c375718
@@ -0,0 +1,102 @@
1
+ Nutcracker Graphite
2
+ ==================
3
+ <a href="https://rubygems.org/gems/nutcracker-graphite"><img src=https://fury-badge.herokuapp.com/rb/nutcracker-graphite.png></a>
4
+
5
+ [Nutcracker](https://github.com/kontera-technologies/nutcracker) plugin for sending cluster data to Graphite
6
+
7
+ ### DISCLAIMER
8
+ this is still a work in progress...
9
+
10
+ ## Dependencies
11
+ - ruby 1.9+
12
+ - [Graphite](http://graphite.wikidot.com/)
13
+
14
+ ## Installation
15
+ Add this line to your application's Gemfile:
16
+ ```
17
+ gem 'nutcracker-graphite'
18
+ ```
19
+
20
+ And then execute:
21
+ ```
22
+ $ bundle install
23
+ ```
24
+
25
+ or just by
26
+ ```
27
+ $ gem install nutcracker-graphite
28
+ ```
29
+
30
+ ## Usage
31
+ example app
32
+ ```ruby
33
+ require 'nutcracker'
34
+ require 'nutcracker/graphite'
35
+
36
+ # Start nutcracker
37
+ nutcracker = Nutcracker.start(cluster: 'cluster.conf')
38
+
39
+ # Start Graphite stats agent
40
+ nutcracker.use(:graphite, graphite: 'graphite.example.com')
41
+ # will send aggregated stats to graphite.example.com every 1 minute
42
+
43
+ # Waiting....
44
+ nutcracker.join
45
+ ```
46
+
47
+ example output for two nodes cluster ( will be send every 1 minute )
48
+ ```
49
+ nutcracker.<cluster-name>.<nutcracker-hostname>.client_eof 0.0 1369569180
50
+ nutcracker.<cluster-name>.<nutcracker-hostname>.client_err 0.0 1369569180
51
+ nutcracker.<cluster-name>.<nutcracker-hostname>.client_connections 0.0 1369569180
52
+ nutcracker.<cluster-name>.<nutcracker-hostname>.server_ejects 0.0 1369569180
53
+ nutcracker.<cluster-name>.<nutcracker-hostname>.forward_error 0.0 1369569180
54
+ nutcracker.<cluster-name>.<nutcracker-hostname>.fragments 0.0 1369569180
55
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_server_eof 0.0 1369569180
56
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_server_err 0.0 1369569180
57
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_server_timedout 0.0 1369569180
58
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_server_connections 0.0 1369569180
59
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_requests 0.0 1369569180
60
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_request_bytes 0.0 1369569180
61
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_responses 0.0 1369569180
62
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_response_bytes 0.0 1369569180
63
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_in_queue 0.0 1369569180
64
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_in_queue_bytes 0.0 1369569180
65
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_out_queue 0.0 1369569180
66
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.cluster_out_queue_bytes 0.0 1369569180
67
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.connections 95.0 1369569180
68
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.used_memory 20173789840.0 1369569180
69
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.used_memory_rss 20932427776.0 1369569180
70
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.fragmentation 1.04 1369569180
71
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.expired_keys 36732182.0 1369569180
72
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.evicted_keys 12284.0 1369569180
73
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.hits 1372163466.0 1369569180
74
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.misses 58928722.0 1369569180
75
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.keys 24347281.0 1369569180
76
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.max_memory 21474836480.0 1369569180
77
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node1>.hit_ratio 0.96 1369569180
78
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_server_eof 0.0 1369569180
79
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_server_err 0.0 1369569180
80
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_server_timedout 0.0 1369569180
81
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_server_connections 0.0 1369569180
82
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_requests 0.0 1369569180
83
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_request_bytes 0.0 1369569180
84
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_responses 0.0 1369569180
85
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_response_bytes 0.0 1369569180
86
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_in_queue 0.0 1369569180
87
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_in_queue_bytes 0.0 1369569180
88
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_out_queue 0.0 1369569180
89
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.cluster_out_queue_bytes 0.0 1369569180
90
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.connections 95.0 1369569180
91
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.used_memory 20173789840.0 1369569180
92
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.used_memory_rss 20932427776.0 1369569180
93
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.fragmentation 1.04 1369569180
94
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.expired_keys 36732182.0 1369569180
95
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.evicted_keys 12284.0 1369569180
96
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.hits 1372163466.0 1369569180
97
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.misses 58928722.0 1369569180
98
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.keys 24347281.0 1369569180
99
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.max_memory 21474836480.0 1369569180
100
+ nutcracker.<cluster-name>.<nutcracker-hostname>.<node2>.hit_ratio 0.96 1369569180
101
+ ```
102
+
@@ -0,0 +1,18 @@
1
+ $:.unshift File.expand_path '../lib', __FILE__
2
+ require 'nutcracker/graphite'
3
+ require 'rubygems/package_task'
4
+ require 'rake/testtask'
5
+
6
+ Nutcracker::GemSpec = eval File.read 'nutcracker-graphite.gemspec'
7
+
8
+ Gem::PackageTask.new Nutcracker::GemSpec do |p|
9
+ p.gem_spec = Nutcracker::GemSpec
10
+ end
11
+
12
+ ## Tests stuff
13
+ task :default => :test
14
+
15
+ Rake::TestTask.new(:test) do |t|
16
+ t.libs.push 'tests'
17
+ t.pattern = 'tests/**/*_test.rb'
18
+ end
@@ -0,0 +1,98 @@
1
+ require 'nutcracker/graphite/version'
2
+ require 'graphite-api'
3
+ require 'redis'
4
+
5
+ module Nutcracker
6
+ module Graphite
7
+
8
+ def self.start nutcracker, options
9
+ Agent.new(nutcracker, options).start
10
+ end
11
+
12
+ class Agent
13
+ INTERVAL=60
14
+
15
+ attr_reader :nutcracker, :graphite
16
+
17
+ def initialize nutcracker, options
18
+ @nutcracker = nutcracker
19
+ @graphite = GraphiteAPI.new options.merge(:interval => INTERVAL)
20
+ end
21
+
22
+ def start
23
+ @task ||= graphite.every INTERVAL do |client|
24
+ client.metrics metrics parse nutcracker.stats
25
+ end
26
+ self
27
+ end
28
+
29
+ def stop
30
+ @task and @task.cancel
31
+ end
32
+
33
+ private
34
+
35
+ def metrics parsed_stats
36
+ data = parsed_stats.clone
37
+ escape = ->(s) { s.gsub(/\.|\:/,'_') }
38
+ hash = {}
39
+ data[:clusters].each do |cluster, cluster_data|
40
+ next unless ( nutcracker.config[cluster]["redis"] rescue false ) # skip memcached
41
+ cluster_key = ['nutcracker',cluster,data['source']].map(&escape).join('.')
42
+ cluster_data.each do |key, value|
43
+ hash[[cluster_key,key].join('.')] = value if value.is_a? Fixnum or value.is_a? Float
44
+ end
45
+
46
+ cluster_data[:nodes].each do |node, node_data|
47
+ node_key = "#{cluster_key}.#{escape.(node)}"
48
+ node_data.each do |key, value|
49
+ hash["#{node_key}.cluster_#{key}"] = value if value.is_a? Fixnum or value.is_a? Float
50
+ end
51
+ redis_info(node).each {|k,v| hash["#{node_key}.#{k}"] = v }
52
+ end
53
+
54
+ end
55
+ hash
56
+ end
57
+
58
+ def redis_info url
59
+ url = "redis://#{url}" unless url =~ /redis\:\/\//
60
+ redis = Redis.connect url: url
61
+ server_info = redis.info
62
+ db_size = redis.dbsize
63
+ max_memory = redis.config(:get, 'maxmemory')['maxmemory'].to_i
64
+ redis.quit
65
+ {
66
+ 'connections' => server_info['connected_clients'].to_i,
67
+ 'used_memory' => server_info['used_memory'].to_f,
68
+ 'used_memory_rss' => server_info['used_memory_rss'].to_f,
69
+ 'fragmentation' => server_info['mem_fragmentation_ratio'].to_f,
70
+ 'expired_keys' => server_info['expired_keys'].to_i,
71
+ 'evicted_keys' => server_info['evicted_keys'].to_i,
72
+ 'hits' => server_info['keyspace_hits'].to_i,
73
+ 'misses' => server_info['keyspace_misses'].to_i,
74
+ 'keys' => db_size,
75
+ 'max_memory' => max_memory,
76
+ 'hit_ratio' => 0
77
+ }.tap {|d| d['hit_ratio'] = d['hits'].to_f / (d['hits']+d['misses']).to_f if d['hits'] > 0 }
78
+ end
79
+
80
+
81
+ def parse stats
82
+ { :clusters => {} }.tap do |data|
83
+ (stats.dup).each do |key, value|
84
+ (data[key] = value and next) if !value.is_a? Hash
85
+ data[:clusters][key] = value
86
+ data[:clusters][key][:nodes] = {}
87
+ data[:clusters][key].each do |key2,value2|
88
+ if value2.kind_of? Hash and key2.is_a? String
89
+ data[:clusters][key][:nodes][key2] = data[:clusters][key].delete(key2)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,5 @@
1
+ module Nutcracker
2
+ module Graphite
3
+ VERSION="0.0.1"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ {"nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.client_eof"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.client_err"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.client_connections"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.server_ejects"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.forward_error"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.fragments"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_server_eof"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_server_err"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_server_timedout"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_server_connections"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_requests"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_request_bytes"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_responses"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_response_bytes"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_in_queue"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_in_queue_bytes"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_out_queue"=>0, "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.cluster_out_queue_bytes"=>0}
@@ -0,0 +1 @@
1
+ {"connections":96,"used_memory":20042110520.0,"used_memory_rss":20905414656.0,"fragmentation":1.04,"expired_keys":36705179,"evicted_keys":12284,"hits":1370531418,"misses":58886159,"keys":24296159,"max_memory":21474836480,"hit_ratio":0.9588040891986317}
@@ -0,0 +1 @@
1
+ {:clusters=>{"page_data_cluster"=>{"client_eof"=>0, "client_err"=>0, "client_connections"=>0, "server_ejects"=>0, "forward_error"=>0, "fragments"=>0, :nodes=>{"node1:6379"=>{"server_eof"=>0, "server_err"=>0, "server_timedout"=>0, "server_connections"=>0, "requests"=>0, "request_bytes"=>0, "responses"=>0, "response_bytes"=>0, "in_queue"=>0, "in_queue_bytes"=>0, "out_queue"=>0, "out_queue_bytes"=>0}}}}, "service"=>"nutcracker", "source"=>"Eran-Levis-MacBook-Pro.local", "version"=>"0.2.4", "uptime"=>53, "timestamp"=>1369558826}
@@ -0,0 +1 @@
1
+ {"info":{"redis_version":"2.4.10","redis_git_sha1":"00000000","redis_git_dirty":"0","arch_bits":"64","multiplexing_api":"epoll","gcc_version":"4.1.2","process_id":"15264","uptime_in_seconds":"5247213","uptime_in_days":"60","lru_clock":"641250","used_cpu_sys":"40451.50","used_cpu_user":"172259.69","used_cpu_sys_children":"0.00","used_cpu_user_children":"0.00","connected_clients":"96","connected_slaves":"0","client_longest_output_list":"0","client_biggest_input_buf":"0","blocked_clients":"0","used_memory":"20042110520","used_memory_human":"18.67G","used_memory_rss":"20905414656","used_memory_peak":"21474896448","used_memory_peak_human":"20.00G","mem_fragmentation_ratio":"1.04","mem_allocator":"jemalloc-2.2.5","loading":"0","aof_enabled":"0","changes_since_last_save":"8316280672","bgsave_in_progress":"0","last_save_time":"1364314088","bgrewriteaof_in_progress":"0","total_connections_received":"64618","total_commands_processed":"18247026966","expired_keys":"36705179","evicted_keys":"12284","keyspace_hits":"1370531418","keyspace_misses":"58886159","pubsub_channels":"0","pubsub_patterns":"0","latest_fork_usec":"0","vm_enabled":"0","role":"master","db0":"keys=24296116,expires=739455","db2":"keys=14178,expires=0"},"dbsize":24296159,"memory":{"maxmemory":"21474836480"}}
@@ -0,0 +1 @@
1
+ {"service":"nutcracker","source":"Eran-Levis-MacBook-Pro.local","version":"0.2.4","uptime":53,"timestamp":1369558826,"page_data_cluster":{"client_eof":0,"client_err":0,"client_connections":0,"server_ejects":0,"forward_error":0,"fragments":0,"node1:6379":{"server_eof":0,"server_err":0,"server_timedout":0,"server_connections":0,"requests":0,"request_bytes":0,"responses":0,"response_bytes":0,"in_queue":0,"in_queue_bytes":0,"out_queue":0,"out_queue_bytes":0}}}
@@ -0,0 +1,31 @@
1
+ $:.unshift File.expand_path '../../lib', __FILE__
2
+ gem 'minitest'
3
+
4
+ require 'minitest/autorun'
5
+ require 'mocha/setup'
6
+ require 'nutcracker/graphite'
7
+ require 'tempfile'
8
+ require 'fileutils'
9
+ require 'json'
10
+
11
+ module Nutcracker
12
+ module Graphite
13
+ class Test < ::Minitest::Test
14
+ def fixture name
15
+ File.expand_path("../fixtures/#{name}", __FILE__)
16
+ end
17
+
18
+ def load_fixture name
19
+ raw = File.read fixture name
20
+ if name.end_with? '.json'
21
+ JSON.parse raw
22
+ elsif name.end_with? '.ruby_hash'
23
+ eval raw
24
+ else
25
+ raw
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,51 @@
1
+ require_relative '../minitest_helper'
2
+
3
+ module Nutcracker
4
+ module Graphite
5
+ class AgentTester < Test
6
+
7
+ def setup
8
+ @nutcracker = mock
9
+ @options = {:graphite => 'shuki'}
10
+ @agent = Agent.new( @nutcracker, @options )
11
+ end
12
+
13
+ attr_reader :agent, :options, :nutcracker
14
+
15
+ def test_stats_parser
16
+ assert_equal load_fixture('expected_stats.ruby_hash'),
17
+ agent.send(:parse,load_fixture('stats.json'))
18
+ end
19
+
20
+ def test_metrics_generator
21
+ nutcracker.expects(:config).returns({'page_data_cluster' => {'redis' => true}})
22
+ agent.expects(:redis_info).with('node1:6379').returns({})
23
+
24
+ assert_equal load_fixture('expected_metrics_wo_redis_info.ruby_hash') ,
25
+ agent.send(:metrics,load_fixture('expected_stats.ruby_hash'))
26
+
27
+ nutcracker.expects(:config).returns({'page_data_cluster' => {'redis' => true}})
28
+ agent.expects(:redis_info).with('node1:6379').returns({'blabla' => 20})
29
+
30
+ expected = load_fixture('expected_metrics_wo_redis_info.ruby_hash').merge(
31
+ "nutcracker.page_data_cluster.Eran-Levis-MacBook-Pro_local.node1_6379.blabla"=>20
32
+ )
33
+
34
+ assert_equal expected, agent.send(:metrics,load_fixture('expected_stats.ruby_hash'))
35
+ end
36
+
37
+ def test_redis_info
38
+ data = load_fixture 'redis_info.json'
39
+ redis = mock
40
+ Redis.expects(:connect).with(url: 'redis://node1:6379').returns(redis)
41
+ redis.expects(:info).returns(data['info'])
42
+ redis.expects(:dbsize).returns(data['dbsize'])
43
+ redis.expects('config').with(:get,'maxmemory').returns(data['memory'])
44
+ redis.expects(:quit)
45
+ assert_equal load_fixture('expected_redis_info.json'),
46
+ agent.send(:redis_info,'node1:6379')
47
+ end
48
+
49
+ end
50
+ end
51
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nutcracker-graphite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eran Barak Levi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: graphite-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: nutcracker
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.4.beta3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.4.beta3
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 5.0.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 5.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: mocha
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 0.14.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 0.14.0
83
+ description: Nutcracker plugin for sending cluster statistics to Graphite
84
+ email: eran@kontera.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - README.md
90
+ - Rakefile
91
+ - lib/nutcracker/graphite/version.rb
92
+ - lib/nutcracker/graphite.rb
93
+ - tests/fixtures/expected_metrics_wo_redis_info.ruby_hash
94
+ - tests/fixtures/expected_redis_info.json
95
+ - tests/fixtures/expected_stats.ruby_hash
96
+ - tests/fixtures/redis_info.json
97
+ - tests/fixtures/stats.json
98
+ - tests/minitest_helper.rb
99
+ - tests/unit/agent_test.rb
100
+ homepage: http://www.kontera.com
101
+ licenses: []
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: 1.8.5
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project: ruby-nutcracker-graphite
119
+ rubygems_version: 2.0.3
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Send Twemproxy/nutcracker statistics to Graphite
123
+ test_files: []