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 +1 -2
- data/CHANGELOG.md +10 -0
- data/LICENSE +3 -3
- data/README.md +7 -0
- data/lib/librato/collector/group.rb +2 -2
- data/lib/librato/rack.rb +41 -5
- data/lib/librato/rack/configuration.rb +31 -3
- data/lib/librato/rack/logger.rb +32 -9
- data/lib/librato/rack/tracker.rb +16 -4
- data/lib/librato/rack/version.rb +1 -1
- data/lib/librato/rack/worker.rb +29 -8
- data/test/apps/queue_wait.ru +38 -0
- data/test/integration/no_stats_test.rb +1 -1
- data/test/integration/queue_wait_test.rb +65 -0
- data/test/integration/request_test.rb +12 -0
- data/test/unit/collector/group_test.rb +2 -0
- data/test/unit/rack/logger_test.rb +17 -0
- data/test/unit/rack/tracker_test.rb +14 -0
- data/test/unit/rack/worker_test.rb +57 -2
- metadata +10 -5
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
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%x�G���/
|
data/CHANGELOG.md
CHANGED
@@ -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
|
12
|
-
|
13
|
-
|
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,
|
16
|
+
def increment(counter, options={})
|
17
17
|
counter = "#{@prefix}#{counter}"
|
18
|
-
@collector.increment counter,
|
18
|
+
@collector.increment counter, options
|
19
19
|
end
|
20
20
|
|
21
21
|
def measure(*args, &block)
|
data/lib/librato/rack.rb
CHANGED
@@ -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
|
-
|
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, :
|
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
|
data/lib/librato/rack/logger.rb
CHANGED
@@ -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 :
|
11
|
+
attr_accessor :prefix
|
12
|
+
attr_reader :outlet
|
12
13
|
|
13
|
-
def initialize(
|
14
|
-
|
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
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/librato/rack/tracker.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/librato/rack/version.rb
CHANGED
data/lib/librato/rack/worker.rb
CHANGED
@@ -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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
43
|
-
|
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)
|
@@ -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
|
-
|
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
|
-
|
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.
|
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-
|
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:
|
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:
|
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
|