yam-ruby-metrics 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitignore +4 -0
  3. data/.rvmrc +1 -0
  4. data/CHANGELOG.md +48 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +36 -0
  7. data/LICENSE +21 -0
  8. data/README.md +86 -0
  9. data/Rakefile +19 -0
  10. data/autotest/discover.rb +3 -0
  11. data/examples/counter.rb +10 -0
  12. data/examples/gauge.rb +25 -0
  13. data/examples/histogram.rb +32 -0
  14. data/examples/integration/rack_endpoint.ru +24 -0
  15. data/examples/integration/rack_middleware.ru +21 -0
  16. data/examples/integration/webrick.rb +17 -0
  17. data/examples/meter.rb +25 -0
  18. data/examples/timer.rb +31 -0
  19. data/lib/ruby-metrics.rb +15 -0
  20. data/lib/ruby-metrics/agent.rb +62 -0
  21. data/lib/ruby-metrics/instruments/counter.rb +39 -0
  22. data/lib/ruby-metrics/instruments/gauge.rb +23 -0
  23. data/lib/ruby-metrics/instruments/histogram.rb +188 -0
  24. data/lib/ruby-metrics/instruments/meter.rb +99 -0
  25. data/lib/ruby-metrics/instruments/timer.rb +138 -0
  26. data/lib/ruby-metrics/integration.rb +11 -0
  27. data/lib/ruby-metrics/integration/rack_endpoint.rb +33 -0
  28. data/lib/ruby-metrics/integration/rack_middleware.rb +82 -0
  29. data/lib/ruby-metrics/integration/webrick.rb +47 -0
  30. data/lib/ruby-metrics/logging.rb +19 -0
  31. data/lib/ruby-metrics/statistics/exponential_sample.rb +91 -0
  32. data/lib/ruby-metrics/statistics/uniform_sample.rb +37 -0
  33. data/lib/ruby-metrics/time_units.rb +61 -0
  34. data/lib/ruby-metrics/version.rb +3 -0
  35. data/ruby-metrics.gemspec +27 -0
  36. data/spec/agent_spec.rb +48 -0
  37. data/spec/instruments/counter_spec.rb +79 -0
  38. data/spec/instruments/gauge_spec.rb +42 -0
  39. data/spec/instruments/histogram_spec.rb +115 -0
  40. data/spec/instruments/meter_spec.rb +99 -0
  41. data/spec/instruments/timer_spec.rb +146 -0
  42. data/spec/integration/rack_endpoint_spec.rb +60 -0
  43. data/spec/integration/rack_middleware_spec.rb +129 -0
  44. data/spec/integration/webrick_spec.rb +18 -0
  45. data/spec/spec_helper.rb +18 -0
  46. data/spec/statistics/exponential_sample_spec.rb +138 -0
  47. data/spec/statistics/uniform_sample_spec.rb +59 -0
  48. data/spec/time_units_spec.rb +13 -0
  49. metadata +184 -0
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ coverage
2
+ *.gem
3
+ pkg/*
4
+ .DS_Store
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.2@metrics
data/CHANGELOG.md ADDED
@@ -0,0 +1,48 @@
1
+ v0.8.6 -- June 2, 2011
2
+ ======================
3
+
4
+ * Updated tests for JSON serialization of instruments
5
+ * Fixed JSON serialization of some instruments
6
+
7
+ v0.8.5 -- May 11, 2011
8
+ ======================
9
+
10
+ * Removed dependency on quantity gem -- conflicted with ActiveSupport
11
+ * Updated code to compute some unit conversions manually instead of depending on quantity
12
+
13
+
14
+ v0.8.0 -- April 26, 2011
15
+ ========================
16
+
17
+ * Added timer example
18
+ * Changes to timer initialization
19
+ * Added register_with_options to support timers with different units or options
20
+ * Integrated Matt's changes for integration to modularize webrick and rack export options
21
+
22
+ v0.7.0 -- April 18, 2011
23
+ ========================
24
+
25
+ * Replaced ruby-units with quantity
26
+ * Added time unit conversion internally
27
+ * Initial implementation of Timer instrument
28
+ * More spec tests to increase coverage
29
+
30
+
31
+ v0.6.0 -- April 15, 2011
32
+ ========================
33
+
34
+ * Exponentially decaying samples for histograms
35
+ * Updates to Meter to use exponentially decaying samples
36
+ * Ability to override WEBrick port in constructor
37
+ * Updates to README
38
+
39
+ v0.5.0 -- April 13, 2011
40
+ ========================
41
+
42
+ * Initial gem packaging (courtesy of @richardiux)
43
+ * Histograms
44
+ * Sampling classes for histograms
45
+ * Updates to weighted average calculations
46
+ * Tests, tests, tests!
47
+ * Mumblety-peg....
48
+
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in ruby-metrics.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rake'
8
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ruby-metrics (0.8.6)
5
+ json
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.2)
11
+ json (1.5.1)
12
+ rack (1.2.2)
13
+ rack-test (0.5.7)
14
+ rack (>= 1.0)
15
+ rake (0.8.7)
16
+ rspec (2.5.0)
17
+ rspec-core (~> 2.5.0)
18
+ rspec-expectations (~> 2.5.0)
19
+ rspec-mocks (~> 2.5.0)
20
+ rspec-core (2.5.1)
21
+ rspec-expectations (2.5.0)
22
+ diff-lcs (~> 1.1.2)
23
+ rspec-mocks (2.5.0)
24
+ simplecov (0.4.0)
25
+ simplecov-html (~> 0.4.0)
26
+ simplecov-html (0.4.3)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ rack-test
33
+ rake
34
+ rspec
35
+ ruby-metrics!
36
+ simplecov (>= 0.3.8)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011 John Ewart
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.
21
+
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+
2
+ ## What is this?
3
+
4
+ This is a Ruby version of performance metrics inspired by [metrics][metrics] developed by Coda Hale at Yammer. Currently this is under *heavy* development -- it needs Gem packaging, more features, validation of metrics, more functional testing, and a little better test coverage. Pull requests happily accepted, please include docs and tests where possible!
5
+
6
+ ## What needs to be done?
7
+
8
+ Among other important things, this needs to be made more thread-safe. I'm currently looking at Mr. Nutter's ruby-atomic gem for making this less tedious but any suggestions are welcome!
9
+
10
+ ## What's in this?
11
+
12
+ Right now, I have:
13
+
14
+ * Counters
15
+ * Meters
16
+ * Gauges
17
+ * Histograms w/ uniform sampling
18
+ * Histograms w/ exponentially decaying sampling
19
+ * Timers
20
+
21
+ ## Getting Started
22
+
23
+ The goal of ruby-metrics is to get up and running quickly. You start an agent, register some instruments, and they're exported over HTTP via JSON. For example, getting started with a counter would look like this:
24
+
25
+ @metrics = Metrics::Agent.new
26
+
27
+ counter = @metrics.counter :my_counter
28
+ counter.incr
29
+ counter.incr
30
+
31
+ puts @metrics.to_json
32
+ #=> {"my_counter":"2"}
33
+
34
+
35
+ ## Integration
36
+
37
+ Integrating ruby-metrics into existing applications is entirely up to your needs. Provided options include:
38
+
39
+ * Embedded WEBrick listener:
40
+
41
+ This runs a background thread and enables HTTP access to a local port (8001 by default) for a JSON representation of the current metrics.
42
+
43
+ ``` ruby
44
+ require 'ruby-metrics/integration/webrick'
45
+ @agent = Metrics::Agent.new
46
+ @agent.start(:port => 8081)
47
+ ```
48
+
49
+ * Rack Middleware:
50
+
51
+ This will add metrics such as `requests` (a timer) as well as counters for each class of HTTP status code (1xx, 2xx, etc). Also counts uncaught exceptions before reraising.
52
+ Provides a configurable path option (`:show`) to trigger the return of the metrics (as JSON) when the request path matches exactly (a string), as a regular expression, or as any object that responds to `call` for custom logic (passed the whole `env`).
53
+
54
+ ``` ruby
55
+ require 'ruby-metrics'
56
+ @agent = Metrics::Agent.new
57
+
58
+ use Metrics::Integration::Rack::Middleware, :agent => @agent, :show => '/stats'
59
+
60
+ run app
61
+ ```
62
+
63
+ * Rack Endpoint:
64
+
65
+ Use this to expose an endpoint for external consumption for your metrics.
66
+ Works best when used with a URLMap or mounted in addition to other routes, like Rails' `mount` route matcher.
67
+
68
+ ``` ruby
69
+ require 'ruby-metrics'
70
+ @agent = Metrics::Agent.new
71
+
72
+ run Metrics::Integration::Rack::Endpoint.new(:agent => @agent)
73
+ ```
74
+
75
+ or
76
+
77
+ ``` ruby
78
+ # in config/router.rb
79
+ mount Metrics::Integration::Rack::Endpoint.new(:agent => @agent)
80
+ ```
81
+
82
+ [metrics]: https://github.com/codahale/metrics
83
+
84
+ ## License
85
+
86
+ Copyright 2011 John Ewart <john@johnewart.net>. Released under the MIT license. See the file LICENSE for further details.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ require "rspec/core/rake_task"
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+
14
+ RSpec::Core::RakeTask.new do |t|
15
+ t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
16
+ t.pattern = 'spec/**/*_spec.rb'
17
+ end
18
+
19
+ task :default => :spec
@@ -0,0 +1,3 @@
1
+ Autotest.add_discovery do
2
+ "rspec2"
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require '../lib/ruby-metrics'
3
+
4
+ @metrics = Metrics::Agent.new
5
+
6
+ counter = @metrics.counter :my_counter
7
+ counter.incr
8
+ counter.incr
9
+
10
+ puts "Counter: #{counter.to_i}"
data/examples/gauge.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require '../lib/ruby-metrics'
3
+
4
+ @metrics = Metrics::Agent.new
5
+
6
+ hit_count = 42
7
+ http_requests = 53
8
+
9
+ gauge = @metrics.gauge :my_gauge do
10
+ {
11
+ :hit_count => hit_count,
12
+ :http_requests => http_requests
13
+ }
14
+ end
15
+
16
+ puts "Gauge: #{gauge.to_s}"
17
+
18
+ hit_count = 65
19
+ http_requests = 99
20
+
21
+ puts "Gauge: #{gauge.to_s}"
22
+
23
+ result = gauge.get
24
+
25
+ puts "Result: #{result}"
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require '../lib/ruby-metrics/integration/webrick'
3
+
4
+ @metrics = Metrics::Agent.new
5
+ @metrics.start
6
+
7
+ exponential_histogram = @metrics.exponential_histogram :exponential_histogram
8
+ uniform_histogram = @metrics.uniform_histogram :uniform_histogram
9
+
10
+ data = %w(3.600 1.800 3.333 2.283 4.533 2.883 4.700 3.600 1.950 4.350 1.833 3.917 4.200 1.750 4.700 2.167 1.750 4.800 1.600 4.250 1.800 1.750 3.450 3.067 4.533 3.600 1.967 4.083 3.850 4.433 4.300 4.467 3.367 4.033 3.833 2.017 1.867 4.833 1.833 4.783 4.350 1.883 4.567 1.750 4.533 3.317 3.833 2.100 4.633 2.000 4.800 4.716 1.833 4.833 1.733 4.883 3.717 1.667 4.567 4.317 2.233 4.500 1.750 4.800 1.817 4.400 4.167 4.700 2.067 4.700 4.033 1.967 4.500 4.000 1.983 5.067 2.017 4.567 3.883 3.600 4.133 4.333 4.100 2.633 4.067 4.933 3.950 4.517 2.167 4.000 2.200 4.333 1.867 4.817 1.833 4.300 4.667 3.750 1.867 4.900 2.483 4.367 2.100 4.500 4.050 1.867 4.700 1.783 4.850 3.683 4.733 2.300 4.900 4.417 1.700 4.633 2.317 4.600 1.817 4.417 2.617 4.067 4.250 1.967 4.600 3.767 1.917 4.500 2.267 4.650 1.867 4.167 2.800 4.333 1.833 4.383 1.883 4.933 2.033 3.733 4.233 2.233 4.533 4.817 4.333 1.983 4.633 2.017 5.100 1.800 5.033 4.000 2.400 4.600 3.567 4.000 4.500 4.083 1.800 3.967 2.200 4.150 2.000 3.833 3.500 4.583 2.367 5.000 1.933 4.617 1.917 2.083 4.583 3.333 4.167 4.333 4.500 2.417 4.000 4.167 1.883 4.583 4.250 3.767 2.033 4.433 4.083 1.833 4.417 2.183 4.800 1.833 4.800 4.100 3.966 4.233 3.500 4.366 2.250 4.667 2.100 4.350 4.133 1.867 4.600 1.783 4.367 3.850 1.933 4.500 2.383 4.700 1.867 3.833 3.417 4.233 2.400 4.800 2.000 4.150 1.867 4.267 1.750 4.483 4.000 4.117 4.083 4.267 3.917 4.550 4.083 2.417 4.183 2.217 4.450 1.883 1.850 4.283 3.950 2.333 4.150 2.350 4.933 2.900 4.583 3.833 2.083 4.367 2.133 4.350 2.200 4.450 3.567 4.500 4.150 3.817 3.917 4.450 2.000 4.283 4.767 4.533 1.850 4.250 1.983 2.250 4.750 4.117 2.150 4.417 1.817 4.467)
11
+ data.each do |point|
12
+ exponential_histogram.update(point.to_f)
13
+ uniform_histogram.update(point.to_f)
14
+ end
15
+
16
+ step = 0
17
+
18
+ # This is here so that we will run indefinitely so you can hit the
19
+ # status page on localhost:8001/stats
20
+ loop do
21
+ sleep 1
22
+
23
+ modifier = rand(500).to_i / 100
24
+ step += 1
25
+
26
+ if (step % 2)
27
+ modifier *= -1
28
+ end
29
+
30
+ uniform_histogram.update((2 + modifier).to_f)
31
+ exponential_histogram.update((2 + modifier).to_f)
32
+ end
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+
3
+ # Ran with:
4
+ # rackup -p 8000 ./examples/integration/rack_endpoint.ru
5
+ #
6
+ # Make requests to: http://localhost:8000/
7
+ # See stats at : http://localhost:8000/stats
8
+
9
+ require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ruby-metrics')
10
+ @agent = Metrics::Agent.new
11
+
12
+ counter = @agent.counter(:my_counter)
13
+
14
+ app = proc do |env|
15
+ counter.incr
16
+ [200, {'Content-Type' => 'text/plain'}, ["Counted!"]]
17
+ end
18
+
19
+ map = Rack::URLMap.new({
20
+ '/stats' => Metrics::Integration::Rack::Endpoint.new(:agent => @app),
21
+ '/' => app
22
+ })
23
+
24
+ run map
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+
3
+ # Ran with:
4
+ # rackup -p 8000 ./examples/integration/rack_middleware.ru
5
+ #
6
+ # Make requests to: http://localhost:8000/
7
+ # See stats at : http://localhost:8000/stats
8
+
9
+ require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ruby-metrics')
10
+ @agent = Metrics::Agent.new
11
+
12
+ counter = @agent.counter(:my_counter)
13
+
14
+ use Metrics::Integration::Rack::Middleware, :agent => @agent
15
+
16
+ app = proc do |env|
17
+ counter.incr
18
+ [200, {'Content-Type' => 'text/plain'}, ["Counted!"]]
19
+ end
20
+
21
+ run app
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ruby-metrics'))
3
+
4
+ # Run with:
5
+ # ruby examples/integration/webrick.rb
6
+
7
+ @agent = Metrics::Agent.new
8
+
9
+ counter = @agent.counter(:my_counter)
10
+ counter.incr
11
+ counter.incr
12
+
13
+ Metrics::Integration::WEBrick.start(:port => 8001,
14
+ :agent => @agent)
15
+
16
+ sleep
17
+ # Now navigate to: http://localhost:8001/stats
data/examples/meter.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require '../lib/ruby-metrics/integration/webrick'
3
+
4
+ @metrics = Metrics::Agent.new
5
+ @metrics.start :port => 8081 # optional
6
+
7
+ timer = @metrics.meter :my_meter
8
+ timer.mark(500)
9
+
10
+ step = 0
11
+
12
+ # This is here so that we will run indefinitely so you can hit the
13
+ # status page on localhost:8081/stats
14
+ loop do
15
+ sleep 1
16
+
17
+ modifier = rand(200).to_i
18
+ step += 1
19
+
20
+ if (step % 2)
21
+ modifier *= -1
22
+ end
23
+
24
+ timer.mark(500 + modifier)
25
+ end
data/examples/timer.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require '../lib/ruby-metrics/integration/webrick'
3
+
4
+ @metrics = Metrics::Agent.new
5
+ @metrics.start :port => 8081 # optional
6
+
7
+ timer = @metrics.timer :my_timer
8
+ timer.update(500, :milliseconds)
9
+ timer.update(5, :seconds)
10
+ timer.update(4242, :nanoseconds)
11
+
12
+ msec_timer = @metrics.timer :msec_timer, {:duration_unit => :microseconds, :rate_unit => :seconds}
13
+
14
+ step = 0
15
+
16
+ # This is here so that we will run indefinitely so you can hit the
17
+ # status page on localhost:8081/stats
18
+ loop do
19
+ sleep 1
20
+
21
+ modifier = rand(200).to_i
22
+ step += 1
23
+
24
+ if (step % 2)
25
+ modifier *= -1
26
+ end
27
+
28
+ timer.update(500 + modifier, :microseconds)
29
+ msec_timer.update(500 + modifier, :microseconds)
30
+
31
+ end