mongodb-graphite 0.1.5 → 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
+ 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
-