mongodb-graphite 0.1.5 → 1.0.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.
- checksums.yaml +7 -0
- data/Gemfile.lock +8 -12
- data/README.md +35 -5
- data/bin/mongodb-graphite +31 -82
- data/lib/mongodb-graphite.rb +5 -0
- data/lib/mongodb-graphite/configuration.rb +39 -0
- data/lib/mongodb-graphite/instance.rb +101 -0
- data/lib/mongodb-graphite/instance_list.rb +46 -0
- data/mongodb-graphite.gemspec +3 -3
- metadata +65 -86
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 462cf3ab0ee602d4cdacff7c2c1f31b92551cdad
|
4
|
+
data.tar.gz: ecc40e1948680682b9f4ef968764f00657ff25c9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f5ee6b638028c2d35f662bdf15ce7217b2e19ad1711b17b0406c5c687c557c3304a1750e7146c6b1976d6c6125c034bb2dc81f4269b0f63c41e7078d58e537a7
|
7
|
+
data.tar.gz: be5acfc4bc778b4ce0e894b00c0551621047436bfeee66ec211df1420de237246770e6254f57bde69558b6243ffe128058f87387d2711b376287047207da6693
|
data/Gemfile.lock
CHANGED
@@ -1,23 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mongodb-graphite (
|
5
|
-
|
4
|
+
mongodb-graphite (1.0.0)
|
5
|
+
daemons
|
6
6
|
mongo (>= 1.5.2)
|
7
|
+
simple-graphite (>= 2.1.0)
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: http://rubygems.org/
|
10
11
|
specs:
|
11
|
-
bson (1.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
mongo (1.5.2)
|
17
|
-
bson (= 1.5.2)
|
18
|
-
rufus-scheduler (2.0.16)
|
19
|
-
tzinfo (>= 0.3.23)
|
20
|
-
tzinfo (0.3.31)
|
12
|
+
bson (1.8.6)
|
13
|
+
daemons (1.1.9)
|
14
|
+
mongo (1.8.6)
|
15
|
+
bson (~> 1.8.6)
|
16
|
+
simple-graphite (2.1.0)
|
21
17
|
|
22
18
|
PLATFORMS
|
23
19
|
ruby
|
data/README.md
CHANGED
@@ -1,12 +1,42 @@
|
|
1
1
|
Very simple gem to monitor a mongodb cluster and send data to a graphite server.
|
2
2
|
|
3
|
-
|
3
|
+
Usage :
|
4
4
|
|
5
|
-
|
5
|
+
You have to set an environment variable MONGODB_GRAPHITE_DIR (or it will use the config dir in the current directory).
|
6
|
+
Then write a yml file to contain basic settings:
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
```yaml
|
9
|
+
log_dir: log
|
10
|
+
pid_dir: pids
|
11
|
+
graphite: graphite.mydomain:3333
|
12
|
+
interval: 3
|
13
|
+
instances_file: 'config/instances.rb'
|
14
|
+
```
|
9
15
|
|
16
|
+
Then in config/instances.rb, you can set instances to monitor:
|
10
17
|
|
11
|
-
|
18
|
+
```ruby
|
19
|
+
instance 'mongoD' do
|
20
|
+
host 'onemongo.mydomain'
|
21
|
+
port '27021'
|
22
|
+
prefix_callback (lambda { |stats|
|
23
|
+
process_type = stats['process']
|
24
|
+
"production.onemongo.#{process_type}"
|
25
|
+
} )
|
26
|
+
end
|
12
27
|
|
28
|
+
instance 'mongoD' do
|
29
|
+
host 'anothermongo.mydomain'
|
30
|
+
port '27017'
|
31
|
+
prefix_callback (lambda { |stats|
|
32
|
+
process_type = stats['process']
|
33
|
+
'test.anothermongo.#{process_type}"
|
34
|
+
} )
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
Finally, you can use the gem as a service (start, status, stop)
|
39
|
+
|
40
|
+
```
|
41
|
+
mongodb-graphite start
|
42
|
+
```
|
data/bin/mongodb-graphite
CHANGED
@@ -1,93 +1,42 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
7
|
-
graphite_server = ARGV[1]
|
8
|
-
prefix_common = ARGV[0]+"."
|
9
|
-
puts graphite_server
|
10
|
-
g = Graphite::Logger.new(graphite_server)
|
11
|
-
|
12
|
-
to_ignore =[ "set", "repl", "time","qr|qw","ar|aw","conn"]
|
13
|
-
to_convert = ["mapped","vsize","res","netIn","netOut"]
|
14
|
-
output_average = ["mapped","vsize","res","locked","idxmiss"]
|
15
|
-
output_sum = ["netIn", "netOut","insert","query","update","delete","getmore","command","flushes","faults"]
|
16
|
-
|
17
|
-
def convert(s)
|
18
|
-
mul = case s[-1]
|
19
|
-
when "b"
|
20
|
-
1
|
21
|
-
when "k"
|
22
|
-
1024
|
23
|
-
when "m"
|
24
|
-
1024 * 1024
|
25
|
-
when "g"
|
26
|
-
1024 * 1024 *1024
|
27
|
-
when "t"
|
28
|
-
1024 * 1024 * 1024 *1024
|
29
|
-
else
|
30
|
-
raise "not convertible"
|
31
|
-
end
|
32
|
-
s[0..-1].to_f * mul
|
33
|
-
end
|
34
|
-
|
3
|
+
require 'mongodb-graphite'
|
4
|
+
require 'optparse'
|
5
|
+
require 'daemons'
|
6
|
+
require 'simple-graphite'
|
35
7
|
|
8
|
+
conf_dir = File.expand_path(ENV['MONGODB_GRAPHITE_DIR'] || '.')
|
36
9
|
|
10
|
+
config = MongodbGraphite::Configuration.new(conf_dir)
|
37
11
|
|
12
|
+
daemon_options = {
|
13
|
+
:multiple => false,
|
14
|
+
:monitor => true,
|
15
|
+
:backtrace => true,
|
16
|
+
:log_dir => config[:log_dir],
|
17
|
+
:log_output => true,
|
18
|
+
:dir_mode => :normal,
|
19
|
+
:dir => config[:pid_dir]
|
20
|
+
}
|
38
21
|
|
22
|
+
g_host, g_port = config[:graphite].split(':')
|
39
23
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
def treat_replicaset(g,to_ignore,to_convert, output_average, output_sum ,prefix_common,host,port, shard_name)
|
45
|
-
#puts "shard : ", host,port
|
46
|
-
connHost = Mongo::Connection.new(host, port)
|
47
|
-
slaves = Array.new
|
48
|
-
connHost["admin"].command({ "isMaster" => 1 } )["hosts"].each { |slave| slaves << slave}
|
49
|
-
slaves.each { |slave|
|
50
|
-
Process.fork do
|
51
|
-
host, port = slave.split(':')
|
52
|
-
timestamp = Time.now.getutc.to_i
|
53
|
-
result= `mongostat -n 60 --host #{host} --port #{port} `.split("\n")
|
54
|
-
#timestamp += Time.now.getutc.to_i
|
55
|
-
#timestamp /= 2
|
56
|
-
headers, values = result[1], result[2..-1]
|
57
|
-
headers = headers.gsub(' %','').gsub('*','').gsub('idx miss','idxmiss').split
|
58
|
-
values= values.delete_if {|line| line.start_with?('insert')}.map { |line| line.gsub('*','').split}
|
59
|
-
values = values.transpose
|
60
|
-
|
61
|
-
prefix = prefix_common +shard_name+"."+ host +"."+port+"."
|
62
|
-
headers = headers.map { |key| prefix+key }
|
63
|
-
metrics = Hash[headers.zip(values)]
|
64
|
-
to_ignore.each { |key| metrics.delete(prefix + key) }
|
65
|
-
to_convert.each { |key| metrics[prefix + key] = metrics[prefix+key].map {|val| convert(val)}}
|
66
|
-
output_average.each { |key| metrics[prefix+key] = metrics[prefix+key].inject(0.0) {|sum,el| sum+(el.to_i) } / metrics[prefix+key].size }
|
67
|
-
output_sum.each { |key| metrics[prefix+key] = metrics[prefix+key].inject(0) {|sum,el| sum+(el.to_i)} }
|
68
|
-
g.log(timestamp, metrics)
|
69
|
-
end
|
70
|
-
}
|
24
|
+
[:log_dir, :pid_dir].each do |d|
|
25
|
+
Dir.mkdir config[d] unless Dir.exist?(config[d])
|
71
26
|
end
|
72
27
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
@
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
Process.fork do
|
85
|
-
host,port = s.split(/,|\//)[1].split(':')
|
86
|
-
treat_replicaset(g,to_ignore,to_convert, output_average, output_sum ,prefix_common,host,port, s.split(/,|\//)[0])
|
28
|
+
Daemons.run_proc('mongodb-graphite', daemon_options) do
|
29
|
+
loop do
|
30
|
+
g = Graphite.new( :host => g_host, :port => g_port || '3333' )
|
31
|
+
@instance_list = MongodbGraphite::InstanceList.new(config)
|
32
|
+
@instance_list.each do |i|
|
33
|
+
begin
|
34
|
+
g.send_metrics(i.to_graphite)
|
35
|
+
rescue Exception => e
|
36
|
+
puts "Impossible to send metrics because of #{e}"
|
37
|
+
puts e.backtrace
|
38
|
+
end
|
87
39
|
end
|
88
|
-
|
89
|
-
|
90
|
-
puts "not mongos"
|
91
|
-
treat_replicaset(g,to_ignore,to_convert, output_average, output_sum ,prefix_common,hostt,portt, "direct")
|
40
|
+
sleep (config[:interval] || 5)
|
41
|
+
end
|
92
42
|
end
|
93
|
-
Process.wait
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module MongodbGraphite
|
4
|
+
class Configuration
|
5
|
+
def initialize(dir)
|
6
|
+
reload(dir)
|
7
|
+
end
|
8
|
+
|
9
|
+
def reload(dir)
|
10
|
+
@config = {
|
11
|
+
:log_dir => 'log',
|
12
|
+
:pid_dir => 'pids',
|
13
|
+
:graphite => 'localhost:3333',
|
14
|
+
:mongodb => 'localhost:27017',
|
15
|
+
:interval => 3, #in seconds
|
16
|
+
:instances_file => nil
|
17
|
+
}
|
18
|
+
|
19
|
+
config_file_path = File.join(dir, 'config', 'mongodb-graphite.yml')
|
20
|
+
if File.exist? config_file_path
|
21
|
+
config_file = YAML.load_file(config_file_path)
|
22
|
+
@config.keys.each do |key|
|
23
|
+
value = config_file[key.to_s]
|
24
|
+
@config[key] = value unless value.nil?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
@config[:mongodb_graphite_dir] = dir
|
29
|
+
|
30
|
+
[:log_dir, :pid_dir, :instances_file].each do |k|
|
31
|
+
@config[k] = File.absolute_path(@config[k], dir)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](key)
|
36
|
+
@config[key]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'simple-graphite'
|
3
|
+
|
4
|
+
module Enumerable
|
5
|
+
def merge_all
|
6
|
+
self.inject({}) { |h1, h2|
|
7
|
+
h1.merge! h2
|
8
|
+
}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module MongodbGraphite
|
13
|
+
class Instance
|
14
|
+
|
15
|
+
OPTIONS = [:host, :port, :prefix_callback, :fields_to_ignore]
|
16
|
+
|
17
|
+
def initialize(name)
|
18
|
+
@name = name
|
19
|
+
@port = 27017
|
20
|
+
@host = 'localhost'
|
21
|
+
@fields_to_ignore = %w(host version process pid uptimeMillis localTime extra_info.note backgroundFlushing.last_finished repl.setName repl.hosts repl.arbiters repl.primary repl.me ok)
|
22
|
+
@prefix_callback = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def reload(options)
|
26
|
+
OPTIONS.each do |opt|
|
27
|
+
val = instance_variable_get "@#{opt}"
|
28
|
+
if options[opt] != val and not options[opt].nil?
|
29
|
+
instance_variable_set "@#{opt}", options.delete(opt)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
OPTIONS.each do |opt|
|
35
|
+
define_method opt do
|
36
|
+
instance_variable_get "@#{opt}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"#{@name} #{@host}:#{@port}, #{@prefix_callback.class}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_graphite
|
45
|
+
@stats = to_hash
|
46
|
+
with_prefix = Hash.new
|
47
|
+
@stats.each do |k,v|
|
48
|
+
with_prefix[ [prefix, k].join('.')] = to_i(v)
|
49
|
+
end
|
50
|
+
with_prefix.reject { |k,v| ignored_fields.include? k }
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def prefix
|
56
|
+
return @prefix_callback.call(@stats) unless @prefix_callback.nil?
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_i(v)
|
61
|
+
return v.to_i if v.respond_to?('to_i')
|
62
|
+
case v
|
63
|
+
when TrueClass
|
64
|
+
1
|
65
|
+
when FalseClass
|
66
|
+
0
|
67
|
+
else
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def ignored_fields
|
73
|
+
@fields_to_ignore.map { |f| [prefix,f].join('.') }
|
74
|
+
end
|
75
|
+
|
76
|
+
def connection
|
77
|
+
@connection ||= Mongo::MongoClient.new(host, port, :slave_ok => true, :connect_timeout => 5, :pool_timeout => 5)
|
78
|
+
end
|
79
|
+
|
80
|
+
def stats
|
81
|
+
connection['test'].command({ 'serverStatus' => 1})
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_hash
|
85
|
+
s = stats
|
86
|
+
@process = s['process']
|
87
|
+
json_descent([], s).flatten.merge_all
|
88
|
+
end
|
89
|
+
|
90
|
+
def json_descent(pre, json)
|
91
|
+
json.map do |k,v|
|
92
|
+
key = pre + [k]
|
93
|
+
if v.is_a? BSON::OrderedHash
|
94
|
+
json_descent(key, v)
|
95
|
+
else
|
96
|
+
{key.join('.') => v }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MongodbGraphite
|
2
|
+
class InstanceList
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :instances
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
@instances = {}
|
10
|
+
reload
|
11
|
+
end
|
12
|
+
|
13
|
+
def reload
|
14
|
+
@instances = {}
|
15
|
+
|
16
|
+
file = @config[:instances_file]
|
17
|
+
if not file.nil?
|
18
|
+
#puts "Reading instance file from #{file}"
|
19
|
+
instance_eval(File.read(file),file)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def instance(name)
|
24
|
+
@options = {}
|
25
|
+
yield
|
26
|
+
@instances[name] ||= Instance.new(name)
|
27
|
+
@instances[name].reload(@options)
|
28
|
+
@options = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
#dynamic definition of properties to have a nice dsl
|
32
|
+
Instance::OPTIONS.each do |opt|
|
33
|
+
define_method opt do |v|
|
34
|
+
@options[opt] = v
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def each
|
40
|
+
@instances.each do |name,i|
|
41
|
+
yield i
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/mongodb-graphite.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "mongodb-graphite"
|
6
|
-
s.version = '0.
|
6
|
+
s.version = '1.0.0'
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.authors = ["Grégoire Seux"]
|
9
9
|
s.email = ["g.seux@criteo.com"]
|
@@ -16,6 +16,6 @@ Gem::Specification.new do |s|
|
|
16
16
|
#s.require_paths = ["lib"]
|
17
17
|
|
18
18
|
s.add_dependency "mongo", ">= 1.5.2"
|
19
|
-
s.add_dependency "graphite", ">=
|
20
|
-
s.add_dependency
|
19
|
+
s.add_dependency "simple-graphite", ">= 2.1.0"
|
20
|
+
s.add_dependency 'daemons'
|
21
21
|
end
|
metadata
CHANGED
@@ -1,116 +1,95 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongodb-graphite
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 5
|
10
|
-
version: 0.1.5
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
13
|
-
-
|
6
|
+
authors:
|
7
|
+
- Grégoire Seux
|
14
8
|
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2013-06-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
21
14
|
name: mongo
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
- - ">="
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
hash: 7
|
29
|
-
segments:
|
30
|
-
- 1
|
31
|
-
- 5
|
32
|
-
- 2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
33
19
|
version: 1.5.2
|
34
20
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: graphite
|
38
21
|
prerelease: false
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: simple-graphite
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.1.0
|
50
34
|
type: :runtime
|
51
|
-
version_requirements: *id002
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
name: peach
|
54
35
|
prerelease: false
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: daemons
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
65
48
|
type: :runtime
|
66
|
-
|
67
|
-
|
68
|
-
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: ''
|
56
|
+
email:
|
69
57
|
- g.seux@criteo.com
|
70
|
-
executables:
|
58
|
+
executables:
|
71
59
|
- mongodb-graphite
|
72
60
|
extensions: []
|
73
|
-
|
74
61
|
extra_rdoc_files: []
|
75
|
-
|
76
|
-
files:
|
62
|
+
files:
|
77
63
|
- Gemfile
|
78
64
|
- Gemfile.lock
|
79
65
|
- README.md
|
80
66
|
- bin/mongodb-graphite
|
67
|
+
- lib/mongodb-graphite.rb
|
68
|
+
- lib/mongodb-graphite/configuration.rb
|
69
|
+
- lib/mongodb-graphite/instance.rb
|
70
|
+
- lib/mongodb-graphite/instance_list.rb
|
81
71
|
- mongodb-graphite.gemspec
|
82
72
|
homepage: https://github.com/kamaradclimber/mongodb-graphite
|
83
73
|
licenses: []
|
84
|
-
|
74
|
+
metadata: {}
|
85
75
|
post_install_message:
|
86
76
|
rdoc_options: []
|
87
|
-
|
88
|
-
require_paths:
|
77
|
+
require_paths:
|
89
78
|
- lib
|
90
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
none: false
|
101
|
-
requirements:
|
102
|
-
- - ">="
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
hash: 3
|
105
|
-
segments:
|
106
|
-
- 0
|
107
|
-
version: "0"
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
108
89
|
requirements: []
|
109
|
-
|
110
90
|
rubyforge_project:
|
111
|
-
rubygems_version:
|
91
|
+
rubygems_version: 2.0.3
|
112
92
|
signing_key:
|
113
|
-
specification_version:
|
114
|
-
summary:
|
93
|
+
specification_version: 4
|
94
|
+
summary: ''
|
115
95
|
test_files: []
|
116
|
-
|