ruby-metrics 0.8.6 → 0.9.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.
Files changed (41) hide show
  1. data/.bundle/config +1 -2
  2. data/.gitignore +2 -0
  3. data/.rvmrc +1 -1
  4. data/.travis.yml +5 -0
  5. data/CHANGELOG.md +48 -0
  6. data/Gemfile +8 -2
  7. data/README.md +2 -1
  8. data/Rakefile +20 -7
  9. data/examples/gmontest.rb +17 -0
  10. data/examples/opentsdb_reporter.rb +77 -0
  11. data/lib/ruby-metrics.rb +3 -4
  12. data/lib/ruby-metrics/agent.rb +72 -16
  13. data/lib/ruby-metrics/instruments/counter.rb +19 -12
  14. data/lib/ruby-metrics/instruments/gauge.rb +13 -9
  15. data/lib/ruby-metrics/instruments/histogram.rb +46 -45
  16. data/lib/ruby-metrics/instruments/meter.rb +29 -26
  17. data/lib/ruby-metrics/instruments/timer.rb +38 -37
  18. data/lib/ruby-metrics/integration.rb +3 -4
  19. data/lib/ruby-metrics/logging.rb +0 -2
  20. data/lib/ruby-metrics/reporter.rb +28 -0
  21. data/lib/ruby-metrics/statistics/exponential_sample.rb +4 -5
  22. data/lib/ruby-metrics/statistics/uniform_sample.rb +1 -2
  23. data/lib/ruby-metrics/time_units.rb +13 -11
  24. data/lib/ruby-metrics/version.rb +1 -1
  25. data/ruby-metrics-ganglia.gemspec +21 -0
  26. data/ruby-metrics-librato.gemspec +20 -0
  27. data/ruby-metrics-opentsdb.gemspec +21 -0
  28. data/ruby-metrics.gemspec +18 -15
  29. data/spec/agent_spec.rb +13 -4
  30. data/spec/instruments/meter_spec.rb +40 -3
  31. data/spec/instruments/timer_spec.rb +1 -1
  32. data/spec/spec_helper.rb +1 -1
  33. metadata +106 -105
  34. data/Gemfile.lock +0 -34
  35. data/lib/ruby-metrics/instruments.rb +0 -89
  36. data/lib/ruby-metrics/instruments/base.rb +0 -23
  37. data/lib/ruby-metrics/statistics/sample.rb +0 -21
  38. data/spec/instruments/base_spec.rb +0 -16
  39. data/spec/instruments_spec.rb +0 -76
  40. data/spec/integration/webrick_spec.rb +0 -18
  41. data/spec/statistics/sample_spec.rb +0 -22
@@ -1,32 +1,33 @@
1
- require File.join(File.dirname(__FILE__), '..', 'time_units')
1
+ require 'ruby-metrics/time_units'
2
2
 
3
3
  module Metrics
4
4
  module Instruments
5
- class Meter < Base
6
- include Metrics::TimeConversion
7
-
5
+ class Meter
6
+ include Metrics::TimeConversion
7
+
8
8
  # From http://www.teamquest.com/pdfs/whitepaper/ldavg2.pdf
9
9
  INTERVAL = 5.0
10
10
  INTERVAL_IN_NS = 5000000000.0
11
11
  ONE_MINUTE_FACTOR = 1 - Math.exp(-INTERVAL / 60.0)
12
12
  FIVE_MINUTE_FACTOR = 1 - Math.exp(-INTERVAL / (60.0 * 5.0))
13
13
  FIFTEEN_MINUTE_FACTOR = 1 - Math.exp(-INTERVAL / (60.0 * 15.0))
14
-
14
+
15
15
  attr_reader :count
16
+ attr_reader :units
16
17
  alias_method :counted, :count
17
-
18
+
18
19
  def initialize(options = {})
19
20
  @one_minute_rate = @five_minute_rate = @fifteen_minute_rate = 0.0
20
21
  @count = 0
21
22
  @initialized = false
22
23
  @start_time = Time.now.to_f
23
-
24
+ @units = "#{options[:units]}"
25
+
24
26
  @timer_thread = Thread.new do
25
- sleep_time = INTERVAL
26
27
  begin
27
28
  loop do
28
29
  self.tick
29
- sleep(sleep_time)
30
+ sleep(INTERVAL)
30
31
  end
31
32
  rescue Exception => e
32
33
  logger.error "Error in timer thread: #{e.class.name}: #{e}\n #{e.backtrace.join("\n ")}"
@@ -34,19 +35,19 @@ module Metrics
34
35
  end # thread new
35
36
 
36
37
  end
37
-
38
+
38
39
  def clear
39
40
  end
40
-
41
+
41
42
  def mark(count = 1)
42
43
  @count += count
43
44
  end
44
-
45
+
45
46
  def calc_rate(rate, factor, count)
46
47
  rate = rate.to_f + (factor.to_f * (count.to_f - rate.to_f))
47
48
  rate.to_f
48
49
  end
49
-
50
+
50
51
  def tick
51
52
  count = @count.to_f / Seconds.to_nsec(INTERVAL).to_f
52
53
 
@@ -58,42 +59,44 @@ module Metrics
58
59
  @one_minute_rate = @five_minute_rate = @fifteen_minute_rate = (count)
59
60
  @initialized = true
60
61
  end
61
-
62
+
62
63
  @count = 0
63
64
  end
64
-
65
+
65
66
  def one_minute_rate(rate_unit = :seconds)
66
67
  convert_to_ns @one_minute_rate, rate_unit
67
68
  end
68
-
69
+
69
70
  def five_minute_rate(rate_unit = :seconds)
70
71
  convert_to_ns @five_minute_rate, rate_unit
71
72
  end
72
-
73
+
73
74
  def fifteen_minute_rate(rate_unit = :seconds)
74
75
  convert_to_ns @fifteen_minute_rate, rate_unit
75
76
  end
76
-
77
+
77
78
  def mean_rate(rate_unit = :seconds)
78
79
  count = @count
79
80
  if count == 0
80
- return 0.0;
81
+ return 0.0
81
82
  else
82
83
  elapsed = Time.now.to_f - @start_time.to_f
83
- convert_to_ns (count.to_f / elapsed.to_f), rate_unit
84
+ mult = scale_time_units(:seconds, rate_unit)
85
+ count.to_f / (mult * elapsed.to_f)
84
86
  end
85
87
  end
86
-
87
- def to_json(*_)
88
+
89
+ def as_json(*_)
88
90
  {
89
91
  :one_minute_rate => self.one_minute_rate,
90
92
  :five_minute_rate => self.five_minute_rate,
91
93
  :fifteen_minute_rate => self.fifteen_minute_rate
92
- }.to_json
94
+ }
93
95
  end
94
-
95
- end
96
96
 
97
- register_instrument(:meter, Meter)
97
+ def to_json(*_)
98
+ as_json.to_json
99
+ end
100
+ end
98
101
  end
99
102
  end
@@ -2,39 +2,40 @@ require File.join(File.dirname(__FILE__), '..', 'time_units')
2
2
 
3
3
  module Metrics
4
4
  module Instruments
5
- class Timer < Base
6
- include Metrics::TimeConversion
7
-
8
- attr_reader :duration_unit, :rate_unit
9
-
5
+ class Timer
6
+ include Metrics::TimeConversion
7
+
8
+ attr_reader :duration_unit, :rate_unit, :units
9
+
10
10
  def initialize(options = {})
11
11
  @meter = Meter.new
12
12
  @histogram = ExponentialHistogram.new
13
13
 
14
14
  @duration_unit = options[:duration_unit] || :seconds
15
15
  @rate_unit = options[:rate_unit] || :seconds
16
+ @units = options[:units]
16
17
 
17
18
  clear
18
19
  end
19
-
20
+
20
21
  def clear
21
22
  @histogram.clear
22
23
  end
23
24
 
24
25
  def update(duration, unit)
25
26
  mult = convert_to_ns(1, unit)
26
- self.update_timer (duration * mult)
27
+ self.update_timer(duration * mult)
27
28
  end
28
29
 
29
- def time(&block)
30
+ def time(&block)
30
31
  start_time = Time.now.to_f
31
32
  result = block.call
32
33
  time_diff = Time.now.to_f - start_time
33
- time_in_ns = convert_to_ns time_diff, :seconds
34
+ time_in_ns = convert_to_ns time_diff, :seconds
34
35
  update_timer(time_in_ns)
35
36
  result
36
37
  end
37
-
38
+
38
39
  def count
39
40
  @histogram.count
40
41
  end
@@ -50,7 +51,7 @@ module Metrics
50
51
  def one_minute_rate
51
52
  @meter.one_minute_rate(@rate_unit)
52
53
  end
53
-
54
+
54
55
  def mean_rate
55
56
  @meter.mean_rate(@rate_unit)
56
57
  end
@@ -58,26 +59,26 @@ module Metrics
58
59
  def max
59
60
  scale_duration_to_ns @histogram.max, @duration_unit
60
61
  end
61
-
62
+
62
63
  def min
63
64
  scale_duration_to_ns @histogram.min, @duration_unit
64
65
  end
65
-
66
+
66
67
  def mean
67
68
  scale_duration_to_ns @histogram.mean, @duration_unit
68
69
  end
69
-
70
+
70
71
  def std_dev
71
72
  scale_duration_to_ns @histogram.std_dev, @duration_unit
72
73
  end
73
-
74
+
74
75
  def quantiles(percentiles = [0.99,0.97,0.95,0.75,0.5,0.25])
75
76
  result = {}
76
-
77
+
77
78
  @histogram.quantiles(percentiles).each do |k,v|
78
79
  result[k] = scale_duration_to_ns v, @duration_unit
79
80
  end
80
-
81
+
81
82
  result
82
83
  end
83
84
 
@@ -87,44 +88,44 @@ module Metrics
87
88
  @histogram.values.each do |value|
88
89
  result << (scale_duration_to_ns value, @duration_unit)
89
90
  end
90
-
91
+
91
92
  result
92
93
  end
93
-
94
+
94
95
  def update_timer(duration)
95
96
  if duration >= 0
96
97
  @histogram.update(duration)
97
98
  @meter.mark
98
99
  end
99
100
  end
100
-
101
- def to_json(*_)
101
+
102
+ def as_json(*_)
102
103
  {
103
- :count => self.count,
104
+ :count => count,
104
105
  :rates => {
105
- :one_minute_rate => self.one_minute_rate,
106
- :five_minute_rate => self.five_minute_rate,
107
- :fifteen_minute_rate => self.fifteen_minute_rate,
106
+ :one_minute_rate => one_minute_rate,
107
+ :five_minute_rate => five_minute_rate,
108
+ :fifteen_minute_rate => fifteen_minute_rate,
108
109
  :unit => @rate_unit
109
110
  },
110
- :durations => {
111
- :min => self.min,
112
- :max => self.max,
113
- :mean => self.mean,
114
- :percentiles => self.quantiles([0.25, 0.50, 0.75, 0.95, 0.97, 0.98, 0.99]),
111
+ :durations => {
112
+ :min => min,
113
+ :max => max,
114
+ :mean => mean,
115
+ :percentiles => quantiles([0.25, 0.50, 0.75, 0.95, 0.97, 0.98, 0.99]),
115
116
  :unit => @duration_unit
116
117
  }
117
- }.to_json
118
+ }
118
119
  end
119
-
120
+
121
+ def to_json(*_)
122
+ as_json.to_json
123
+ end
124
+
120
125
  private
121
126
  def scale_duration_to_ns(value, unit)
122
127
  value.to_f / convert_to_ns(1, unit).to_f
123
128
  end
124
-
125
129
  end
126
-
127
- register_instrument(:timer, Timer)
128
130
  end
129
- end
130
-
131
+ end
@@ -1,12 +1,11 @@
1
1
  module Metrics
2
2
  module Integration
3
3
 
4
- autoload :WEBrick, File.join(File.dirname(__FILE__), 'integration', 'webrick')
4
+ autoload :WEBrick, File.expand_path('../integration/webrick', __FILE__)
5
5
 
6
6
  module Rack
7
- autoload :Middleware, File.join(File.dirname(__FILE__), 'integration', 'rack_middleware')
8
- autoload :Endpoint, File.join(File.dirname(__FILE__), 'integration', 'rack_endpoint')
7
+ autoload :Middleware, File.expand_path('../integration/rack_middleware', __FILE__)
8
+ autoload :Endpoint, File.expand_path('../integration/rack_endpoint', __FILE__)
9
9
  end
10
-
11
10
  end
12
11
  end
@@ -1,5 +1,3 @@
1
- require 'logger'
2
-
3
1
  module Metrics
4
2
  module Logging
5
3
 
@@ -0,0 +1,28 @@
1
+ module Metrics
2
+ class Reporter
3
+ # Default reporting delay is 60 seconds
4
+ DEFAULT_REPORTING_DELAY = 60
5
+
6
+ include Logging
7
+
8
+ def initialize(options = {})
9
+
10
+ if options[:agent] == nil
11
+ raise "Need an agent to report data from"
12
+ end
13
+
14
+ delay = options[:delay] || DEFAULT_REPORTING_DELAY
15
+ agent = options[:agent]
16
+
17
+ Thread.new {
18
+ while(true)
19
+ agent.reporters.each do |name, service|
20
+ service.report(agent)
21
+ end
22
+ sleep delay
23
+ end
24
+ }.join
25
+ end
26
+
27
+ end
28
+ end
@@ -1,7 +1,6 @@
1
1
  module Metrics
2
2
  module Statistics
3
- class ExponentialSample < Sample
4
-
3
+ class ExponentialSample
5
4
  def initialize(size = 1028, alpha = 0.015)
6
5
  @values = Hash.new
7
6
  @count = 0
@@ -23,7 +22,7 @@ module Metrics
23
22
  end
24
23
 
25
24
  def tick
26
- return Time.now.to_f
25
+ Time.now.to_f
27
26
  end
28
27
 
29
28
  def update(value)
@@ -38,7 +37,7 @@ module Metrics
38
37
  @values[priority] = value
39
38
  else
40
39
  firstkey = @values.keys[0]
41
- if (firstkey < priority)
40
+ if firstkey && (firstkey < priority)
42
41
  @values[priority] = value
43
42
 
44
43
  while(@values.delete(firstkey) == nil)
@@ -85,7 +84,7 @@ module Metrics
85
84
  result << @values[key]
86
85
  end
87
86
 
88
- return result
87
+ result
89
88
  end
90
89
  end
91
90
  end
@@ -1,7 +1,6 @@
1
1
  module Metrics
2
2
  module Statistics
3
- class UniformSample < Sample
4
-
3
+ class UniformSample
5
4
  def initialize(size = 1028)
6
5
  @values = Array.new(size)
7
6
  @count = 0
@@ -43,19 +43,21 @@ module Metrics
43
43
  end
44
44
 
45
45
  module TimeConversion
46
-
46
+ UNITS = {
47
+ :nanoseconds => Nanoseconds,
48
+ :microseconds => Microseconds,
49
+ :milliseconds => Milliseconds,
50
+ :seconds => Seconds,
51
+ :minutes => Minutes,
52
+ :hours => Hours
53
+ }
47
54
 
48
55
  def convert_to_ns(value, unit)
49
- units = {
50
- :nanoseconds => Nanoseconds,
51
- :microseconds => Microseconds,
52
- :milliseconds => Milliseconds,
53
- :seconds => Seconds,
54
- :minutes => Minutes,
55
- :hours => Hours
56
- }
57
-
58
- return units[unit].to_nsec * value
56
+ (UNITS[unit].to_nsec.to_f * value.to_f)
57
+ end
58
+
59
+ def scale_time_units(source, dest)
60
+ (UNITS[source].to_nsec.to_f) / (UNITS[dest].to_nsec.to_f)
59
61
  end
60
62
  end
61
63
  end
@@ -1,3 +1,3 @@
1
1
  module Metrics
2
- VERSION = "0.8.6"
2
+ VERSION = '0.9.0'
3
3
  end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'ruby-metrics/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'ruby-metrics-ganglia'
7
+ s.version = Metrics::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['John Ewart']
10
+ s.email = ['john@johnewart.net']
11
+ s.homepage = 'https://github.com/johnewart/ruby-metrics'
12
+ s.summary = %q{Ganglia reporter for ruby-metrics}
13
+ s.description = %q{A reporter that uses Ganglia's to stash metric data}
14
+ s.license = 'MIT'
15
+
16
+ s.files = ['lib/ruby-metrics/reporters/ganglia.rb']
17
+ s.require_paths = ['lib']
18
+
19
+ s.add_dependency 'gmetric', '0.1.3'
20
+ s.add_dependency 'ruby-metrics', Metrics::VERSION
21
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'ruby-metrics/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'ruby-metrics-librato'
7
+ s.version = Metrics::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['John Ewart']
10
+ s.email = ['john@johnewart.net']
11
+ s.homepage = 'https://github.com/johnewart/ruby-metrics'
12
+ s.summary = %q{Librato reporter for ruby-metrics}
13
+ s.description = %q{A reporter that uses Librato to stash metric data}
14
+ s.license = 'MIT'
15
+
16
+ s.files = ['lib/ruby-metrics/reporters/librato.rb']
17
+ s.require_paths = ['lib']
18
+
19
+ s.add_dependency 'ruby-metrics', Metrics::VERSION
20
+ end