ruby-metrics 0.8.6 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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