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 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 (0.1.0.alpha)
5
- graphite (>= 0.2.0)
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.5.2)
12
- eventmachine (0.12.10)
13
- graphite (0.2.0)
14
- eventmachine
15
- rufus-scheduler
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
- Install :
3
+ Usage :
4
4
 
5
- Open the mongodb_graphite file and modify the graphite server variable to your graphite server. For exemple : "mygraphite.mydomain.com:2023"
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
- Add the mongodb_graphite to your crontab, for instance
8
- * * * * mongodb_graphite "graphite.mydomain:2023"
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
- That's all.
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 'mongo'
4
- require 'graphite'
5
- require 'peach'
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
- hostt='localhost'
74
- portt=27017
75
- @conn = Mongo::Connection.new(hostt,portt)
76
- @isdbgrid = {"isdbgrid" => 1}
77
- begin
78
- @conn["admin"].command(@isdbgrid)["ok"] == 1
79
- puts "mongos"
80
- shards = Array.new
81
- puts @conn["config"]["shards"].find().each { |shard| shards << shard["host"] }
82
- shards.each { |s|
83
- puts s
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
- rescue
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,5 @@
1
+ module MongodbGraphite
2
+ autoload :Configuration, 'mongodb-graphite/configuration'
3
+ autoload :InstanceList, 'mongodb-graphite/instance_list'
4
+ autoload :Instance, 'mongodb-graphite/instance'
5
+ end
@@ -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
@@ -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.1.5'
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", ">= 0.2.0"
20
- s.add_dependency "peach", ">= 0.4"
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
- hash: 17
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
- - "Gr\xC3\xA9goire Seux"
6
+ authors:
7
+ - Grégoire Seux
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2012-03-15 00:00:00 Z
19
- dependencies:
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
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
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
- requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 23
45
- segments:
46
- - 0
47
- - 2
48
- - 0
49
- version: 0.2.0
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
- requirement: &id003 !ruby/object:Gem::Requirement
56
- none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- hash: 3
61
- segments:
62
- - 0
63
- - 4
64
- version: "0.4"
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
- version_requirements: *id003
67
- description: ""
68
- email:
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
- none: false
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- hash: 3
96
- segments:
97
- - 0
98
- version: "0"
99
- required_rubygems_version: !ruby/object:Gem::Requirement
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: 1.8.15
91
+ rubygems_version: 2.0.3
112
92
  signing_key:
113
- specification_version: 3
114
- summary: ""
93
+ specification_version: 4
94
+ summary: ''
115
95
  test_files: []
116
-