mouth-instrument 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.
@@ -0,0 +1,7 @@
1
+ .rvmrc
2
+ *.log
3
+ *.pid
4
+ log/*.log
5
+ log/*.pid
6
+ Gemfile.lock
7
+ *.gem
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Jonathan Novak - http://github.com/cypriss
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,43 @@
1
+ # mouth-instrument
2
+
3
+ Mouth-instrument is a very lightweight Ruby gem that you can use to instrument your apps to collect metrics. It sends these metrics via UDP to a [mouth](http://www.github.com/cypriss/mouth) daemon for storage and analysis.
4
+
5
+ ## What is Mouth?
6
+
7
+ [Mouth](http://www.github.com/cypriss/mouth) is a Ruby daemon that collects metrics via UDP and stores them in Mongo. It comes with a modern UI that allows you to view graphs and create dashboards of these statistics.
8
+
9
+ ## Using mouth-instrument
10
+
11
+ First, install the gem via your Gemfile or do so manually:
12
+
13
+ gem install mouth-instrument
14
+
15
+ Then, include it in your app:
16
+
17
+ require 'mouth-instrument'
18
+
19
+ Configure it to point to your daemon. In a Rails app, you might want to put this in config/initializers/mouth.rb
20
+
21
+ Mouth.daemon_hostport = "localhost:8889"
22
+
23
+ Then, instrument your app:
24
+
25
+ # Count things like this:
26
+ Mouth.increment("myapp.occurrences") # Basic
27
+ Mouth.increment("myapp.occurrences", 10) # Occurrences occurred 10 times!
28
+ Mouth.increment("myapp.occurrences", 1, 0.1) # Sample at a 1/10 rate. Lose a bit of accuracy, but sends less packets. Good for super-high volume metrics.
29
+
30
+ # Measure timings like this:
31
+ Mouth.measure("myapp.happening") do
32
+ do_happening!
33
+ end
34
+
35
+ # Or, like this (23.9 is in milliseconds):
36
+ Mouth.measure("myapp.happening", 23.9)
37
+
38
+ # Gauge values like this:
39
+ Mouth.gauge("myapp.subscriber_count", 1230) # I have 1230 customers right now!
40
+
41
+ ## View your metrics
42
+
43
+ Please see the [Mouth](http://www.github.com/cypriss/mouth) project for more information! This gem plays a supporting role to core Mouth gem.
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new('test') do |t|
4
+ t.ruby_opts << '-rubygems'
5
+ t.libs << 'lib'
6
+ t.test_files = FileList['test/*.rb']
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,63 @@
1
+ require 'socket'
2
+ require 'benchmark'
3
+
4
+ module Mouth
5
+
6
+ INSTRUMENT_VERSION = '1.0.0'
7
+
8
+ unless self.respond_to?(:measure)
9
+ class << self
10
+ attr_accessor :daemon_host, :daemon_port, :disabled
11
+
12
+ # Mouth.server = 'localhost:1234'
13
+ def daemon_hostport=(hostport)
14
+ self.daemon_host, port = hostport.split(':')
15
+ self.daemon_port = port.to_i
16
+ end
17
+
18
+ def daemon_host
19
+ @daemon_host || "localhost"
20
+ end
21
+
22
+ def daemon_port
23
+ @daemon_port || 8889
24
+ end
25
+
26
+ def measure(key, milli = nil)
27
+ result = nil
28
+ ms = milli || (Benchmark.realtime { result = yield } * 1000).to_i
29
+
30
+ write(key, ms, :ms)
31
+
32
+ result
33
+ end
34
+
35
+ def increment(key, delta = 1, sample_rate = nil)
36
+ write(key, delta, :c, sample_rate)
37
+ end
38
+
39
+ def gauge(key, value)
40
+ write(key, value, :g)
41
+ end
42
+
43
+ protected
44
+
45
+ def socket
46
+ @socket ||= UDPSocket.new
47
+ end
48
+
49
+ def write(k, v, op, sample_rate = nil)
50
+ return if self.disabled
51
+ if sample_rate
52
+ sample_rate = 1 if sample_rate > 1
53
+ return if rand > sample_rate
54
+ end
55
+
56
+ command = "#{k}:#{v}|#{op}"
57
+ command << "|@#{sample_rate}" if sample_rate
58
+
59
+ socket.send(command, 0, self.daemon_host, self.daemon_port)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,14 @@
1
+ require './lib/mouth-instrument'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'mouth-instrument'
5
+ s.version = Mouth::INSTRUMENT_VERSION
6
+ s.author = 'Jonathan Novak'
7
+ s.email = 'jnovak@gmail.com'
8
+ s.homepage = 'http://github.com/cypriss/mouth-instrument'
9
+ s.summary = 'Instrument your app to send metrics to a Mouth'
10
+ s.description = 'Instrument your app to send metrics to a Mouth. Sends UDP packets to Mouth for Counters, Timers, and Gauges.'
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files test`.split("\n")
14
+ end
@@ -0,0 +1,79 @@
1
+ $LOAD_PATH.unshift 'test'
2
+ require 'test_helper'
3
+
4
+ class MouthInstrumentTest < Test::Unit::TestCase
5
+ def setup
6
+ @@udp ||= UDPSocket.new.tap do |u|
7
+ u.bind("127.0.0.1", 32123)
8
+ end
9
+ @udp = @@udp
10
+ Mouth.daemon_hostport = "127.0.0.1:32123"
11
+ end
12
+
13
+ def test_increment
14
+ Mouth.increment("bob")
15
+
16
+ res = @udp.recvfrom(1024)
17
+ assert_equal "bob:1|c", res[0]
18
+ end
19
+
20
+ def test_increment_delta
21
+ Mouth.increment("bob.rob", 123)
22
+
23
+ res = @udp.recvfrom(1024)
24
+ assert_equal "bob.rob:123|c", res[0]
25
+ end
26
+
27
+ def test_increment_sample
28
+ # Clear out anything on the UDP packet
29
+ 100.times { @udp.recvfrom_nonblock(1024) } rescue nil
30
+
31
+ pack = nil
32
+ nothing = false
33
+
34
+ 100.times do
35
+ Mouth.increment("bob.rob/blah-haha", 123, 0.1)
36
+
37
+ begin
38
+ pack ||= @udp.recvfrom_nonblock(1024)
39
+ break if nothing
40
+ rescue IO::WaitReadable
41
+ nothing = true
42
+ end
43
+ end
44
+
45
+ assert nothing
46
+ assert_equal "bob.rob/blah-haha:123|c|@0.1", pack[0]
47
+ end
48
+
49
+ def test_gauge
50
+ Mouth.gauge("bob", 77)
51
+
52
+ res = @udp.recvfrom(1024)
53
+ assert_equal "bob:77|g", res[0]
54
+ end
55
+
56
+ def test_measure
57
+ Mouth.measure("bob", 1.2)
58
+
59
+ res = @udp.recvfrom(1024)
60
+ assert_equal "bob:1.2|ms", res[0]
61
+ end
62
+
63
+ def test_measure_block
64
+ result = Mouth.measure("bob") do
65
+ sleep 0.2
66
+ 9876
67
+ end
68
+
69
+ assert_equal 9876, result
70
+
71
+ res = @udp.recvfrom(1024)[0]
72
+ m = res.match(/bob:(\d+)\|ms/)
73
+ assert m
74
+
75
+ # Make sure the number is within a resonable range
76
+ assert m[1].to_i > 180
77
+ assert m[1].to_i < 220
78
+ end
79
+ end
@@ -0,0 +1,5 @@
1
+ require 'test/unit'
2
+ require 'pp'
3
+
4
+ $LOAD_PATH.unshift 'lib'
5
+ require 'mouth-instrument'
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mouth-instrument
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jonathan Novak
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-07 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Instrument your app to send metrics to a Mouth. Sends UDP packets to
15
+ Mouth for Counters, Timers, and Gauges.
16
+ email: jnovak@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - MIT-LICENSE
23
+ - README.md
24
+ - Rakefile
25
+ - lib/mouth-instrument.rb
26
+ - mouth-instrument.gemspec
27
+ - test/mouth-instrument_test.rb
28
+ - test/test_helper.rb
29
+ homepage: http://github.com/cypriss/mouth-instrument
30
+ licenses: []
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 1.8.17
50
+ signing_key:
51
+ specification_version: 3
52
+ summary: Instrument your app to send metrics to a Mouth
53
+ test_files:
54
+ - test/mouth-instrument_test.rb
55
+ - test/test_helper.rb