maestro_metrics 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/README.md +4 -0
- data/Rakefile +17 -0
- data/lib/maestro_metrics.rb +215 -0
- data/lib/maestro_metrics/version.rb +5 -0
- data/maestro_metrics.gemspec +24 -0
- data/spec/maestro_metrics_spec.rb +161 -0
- data/spec/spec_helper.rb +11 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f5ed4252a33b5cf79e7fcc8a1d52392702fc2c49
|
4
|
+
data.tar.gz: c74d4a556e30e7b139961b22540d0f4a2426999e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd35d8cb55675d2d91dadbfee1e1768dbeb0c128834f14f9f69237753611afa4880fca5df80545179dbdfdd88390baed065d91eba3197e37665eefc4196b6920
|
7
|
+
data.tar.gz: 85102a9e0f5f91ecedd4b7337ccce9487f8ccbeb79e92b070a40820f7fef96a5f8274c7253535fb4074639504d6ab9ba5e56053b3775e8cd0860e8880ac7b5db
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
jruby-1.7.4
|
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
#require File.expand_path('../lib/maestro_plugin/version', __FILE__)
|
6
|
+
|
7
|
+
CLEAN.include('pkg')
|
8
|
+
CLOBBER.include('.bundle', '.config', 'coverage', 'InstalledFiles', 'spec/reports', 'rdoc', 'test', 'tmp')
|
9
|
+
|
10
|
+
task :default => [:clean, :bundle, :spec, :build]
|
11
|
+
|
12
|
+
RSpec::Core::RakeTask.new
|
13
|
+
|
14
|
+
desc 'Get dependencies with Bundler'
|
15
|
+
task :bundle do
|
16
|
+
sh %{bundle install}
|
17
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'maestro_metrics/version'
|
2
|
+
require 'singleton'
|
3
|
+
require 'mongo'
|
4
|
+
require 'statsd'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
module Maestro
|
8
|
+
module Metrics
|
9
|
+
|
10
|
+
@mocking = false
|
11
|
+
@config = {}
|
12
|
+
|
13
|
+
def Metrics.mock!
|
14
|
+
@mocking = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def Metrics.unmock!
|
18
|
+
@mocking = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def Metrics.mock?
|
22
|
+
@mocking
|
23
|
+
end
|
24
|
+
|
25
|
+
def Metrics.mocking?
|
26
|
+
@mocking
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.configure(config={})
|
30
|
+
@config = config unless config.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def Metrics.count(metric, value, sample_rate=1)
|
34
|
+
logger.count(metric, value, sample_rate)
|
35
|
+
end
|
36
|
+
|
37
|
+
def Metrics.timing(metric, value, sample_rate=1)
|
38
|
+
logger.timing(metric, value, sample_rate)
|
39
|
+
end
|
40
|
+
|
41
|
+
def Metrics.increment(metric, sample_rate=1)
|
42
|
+
logger.increment(metric, sample_rate)
|
43
|
+
end
|
44
|
+
|
45
|
+
def Metrics.decrement(metric, sample_rate=1)
|
46
|
+
logger.decrement(metric, sample_rate)
|
47
|
+
end
|
48
|
+
|
49
|
+
def Metrics.time(metric, sample_rate=1, &block)
|
50
|
+
logger.time(metric, sample_rate, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def Metrics.log(collection, metrics)
|
54
|
+
logger.log(collection, metrics)
|
55
|
+
end
|
56
|
+
|
57
|
+
def Metrics.aggregate(collection, pipeline=nil)
|
58
|
+
logger.aggregate(collection, pipeline)
|
59
|
+
end
|
60
|
+
|
61
|
+
def Metrics.find(collection, selector={}, opts={})
|
62
|
+
logger.find(collection, selector, opts)
|
63
|
+
end
|
64
|
+
|
65
|
+
def Metrics.to_mongo(value)
|
66
|
+
if value.nil? || value == ''
|
67
|
+
nil
|
68
|
+
else
|
69
|
+
time = nil
|
70
|
+
|
71
|
+
if value.is_a?(::Date)
|
72
|
+
time = value.to_time
|
73
|
+
elsif value.is_a?(::Time)
|
74
|
+
time = value
|
75
|
+
else
|
76
|
+
time = ::Time.parse(value.to_s)
|
77
|
+
end
|
78
|
+
|
79
|
+
time.utc
|
80
|
+
end
|
81
|
+
rescue
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def Metrics.collection_names
|
86
|
+
logger.collection_names
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
def self.config
|
92
|
+
@config
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def self.logger
|
98
|
+
self.mocking? ? Mock.instance : Real.instance
|
99
|
+
end
|
100
|
+
|
101
|
+
class Real
|
102
|
+
|
103
|
+
include Mongo
|
104
|
+
include Singleton
|
105
|
+
|
106
|
+
def initialize
|
107
|
+
@mongo_host = Metrics.config[:mongo_host] || 'localhost'
|
108
|
+
@mongo_port = Metrics.config[:mongo_port] || 27017
|
109
|
+
@statsd_host = Metrics.config[:statsd_host] || 'localhost'
|
110
|
+
@statsd_port = Metrics.config[:statsd_port] || 8125
|
111
|
+
end
|
112
|
+
|
113
|
+
def count(metric, value, sample_rate=1)
|
114
|
+
statsd.count(metric, value, sample_rate)
|
115
|
+
end
|
116
|
+
|
117
|
+
def timing(metric, value, sample_rate=1)
|
118
|
+
statsd.timing(metric, value, sample_rate)
|
119
|
+
end
|
120
|
+
|
121
|
+
def increment(metric, sample_rate=1)
|
122
|
+
statsd.increment(metric, sample_rate)
|
123
|
+
end
|
124
|
+
|
125
|
+
def decrement(metric, sample_rate=1)
|
126
|
+
statsd.decrement(metric, sample_rate)
|
127
|
+
end
|
128
|
+
|
129
|
+
def time(metric, sample_rate=1, &block)
|
130
|
+
statsd.time(metric, sample_rate, &block)
|
131
|
+
end
|
132
|
+
|
133
|
+
def log(collection, metrics)
|
134
|
+
mongo_collection(collection).save(metrics)
|
135
|
+
end
|
136
|
+
|
137
|
+
def aggregate(collection, pipeline=nil)
|
138
|
+
mongo_collection(collection).aggregate(pipeline)
|
139
|
+
end
|
140
|
+
|
141
|
+
def find(collection, selector={}, opts={})
|
142
|
+
mongo_collection(collection).find(selector, opts)
|
143
|
+
end
|
144
|
+
|
145
|
+
def collection_names
|
146
|
+
mongo_db.collection_names
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def mongo_client
|
152
|
+
@mongo_client ||= MongoClient.new(@mongo_host, @mongo_port)
|
153
|
+
end
|
154
|
+
|
155
|
+
def mongo_db
|
156
|
+
@mongo_db ||= mongo_client['maestro']
|
157
|
+
end
|
158
|
+
|
159
|
+
def mongo_collection(name)
|
160
|
+
mongo_db[name]
|
161
|
+
end
|
162
|
+
|
163
|
+
def statsd
|
164
|
+
@statsd ||= Statsd.new(@statsd_host, @statsd_port)
|
165
|
+
@statsd.namespace= 'maestro'
|
166
|
+
@statsd
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
class Mock
|
174
|
+
|
175
|
+
include Singleton
|
176
|
+
|
177
|
+
def count(metric, value, sample_rate=1)
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
def timing(metric, value, sample_rate=1)
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
def increment(metric, sample_rate=1)
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
def decrement(metric, sample_rate=1)
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
def time(metric, sample_rate=1, &block)
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
def log(collection, metrics)
|
198
|
+
-1
|
199
|
+
end
|
200
|
+
|
201
|
+
def aggregate(collection, pipeline=nil)
|
202
|
+
Array.new
|
203
|
+
end
|
204
|
+
|
205
|
+
def find(collection, selector={}, opts={})
|
206
|
+
Array.new
|
207
|
+
end
|
208
|
+
|
209
|
+
def collection_names
|
210
|
+
Array.new
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/maestro_metrics/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Etienne Pelletier"]
|
6
|
+
gem.email = ["epelletier@maestrodev.com"]
|
7
|
+
gem.description = "A gem used to log application metrics"
|
8
|
+
gem.summary = "Use this gem to record application run time metrics."
|
9
|
+
gem.homepage = "https://github.com/kellyp/maestro-metrics"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "maestro_metrics"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Maestro::Metrics::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency('mongo')
|
19
|
+
gem.add_dependency('statsd')
|
20
|
+
gem.add_dependency('statsd-ruby')
|
21
|
+
gem.add_development_dependency('rake')
|
22
|
+
gem.add_development_dependency('rspec')
|
23
|
+
gem.add_development_dependency('mongo_mapper')
|
24
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'maestro_metrics'
|
3
|
+
|
4
|
+
include Maestro
|
5
|
+
|
6
|
+
describe Maestro::Metrics do
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
Metrics.configure( { :mongo_host => '192.168.56.10', :statsd_host => '192.168.56.10' } )
|
10
|
+
end
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
Metrics.unmock!
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'Stats logging' do
|
17
|
+
|
18
|
+
@metric = 'test'
|
19
|
+
|
20
|
+
before(:each) do
|
21
|
+
|
22
|
+
@statsd = double('statsd')
|
23
|
+
Metrics::Real.instance.stub(:statsd => @statsd)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should log counts of things' do
|
27
|
+
value = 8
|
28
|
+
@statsd.should_receive(:count).with(@metric, value, 1)
|
29
|
+
Metrics.count(@metric, value)
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should increment a counter' do
|
34
|
+
@statsd.should_receive(:increment).with(@metric, 1)
|
35
|
+
Metrics.increment(@metric)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should decrement a counter' do
|
39
|
+
@statsd.should_receive(:decrement).with(@metric, 1)
|
40
|
+
Metrics.decrement(@metric)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
it 'should log timing stats' do
|
45
|
+
@statsd.should_receive(:timing).with(@metric, 1, 1)
|
46
|
+
Metrics.timing(@metric, 1)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should time the execution of a block of code' do
|
50
|
+
ran = false
|
51
|
+
|
52
|
+
proc = Proc.new do
|
53
|
+
ran = true
|
54
|
+
end
|
55
|
+
|
56
|
+
@statsd.should_receive(:time).with(@metric, 1, &proc)
|
57
|
+
Metrics.time(@metric,1, &proc)
|
58
|
+
ran.should be_true
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should do nothing when using a mock' do
|
63
|
+
Metrics.mock!
|
64
|
+
value = 8
|
65
|
+
@statsd.should_not_receive(:count)
|
66
|
+
Metrics.count(@metric, value)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'raw metrics logging' do
|
72
|
+
|
73
|
+
it 'should have a list of collections' do
|
74
|
+
|
75
|
+
|
76
|
+
collection_names = ["system.indexes", "runs", "counters.login.admin_10"]
|
77
|
+
Metrics::Real.instance.stub(:collection_names => collection_names)
|
78
|
+
|
79
|
+
names = Metrics.collection_names
|
80
|
+
names.should_not be_nil
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should log a hash containing raw metrics' do
|
85
|
+
|
86
|
+
@collection = double('collection')
|
87
|
+
Metrics::Real.instance.stub(:mongo_collection => @collection)
|
88
|
+
|
89
|
+
doc = { :name => 'testdoc' }
|
90
|
+
@collection.stub(:save => 1)
|
91
|
+
@collection.should_receive(:save).with(doc)
|
92
|
+
|
93
|
+
Metrics.log("test", doc).should eq 1
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should log a complex document' do
|
98
|
+
Metrics.mock!
|
99
|
+
|
100
|
+
require 'mongo_mapper'
|
101
|
+
|
102
|
+
doc = {
|
103
|
+
:id => 1,
|
104
|
+
:composition_id => 1,
|
105
|
+
:start_time => Time.to_mongo(Time.new),
|
106
|
+
:user=> 'maestro',
|
107
|
+
:trigger_type => 'manual',
|
108
|
+
:run_time => 1234,
|
109
|
+
:wait_time => 0,
|
110
|
+
:success => true,
|
111
|
+
:agent_name => 'some-agent',
|
112
|
+
:agent_host => 'agenthost.example.com',
|
113
|
+
:tasks => [
|
114
|
+
{
|
115
|
+
:task_id => 1,
|
116
|
+
:start_time => Time.to_mongo(Time.new),
|
117
|
+
:run_time => 1234,
|
118
|
+
:wait_time => 0,
|
119
|
+
:success => true
|
120
|
+
}
|
121
|
+
]
|
122
|
+
}
|
123
|
+
|
124
|
+
Metrics.log('runs', doc)
|
125
|
+
results = Metrics.aggregate('runs',
|
126
|
+
[ { '$group' => { '_id' => '$composition_id',
|
127
|
+
'numRuns' => { '$sum' => 1 },
|
128
|
+
'numSuccessfulRuns' => { '$sum' => { '$cond' => [ '$success', 1, 0 ] } },
|
129
|
+
'avgRunTime' => { '$avg' => '$run_time' },
|
130
|
+
'maxRunTime' => { '$max' => '$run_time' },
|
131
|
+
'minRunTime' => { '$min' => '$run_time' }
|
132
|
+
}
|
133
|
+
} ] )
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should correctly convert date to mongo' do
|
138
|
+
d = Date.new(2001, 2, 3)
|
139
|
+
u = d.to_time.utc
|
140
|
+
m = Maestro::Metrics.to_mongo(d)
|
141
|
+
|
142
|
+
m.should == u
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should correctly convert time to mongo' do
|
146
|
+
t = Time.parse("2001-02-03 04:05:06 -0800")
|
147
|
+
u = t.utc
|
148
|
+
m = Maestro::Metrics.to_mongo(t)
|
149
|
+
|
150
|
+
m.should == u
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should correctly convert string datetime to mongo' do
|
154
|
+
s = "2001-02-03 04:05:06"
|
155
|
+
u = Time.parse(s).utc
|
156
|
+
m = Maestro::Metrics.to_mongo(s)
|
157
|
+
|
158
|
+
m.should == u
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: maestro_metrics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Etienne Pelletier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mongo
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - '>='
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '0'
|
25
|
+
prerelease: false
|
26
|
+
type: :runtime
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: statsd
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
prerelease: false
|
40
|
+
type: :runtime
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: statsd-ruby
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
prerelease: false
|
54
|
+
type: :runtime
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
prerelease: false
|
68
|
+
type: :development
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
prerelease: false
|
82
|
+
type: :development
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mongo_mapper
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
prerelease: false
|
96
|
+
type: :development
|
97
|
+
description: A gem used to log application metrics
|
98
|
+
email:
|
99
|
+
- epelletier@maestrodev.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- .ruby-version
|
106
|
+
- Gemfile
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- lib/maestro_metrics.rb
|
110
|
+
- lib/maestro_metrics/version.rb
|
111
|
+
- maestro_metrics.gemspec
|
112
|
+
- spec/maestro_metrics_spec.rb
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
homepage: https://github.com/kellyp/maestro-metrics
|
115
|
+
licenses: []
|
116
|
+
metadata: {}
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 2.0.3
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: Use this gem to record application run time metrics.
|
137
|
+
test_files:
|
138
|
+
- spec/maestro_metrics_spec.rb
|
139
|
+
- spec/spec_helper.rb
|