librato-rack 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
@@ -1,2 +1 @@
1
- *�2VbGD��C����e:�?�TS���PQo�DžѬy1Ww���G^(m8Ĝ�̶��ar|Em%Z�~��m�`5�HX�ŘKhC�-|,Ӑ_���<
2
- QU�1(��h̜{�ּb=?gְ���� v5"��͊"ҳv����!�l6�B���h�Yް��Ț,�s���j~]|���_*N�$Z�� P\��n=j�
1
+ fI>�j.;8Q:�sj���atL���0_g������R-���%� ���ζ }���L�ơ��`�+ Ǒ�aH!��o��1�i �n�)p%xG���/
@@ -1,3 +1,13 @@
1
+ ### Version 0.4.0
2
+ * Add HTTP method (GET, POST) metrics
3
+ * Add log buffering support
4
+ * Ensure all options passed to a grouped increment are respected
5
+ * LIBRATO_AUTORUN can be used to prevent startup
6
+ * Add ability to interrupt reporter process
7
+ * Start reporting deprecations for old config methods
8
+ * Add docs for best practices for background workers
9
+ * Other documentation improvements
10
+
1
11
  ### Version 0.3.0
2
12
  * Add experimental support for EventMachine and EMSynchrony (Balwant K)
3
13
  * Start testing suite against jruby/rbx
data/LICENSE CHANGED
@@ -8,9 +8,9 @@ modification, are permitted provided that the following conditions are met:
8
8
  * Redistributions in binary form must reproduce the above copyright
9
9
  notice, this list of conditions and the following disclaimer in the
10
10
  documentation and/or other materials provided with the distribution.
11
- * Neither the name of the <organization> nor the
12
- names of its contributors may be used to endorse or promote products
13
- derived from this software without specific prior written permission.
11
+ * Neither the name of Librato, Inc. nor the names of its contributors
12
+ may be used to endorse or promote products derived from this software
13
+ without specific prior written permission.
14
14
 
15
15
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
16
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
data/README.md CHANGED
@@ -49,6 +49,7 @@ By default you can use `LIBRATO_USER` and `LIBRATO_TOKEN` to pass your account d
49
49
 
50
50
  * `LIBRATO_SOURCE` - the default source to use for submitted metrics. If this is not set, hostname of the executing machine will be the default source
51
51
  * `LIBRATO_PREFIX` - a prefix which will be prepended to all metric names
52
+ * `LIBRATO_AUTORUN` - set to `'0'` to prevent the reporter from starting, useful if you don't want `librato-rack` to start under certain circumstances
52
53
  * `LIBRATO_LOG_LEVEL` - see logging section for more
53
54
  * `LIBRATO_EVENT_MODE` - use with evented apps, see "Use with EventMachine" below
54
55
 
@@ -148,6 +149,12 @@ Can also be written as:
148
149
 
149
150
  Symbols can be used interchangeably with strings for metric names.
150
151
 
152
+ ## Use with Background Workers / Cron Jobs
153
+
154
+ `librato-rack` is designed to run within a long-running process and report periodically. Intermittently running rake tasks and most background job tools (delayed job, resque, queue_classic) don't run long enough for this to work.
155
+
156
+ Never fear, [we have some guidelines](https://github.com/librato/librato-rails/wiki/Monitoring-Background-Workers) for how to instrument your workers properly.
157
+
151
158
  ## Cross-Process Aggregation
152
159
 
153
160
  `librato-rack` submits measurements back to the Librato platform on a _per-process_ basis. By default these measurements are then combined into a single measurement per source (default is your hostname) before persisting the data.
@@ -13,9 +13,9 @@ module Librato
13
13
  yield self.class.new(@collector, prefix)
14
14
  end
15
15
 
16
- def increment(counter, by=1)
16
+ def increment(counter, options={})
17
17
  counter = "#{@prefix}#{counter}"
18
- @collector.increment counter, by
18
+ @collector.increment counter, options
19
19
  end
20
20
 
21
21
  def measure(*args, &block)
@@ -27,31 +27,50 @@ module Librato
27
27
  # run lambda { |env| [200, {"Content-Type" => 'text/html'}, ["Hello!"]] }
28
28
  # end
29
29
  #
30
+ # @example Using a custom config object
31
+ # config = Librato::Rack::Configuration.new
32
+ # config.user = 'myuser@mysite.com'
33
+ # config.token = 'mytoken'
34
+ # …more configuration
35
+ #
36
+ # use Librato::Rack, :config => config
37
+ # run MyApp
38
+ #
30
39
  class Rack
31
40
  attr_reader :config, :tracker
32
41
 
33
42
  def initialize(app, options={})
43
+ old_style = false
34
44
  if options.respond_to?(:tracker) # old-style single argument
35
45
  config = options
46
+ old_style = true
36
47
  else
37
48
  config = options.fetch(:config, Configuration.new)
38
49
  end
39
50
  @app, @config = app, config
40
51
  @tracker = Tracker.new(@config)
41
52
  Librato.register_tracker(@tracker) # create global reference
53
+
54
+ if old_style
55
+ @tracker.deprecate 'middleware setup no longer takes a single argument, use `use Librato::Rack :config => config` instead.'
56
+ end
42
57
  end
43
58
 
44
59
  def call(env)
45
- check_log_output(env)
60
+ check_log_output(env) unless @log_target
46
61
  @tracker.check_worker
62
+ request_method = env["REQUEST_METHOD"]
47
63
  record_header_metrics(env)
48
64
  response, duration = process_request(env)
49
- record_request_metrics(response.first, duration)
65
+ record_request_metrics(response.first, request_method, duration)
50
66
  response
51
67
  end
52
68
 
53
69
  private
54
70
 
71
+ # this generally will only get called on the first request
72
+ # it figures out the environment-appropriate logging outlet
73
+ # and notifies config and tracker about it
55
74
  def check_log_output(env)
56
75
  return if @log_target
57
76
  if in_heroku_env?
@@ -60,7 +79,7 @@ module Librato
60
79
  else
61
80
  default = env['rack.errors'] || $stderr
62
81
  end
63
- config.log_target ||= default
82
+ @tracker.update_log_target(config.log_target ||= default)
64
83
  @log_target = config.log_target
65
84
  end
66
85
 
@@ -82,10 +101,21 @@ module Librato
82
101
  end
83
102
 
84
103
  def record_header_metrics(env)
85
- # TODO: track generalized queue wait
104
+ queue_start = env['HTTP_X_REQUEST_START'] || env['HTTP_X_QUEUE_START']
105
+ if queue_start
106
+ queue_start = queue_start.to_s.gsub('t=', '').to_i
107
+ case queue_start.to_s.length
108
+ when 16 # microseconds
109
+ wait = ((Time.now.to_f * 1000000).to_i - queue_start) / 1000.0
110
+ tracker.timing 'rack.request.queue.time', wait
111
+ when 13 # milliseconds
112
+ wait = (Time.now.to_f * 1000).to_i - queue_start
113
+ tracker.timing 'rack.request.queue.time', wait
114
+ end
115
+ end
86
116
  end
87
117
 
88
- def record_request_metrics(status, duration)
118
+ def record_request_metrics(status, http_method, duration)
89
119
  return if config.disable_rack_metrics
90
120
  tracker.group 'rack.request' do |group|
91
121
  group.increment 'total'
@@ -99,6 +129,12 @@ module Librato
99
129
  s.timing "#{status}.time", duration
100
130
  s.timing "#{status.to_s[0]}xx.time", duration
101
131
  end
132
+
133
+ group.group 'method' do |m|
134
+ http_method.downcase!
135
+ m.increment http_method
136
+ m.timing "#{http_method}.time", duration
137
+ end
102
138
  end
103
139
  end
104
140
 
@@ -12,10 +12,10 @@ module Librato
12
12
  class Configuration
13
13
  EVENT_MODES = [:eventmachine, :synchrony]
14
14
 
15
- attr_accessor :user, :token, :api_endpoint, :tracker, :source_pids,
16
- :log_level, :flush_interval, :log_target,
15
+ attr_accessor :user, :token, :autorun, :api_endpoint, :tracker,
16
+ :source_pids, :log_level, :flush_interval, :log_target,
17
17
  :disable_rack_metrics
18
- attr_reader :prefix, :source
18
+ attr_reader :prefix, :source, :deprecations
19
19
 
20
20
  def initialize
21
21
  # set up defaults
@@ -24,14 +24,17 @@ module Librato
24
24
  self.flush_interval = 60
25
25
  self.source_pids = false
26
26
  @listeners = []
27
+ @deprecations = []
27
28
 
28
29
  # check environment
29
30
  self.user = ENV['LIBRATO_USER'] || ENV['LIBRATO_METRICS_USER']
30
31
  self.token = ENV['LIBRATO_TOKEN'] || ENV['LIBRATO_METRICS_TOKEN']
32
+ self.autorun = detect_autorun
31
33
  self.prefix = ENV['LIBRATO_PREFIX'] || ENV['LIBRATO_METRICS_PREFIX']
32
34
  self.source = ENV['LIBRATO_SOURCE'] || ENV['LIBRATO_METRICS_SOURCE']
33
35
  self.log_level = ENV['LIBRATO_LOG_LEVEL'] || :info
34
36
  self.event_mode = ENV['LIBRATO_EVENT_MODE']
37
+ check_deprecations
35
38
  end
36
39
 
37
40
  def event_mode
@@ -76,6 +79,31 @@ module Librato
76
79
  fields
77
80
  end
78
81
 
82
+ private
83
+
84
+ def check_deprecations
85
+ %w{USER TOKEN PREFIX SOURCE}.each do |item|
86
+ if ENV["LIBRATO_METRICS_#{item}"]
87
+ deprecate "LIBRATO_METRICS_#{item} will be removed in a future release, please use LIBRATO_#{item} instead."
88
+ end
89
+ end
90
+ end
91
+
92
+ def deprecate(message)
93
+ @deprecations << message
94
+ end
95
+
96
+ def detect_autorun
97
+ case ENV['LIBRATO_AUTORUN']
98
+ when '0', 'FALSE'
99
+ false
100
+ when '1', 'TRUE'
101
+ true
102
+ else
103
+ nil
104
+ end
105
+ end
106
+
79
107
  end
80
108
  end
81
109
  end
@@ -8,10 +8,12 @@ module Librato
8
8
  class Logger
9
9
  LOG_LEVELS = [:off, :error, :warn, :info, :debug, :trace]
10
10
 
11
- attr_accessor :logger, :prefix
11
+ attr_accessor :prefix
12
+ attr_reader :outlet
12
13
 
13
- def initialize(logger)
14
- self.logger = logger
14
+ def initialize(outlet=nil)
15
+ @buffer = []
16
+ self.outlet = outlet
15
17
  self.prefix = '[librato-rack] '
16
18
  end
17
19
 
@@ -24,12 +26,10 @@ module Librato
24
26
  def log(level, message=nil, &block)
25
27
  return unless should_log?(level)
26
28
  message = prefix + (message || block.call)
27
- if logger.respond_to?(:puts) # io obj
28
- logger.puts(message)
29
- elsif logger.respond_to?(:error) # logger obj
30
- log_to_logger(level, message)
29
+ if outlet.nil?
30
+ buffer(level, message)
31
31
  else
32
- raise "invalid logger object"
32
+ write_to_outlet(level, message)
33
33
  end
34
34
  end
35
35
 
@@ -48,8 +48,21 @@ module Librato
48
48
  @log_level ||= :info
49
49
  end
50
50
 
51
+ def outlet=(outlet)
52
+ @outlet = outlet
53
+ flush_buffer unless (outlet.nil? || @buffer.empty?)
54
+ end
55
+
51
56
  private
52
57
 
58
+ def buffer(level, message)
59
+ @buffer << [level, message]
60
+ end
61
+
62
+ def flush_buffer
63
+ @buffer.each { |buffered| write_to_outlet(*buffered) }
64
+ end
65
+
53
66
  # write message to an ruby stdlib logger object or another class with
54
67
  # similar interface, respecting log levels when we can map them
55
68
  def log_to_logger(level, message)
@@ -59,13 +72,23 @@ module Librato
59
72
  else
60
73
  method = :info
61
74
  end
62
- logger.send(method, message)
75
+ outlet.send(method, message)
63
76
  end
64
77
 
65
78
  def should_log?(level)
66
79
  LOG_LEVELS.index(self.log_level) >= LOG_LEVELS.index(level)
67
80
  end
68
81
 
82
+ def write_to_outlet(level, message)
83
+ if outlet.respond_to?(:puts) # io obj
84
+ outlet.puts(message)
85
+ elsif outlet.respond_to?(:error) # logger obj
86
+ log_to_logger(level, message)
87
+ else
88
+ raise "invalid outlet: not a Logger or IO object"
89
+ end
90
+ end
91
+
69
92
  end
70
93
  end
71
94
  end
@@ -34,6 +34,8 @@ module Librato
34
34
  @worker.run_periodically(config.flush_interval) do
35
35
  flush
36
36
  end
37
+
38
+ config.deprecations.each { |d| deprecate(d) }
37
39
  end
38
40
 
39
41
  # primary collector object used by this tracker
@@ -41,6 +43,11 @@ module Librato
41
43
  @collector ||= Librato::Collector.new
42
44
  end
43
45
 
46
+ # log a deprecation message
47
+ def deprecate(message)
48
+ log :warn, "DEPRECATION: #{message}"
49
+ end
50
+
44
51
  # send all current data to Metrics
45
52
  def flush
46
53
  log :debug, "flushing pid #{@pid} (#{Time.now}).."
@@ -58,6 +65,11 @@ module Librato
58
65
  config.source_pids ? "#{source}.#{$$}" : source
59
66
  end
60
67
 
68
+ # change output stream for logging
69
+ def update_log_target(target)
70
+ logger.outlet = target
71
+ end
72
+
61
73
  private
62
74
 
63
75
  # access to client instance
@@ -123,16 +135,16 @@ module Librato
123
135
  if !config.user || !config.token
124
136
  # don't show this unless we're debugging, expected behavior
125
137
  log :debug, 'halting: credentials not present.'
126
- false
138
+ elsif config.autorun == false
139
+ log :debug, 'halting: LIBRATO_AUTORUN disabled startup'
127
140
  elsif qualified_source !~ SOURCE_REGEX
128
141
  log :warn, "halting: '#{qualified_source}' is an invalid source name."
129
- false
130
142
  elsif on_heroku && !config.explicit_source?
131
143
  log :warn, 'halting: source must be provided in configuration.'
132
- false
133
144
  else
134
- true
145
+ return true
135
146
  end
147
+ false
136
148
  end
137
149
 
138
150
  def source
@@ -1,5 +1,5 @@
1
1
  module Librato
2
2
  class Rack
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -10,9 +10,12 @@ module Librato
10
10
  # available options:
11
11
  # * timer - type of timer to use, valid options are
12
12
  # :sleep (default), :eventmachine, or :synchrony
13
+ # * sync - try to synchronize timer executions to whole
14
+ # minutes or subdivisions thereof
13
15
  def initialize(options={})
14
16
  @interrupt = false
15
17
  @timer = (options[:timer] || :sleep).to_sym
18
+ @sync = options[:sync] || false
16
19
  end
17
20
 
18
21
  # run the given block every <period> seconds, looping
@@ -32,18 +35,36 @@ module Librato
32
35
  # they will be in sync.
33
36
  #
34
37
  def start_time(period)
35
- earliest = Time.now + period
36
- # already on a whole minute
37
- return earliest if earliest.sec == 0
38
- if period > 30
39
- # bump to whole minute
40
- earliest + (60-earliest.sec)
38
+ if @sync
39
+ earliest = Time.now + period
40
+ # already on a whole minute
41
+ return earliest if earliest.sec == 0
42
+ if period > 30
43
+ # bump to whole minute
44
+ earliest + (60-earliest.sec)
45
+ else
46
+ # ensure sync to whole minute if minute is evenly divisible
47
+ earliest + (period-(earliest.sec%period))
48
+ end
41
49
  else
42
- # ensure sync to whole minute if minute is evenly divisible
43
- earliest + (period-(earliest.sec%period))
50
+ if period > 30
51
+ # ensure some wobble in start times,
52
+ # trade a slightly irregular first period for a more even
53
+ # distribution for network requests between processes
54
+ start = Time.now
55
+ start + (60-start.sec) + rand(60)
56
+ else
57
+ Time.now + period
58
+ end
44
59
  end
45
60
  end
46
61
 
62
+ # stop worker loop at the beginning of the next round
63
+ # of execution
64
+ def stop!
65
+ @interrupt = true
66
+ end
67
+
47
68
  private
48
69
 
49
70
  # run continuous loop executing every <period>, will start
@@ -0,0 +1,38 @@
1
+ require 'bundler/setup'
2
+ require 'librato-rack'
3
+
4
+ # Simulate the environment variables Heroku passes along
5
+ # with each request
6
+ #
7
+ class QueueWait
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ case env['PATH_INFO']
14
+ when '/milli'
15
+ env['HTTP_X_REQUEST_START'] = (Time.now.to_f * 1000).to_i.to_s
16
+ sleep 0.005
17
+ when '/micro'
18
+ env['HTTP_X_REQUEST_START'] = (Time.now.to_f * 1000000).to_i.to_s
19
+ sleep 0.01
20
+ when '/queue_start'
21
+ env['HTTP_X_QUEUE_START'] = (Time.now.to_f * 1000).to_i.to_s
22
+ sleep 0.015
23
+ when '/with_t'
24
+ env['HTTP_X_REQUEST_START'] = "t=#{(Time.now.to_f * 1000000).to_i}".to_s
25
+ sleep 0.02
26
+ end
27
+ @app.call(env)
28
+ end
29
+ end
30
+
31
+ use QueueWait
32
+ use Librato::Rack
33
+
34
+ def application(env)
35
+ [200, {"Content-Type" => 'text/html'}, ["Hello!"]]
36
+ end
37
+
38
+ run method(:application)
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
  require 'rack/test'
3
3
 
4
- # Tests for universal tracking for all request paths
4
+ # Tests to ensure config.disable_rack_metrics disables stats
5
5
  #
6
6
  class NoStatsTest < Minitest::Test
7
7
  include Rack::Test::Methods
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+ require 'rack/test'
3
+
4
+ # Tests for universal tracking for all request paths
5
+ #
6
+ class QueueWaitTest < Minitest::Test
7
+ include Rack::Test::Methods
8
+
9
+ def app
10
+ Rack::Builder.parse_file('test/apps/queue_wait.ru').first
11
+ end
12
+
13
+ def teardown
14
+ # clear metrics before each run
15
+ aggregate.delete_all
16
+ counters.delete_all
17
+ end
18
+
19
+ def test_milliseconds
20
+ get '/milli'
21
+
22
+ # puts "milli: #{aggregate["rack.request.queue.time"].inspect}"
23
+ assert_equal 1, aggregate["rack.request.queue.time"][:count],
24
+ 'should track total queue time'
25
+ assert_in_delta 5, aggregate["rack.request.queue.time"][:sum], 4
26
+ end
27
+
28
+ def test_microseconds
29
+ get '/micro'
30
+
31
+ # puts "micro: #{aggregate["rack.request.queue.time"].inspect}"
32
+ assert_equal 1, aggregate["rack.request.queue.time"][:count],
33
+ 'should track total queue time'
34
+ assert_in_delta 10, aggregate["rack.request.queue.time"][:sum], 4
35
+ end
36
+
37
+ def test_queue_start
38
+ get '/queue_start'
39
+
40
+ # puts "micro: #{aggregate["rack.request.queue.time"].inspect}"
41
+ assert_equal 1, aggregate["rack.request.queue.time"][:count],
42
+ 'should track total queue time'
43
+ assert_in_delta 15, aggregate["rack.request.queue.time"][:sum], 4
44
+ end
45
+
46
+ def test_with_t
47
+ get '/with_t'
48
+
49
+ # puts "micro: #{aggregate["rack.request.queue.time"].inspect}"
50
+ assert_equal 1, aggregate["rack.request.queue.time"][:count],
51
+ 'should track total queue time'
52
+ assert_in_delta 20, aggregate["rack.request.queue.time"][:sum], 4
53
+ end
54
+
55
+ private
56
+
57
+ def aggregate
58
+ Librato.tracker.collector.aggregate
59
+ end
60
+
61
+ def counters
62
+ Librato.tracker.collector.counters
63
+ end
64
+
65
+ end
@@ -42,6 +42,18 @@ class RequestTest < Minitest::Test
42
42
  assert_equal 1, aggregate["rack.request.status.2xx.time"][:count]
43
43
  end
44
44
 
45
+ def test_track_http_method_info
46
+ get '/'
47
+
48
+ assert_equal 1, counters['rack.request.method.get']
49
+ assert_equal 1, aggregate['rack.request.method.get.time'][:count]
50
+
51
+ post '/'
52
+
53
+ assert_equal 1, counters['rack.request.method.post']
54
+ assert_equal 1, aggregate['rack.request.method.post.time'][:count]
55
+ end
56
+
45
57
  def test_track_exceptions
46
58
  begin
47
59
  get '/exception'
@@ -8,8 +8,10 @@ module Librato
8
8
  collector = Collector.new
9
9
  collector.group 'foo' do |g|
10
10
  g.increment :bar
11
+ g.increment :baz, :source => 'bang'
11
12
  end
12
13
  assert_equal 1, collector.counters['foo.bar']
14
+ assert_equal 1, collector.counters.fetch('foo.baz', source: 'bang')
13
15
  end
14
16
 
15
17
  def test_measure
@@ -79,6 +79,23 @@ module Librato
79
79
  assert buffer_lines[0].index('[test prefix] '), 'should use prefix'
80
80
  end
81
81
 
82
+ def test_log_buffering
83
+ buffer = StringIO.new
84
+ logger = Logger.new # no outlet provided
85
+ logger.prefix = ''
86
+
87
+ logger.log :error, 'some business'
88
+ logger.log :error, 'some more business'
89
+ logger.outlet = buffer
90
+ logger.log :error, 'some ongoing business'
91
+
92
+ buffer.rewind
93
+ lines = buffer.readlines
94
+ assert_equal 'some business', lines[0].chomp
95
+ assert_equal 'some more business', lines[1].chomp
96
+ assert_equal 'some ongoing business', lines[2].chomp
97
+ end
98
+
82
99
  private
83
100
 
84
101
  def buffer_lines
@@ -32,6 +32,20 @@ module Librato
32
32
  assert_equal true, new_tracker.send(:should_start?)
33
33
  end
34
34
 
35
+ def test_autorun_can_prevent_startup
36
+ ENV['LIBRATO_AUTORUN']='0'
37
+ config = Configuration.new
38
+ config.user, config.token = 'foo', 'bar'
39
+ @buffer = StringIO.new
40
+ config.log_target = @buffer
41
+ tracker = Tracker.new(config)
42
+
43
+ assert_equal false, tracker.send(:should_start?),
44
+ 'should not start if autorun set to 0'
45
+
46
+ ENV.delete('LIBRATO_AUTORUN')
47
+ end
48
+
35
49
  private
36
50
 
37
51
  def buffer_lines
@@ -1,6 +1,9 @@
1
1
  require 'test_helper'
2
2
  require 'stringio'
3
3
 
4
+ require 'eventmachine'
5
+ require 'em-synchrony'
6
+
4
7
  module Librato
5
8
  class Rack
6
9
  class WorkerTest < Minitest::Test
@@ -8,18 +11,34 @@ module Librato
8
11
  def test_basic_use
9
12
  worker = Worker.new
10
13
  counter = 0
11
- Thread.new do
14
+
15
+ thread = Thread.new do
12
16
  worker.run_periodically(0.1) do
13
17
  counter += 1
14
18
  end
15
19
  end
20
+
16
21
  sleep 0.45
17
- assert_equal counter, 4
22
+ assert_in_delta 4, counter, 1
23
+
24
+ worker.stop!
25
+ thread.join
18
26
  end
19
27
 
20
28
  def test_start_time
21
29
  worker = Worker.new
22
30
 
31
+ 20.times do
32
+ time = Time.now
33
+ start = worker.start_time(60)
34
+ assert start >= time + 1, 'should be more than 1 second from when run'
35
+ assert start <= time + 120, 'should not be more than 60 seconds from when run'
36
+ end
37
+ end
38
+
39
+ def test_start_time_with_sync
40
+ worker = Worker.new(sync: true)
41
+
23
42
  time = Time.now
24
43
  start = worker.start_time(60)
25
44
  assert start >= time + 60, 'should be more than 60 seconds from when run'
@@ -43,6 +62,42 @@ module Librato
43
62
  assert_equal :sleep, worker.timer
44
63
  end
45
64
 
65
+ def test_eventmachine_timer
66
+ worker = Worker.new(:timer => :eventmachine)
67
+ counter = 0
68
+
69
+ thread = Thread.new do
70
+ EventMachine.run do
71
+ worker.run_periodically(0.1) do
72
+ counter += 1
73
+ end
74
+ EM.add_timer(0.6) { worker.stop!; EM.stop }
75
+ end
76
+ end
77
+
78
+ sleep 0.45
79
+ assert_in_delta 4, counter, 1
80
+ thread.join
81
+ end
82
+
83
+ def test_em_synchrony_timer
84
+ worker = Worker.new(:timer => :synchrony)
85
+ counter = 0
86
+
87
+ thread = Thread.new do
88
+ EM.synchrony do
89
+ worker.run_periodically(0.1) do
90
+ counter += 1
91
+ end
92
+ EventMachine.stop
93
+ end
94
+ end
95
+
96
+ sleep 0.45
97
+ assert_in_delta 4, counter, 1
98
+ Thread.kill(thread)
99
+ end
100
+
46
101
  end
47
102
  end
48
103
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: librato-rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -37,7 +37,7 @@ cert_chain:
37
37
  bktaNmhlblFBRjFDSDk2WmNxY0pIMTc5UzJ0SWlLRE04a2VlUklVT1BDM1dU
38
38
  MGZhb2svMgpnQTJvemRyODUxYy9uQT09Ci0tLS0tRU5EIENFUlRJRklDQVRF
39
39
  LS0tLS0K
40
- date: 2013-08-13 00:00:00.000000000 Z
40
+ date: 2013-08-19 00:00:00.000000000 Z
41
41
  dependencies:
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: librato-metrics
@@ -100,9 +100,11 @@ files:
100
100
  - test/apps/custom.ru
101
101
  - test/apps/deprecated.ru
102
102
  - test/apps/no_stats.ru
103
+ - test/apps/queue_wait.ru
103
104
  - test/integration/custom_test.rb
104
105
  - test/integration/deprecated_test.rb
105
106
  - test/integration/no_stats_test.rb
107
+ - test/integration/queue_wait_test.rb
106
108
  - test/integration/request_test.rb
107
109
  - test/remote/tracker_test.rb
108
110
  - test/test_helper.rb
@@ -115,7 +117,8 @@ files:
115
117
  - test/unit/rack/tracker_test.rb
116
118
  - test/unit/rack/worker_test.rb
117
119
  homepage: https://github.com/librato/librato-rack
118
- licenses: []
120
+ licenses:
121
+ - BSD 3-clause
119
122
  post_install_message:
120
123
  rdoc_options: []
121
124
  require_paths:
@@ -128,7 +131,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
131
  version: '0'
129
132
  segments:
130
133
  - 0
131
- hash: 3140236237791435311
134
+ hash: -3276523900394881660
132
135
  required_rubygems_version: !ruby/object:Gem::Requirement
133
136
  none: false
134
137
  requirements:
@@ -137,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
140
  version: '0'
138
141
  segments:
139
142
  - 0
140
- hash: 3140236237791435311
143
+ hash: -3276523900394881660
141
144
  requirements: []
142
145
  rubyforge_project:
143
146
  rubygems_version: 1.8.23
@@ -149,9 +152,11 @@ test_files:
149
152
  - test/apps/custom.ru
150
153
  - test/apps/deprecated.ru
151
154
  - test/apps/no_stats.ru
155
+ - test/apps/queue_wait.ru
152
156
  - test/integration/custom_test.rb
153
157
  - test/integration/deprecated_test.rb
154
158
  - test/integration/no_stats_test.rb
159
+ - test/integration/queue_wait_test.rb
155
160
  - test/integration/request_test.rb
156
161
  - test/remote/tracker_test.rb
157
162
  - test/test_helper.rb
metadata.gz.sig CHANGED
Binary file