librato-rack 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +24 -0
- data/README.md +176 -0
- data/Rakefile +25 -0
- data/lib/librato-rack.rb +1 -0
- data/lib/librato/collector.rb +48 -0
- data/lib/librato/collector/aggregator.rb +97 -0
- data/lib/librato/collector/counter_cache.rb +113 -0
- data/lib/librato/collector/group.rb +29 -0
- data/lib/librato/rack.rb +116 -0
- data/lib/librato/rack/configuration.rb +61 -0
- data/lib/librato/rack/errors.rb +7 -0
- data/lib/librato/rack/logger.rb +71 -0
- data/lib/librato/rack/tracker.rb +137 -0
- data/lib/librato/rack/validating_queue.rb +41 -0
- data/lib/librato/rack/version.rb +5 -0
- data/lib/librato/rack/worker.rb +49 -0
- data/test/apps/basic.ru +20 -0
- data/test/apps/custom.ru +27 -0
- data/test/apps/heroku.ru +27 -0
- data/test/integration/custom_test.rb +59 -0
- data/test/integration/heroku_test.rb +36 -0
- data/test/integration/request_test.rb +69 -0
- data/test/remote/tracker_test.rb +198 -0
- data/test/test_helper.rb +22 -0
- data/test/unit/collector/aggregator_test.rb +69 -0
- data/test/unit/collector/counter_cache_test.rb +96 -0
- data/test/unit/collector/group_test.rb +53 -0
- data/test/unit/collector_test.rb +23 -0
- data/test/unit/rack/configuration_test.rb +86 -0
- data/test/unit/rack/logger_test.rb +91 -0
- data/test/unit/rack/tracker_test.rb +44 -0
- data/test/unit/rack/worker_test.rb +36 -0
- metadata +132 -0
data/test/test_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require 'pry'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
# require 'mocha/setup'
|
7
|
+
|
8
|
+
# Configure Rails Environment
|
9
|
+
ENV["RAILS_ENV"] = "test"
|
10
|
+
|
11
|
+
require 'librato/rack'
|
12
|
+
|
13
|
+
# require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
14
|
+
# require "rails/test_help"
|
15
|
+
|
16
|
+
# Configure capybara
|
17
|
+
# require 'capybara/rails'
|
18
|
+
# Capybara.default_driver = :rack_test
|
19
|
+
# Capybara.default_selector = :css
|
20
|
+
|
21
|
+
# Load support files
|
22
|
+
#Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Librato
|
4
|
+
class Collector
|
5
|
+
class AggregatorTest < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@agg = Aggregator.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_adding_timings
|
12
|
+
@agg.timing 'request.time.total', 23.7
|
13
|
+
@agg.timing 'request.time.db', 5.3
|
14
|
+
@agg.timing 'request.time.total', 64.3
|
15
|
+
|
16
|
+
assert_equal 2, @agg['request.time.total'][:count]
|
17
|
+
assert_equal 88.0, @agg['request.time.total'][:sum]
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_block_timing
|
21
|
+
@agg.timing 'my.task' do
|
22
|
+
sleep 0.2
|
23
|
+
end
|
24
|
+
assert_in_delta @agg['my.task'][:sum], 200, 50
|
25
|
+
|
26
|
+
@agg.timing('another.task') { sleep 0.1 }
|
27
|
+
assert_in_delta @agg['another.task'][:sum], 100, 50
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_return_values
|
31
|
+
simple = @agg.timing 'simple', 20
|
32
|
+
assert_equal nil, simple
|
33
|
+
|
34
|
+
timing = @agg.timing 'foo' do
|
35
|
+
sleep 0.1
|
36
|
+
'bar'
|
37
|
+
end
|
38
|
+
assert_equal 'bar', timing
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_custom_source
|
42
|
+
# sources are kept separate
|
43
|
+
@agg.measure 'meaning.of.life', 1
|
44
|
+
@agg.measure 'meaning.of.life', 42, :source => 'douglas_adams'
|
45
|
+
assert_equal 1.0, @agg.fetch('meaning.of.life')[:sum]
|
46
|
+
assert_equal 42.0, @agg.fetch('meaning.of.life', :source => 'douglas_adams')[:sum]
|
47
|
+
|
48
|
+
# sources work with time blocks
|
49
|
+
@agg.timing 'mytiming', :source => 'mine' do
|
50
|
+
sleep 0.02
|
51
|
+
end
|
52
|
+
assert_in_delta @agg.fetch('mytiming', :source => 'mine')[:sum], 20, 10
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_flush
|
56
|
+
@agg.measure 'meaning.of.life', 1
|
57
|
+
@agg.measure 'meaning.of.life', 42, :source => 'douglas_adams'
|
58
|
+
|
59
|
+
q = Librato::Metrics::Queue.new
|
60
|
+
@agg.flush_to(q)
|
61
|
+
expected = Set.new([
|
62
|
+
{:name=>"meaning.of.life", :count=>1, :sum=>1.0, :min=>1.0, :max=>1.0},
|
63
|
+
{:name=>"meaning.of.life", :count=>1, :sum=>42.0, :min=>42.0, :max=>42.0, :source=>"douglas_adams"}])
|
64
|
+
assert_equal expected, Set.new(q.queued[:gauges])
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Librato
|
4
|
+
class Collector
|
5
|
+
class CounterCacheTest < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def test_basic_operations
|
8
|
+
cc = CounterCache.new
|
9
|
+
cc.increment :foo
|
10
|
+
assert_equal 1, cc[:foo]
|
11
|
+
|
12
|
+
# accepts optional argument
|
13
|
+
cc.increment :foo, :by => 5
|
14
|
+
assert_equal 6, cc[:foo]
|
15
|
+
|
16
|
+
# legacy style
|
17
|
+
cc.increment :foo, 2
|
18
|
+
assert_equal 8, cc[:foo]
|
19
|
+
|
20
|
+
# strings or symbols work
|
21
|
+
cc.increment 'foo'
|
22
|
+
assert_equal 9, cc['foo']
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_custom_sources
|
26
|
+
cc = CounterCache.new
|
27
|
+
|
28
|
+
cc.increment :foo, :source => 'bar'
|
29
|
+
assert_equal 1, cc.fetch(:foo, :source => 'bar')
|
30
|
+
|
31
|
+
# symbols also work
|
32
|
+
cc.increment :foo, :source => :baz
|
33
|
+
assert_equal 1, cc.fetch(:foo, :source => :baz)
|
34
|
+
|
35
|
+
# strings and symbols are interchangable
|
36
|
+
cc.increment :foo, :source => :bar
|
37
|
+
assert_equal 2, cc.fetch(:foo, :source => 'bar')
|
38
|
+
|
39
|
+
# custom source and custom increment
|
40
|
+
cc.increment :foo, :source => 'boombah', :by => 10
|
41
|
+
assert_equal 10, cc.fetch(:foo, :source => 'boombah')
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_sporadic
|
45
|
+
cc = CounterCache.new
|
46
|
+
|
47
|
+
cc.increment :foo
|
48
|
+
cc.increment :foo, :source => 'bar'
|
49
|
+
|
50
|
+
cc.increment :baz, :sporadic => true
|
51
|
+
cc.increment :baz, :source => 118, :sporadic => true
|
52
|
+
assert_equal 1, cc[:baz]
|
53
|
+
assert_equal 1, cc.fetch(:baz, :source => 118)
|
54
|
+
|
55
|
+
# persist values once
|
56
|
+
cc.flush_to(Librato::Metrics::Queue.new)
|
57
|
+
|
58
|
+
# normal values persist
|
59
|
+
assert_equal 0, cc[:foo]
|
60
|
+
assert_equal 0, cc.fetch(:foo, :source => 'bar')
|
61
|
+
|
62
|
+
# sporadic do not
|
63
|
+
assert_equal nil, cc[:baz]
|
64
|
+
assert_equal nil, cc.fetch(:baz, :source => 118)
|
65
|
+
|
66
|
+
# add a different sporadic metric
|
67
|
+
cc.increment :bazoom, :sporadic => true
|
68
|
+
assert_equal 1, cc[:bazoom]
|
69
|
+
|
70
|
+
# persist values again
|
71
|
+
cc.flush_to(Librato::Metrics::Queue.new)
|
72
|
+
assert_equal nil, cc[:bazoom]
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_flushing
|
76
|
+
cc = CounterCache.new
|
77
|
+
|
78
|
+
cc.increment :foo
|
79
|
+
cc.increment :bar, :by => 2
|
80
|
+
cc.increment :foo, :source => 'foobar'
|
81
|
+
cc.increment :foo, :source => 'foobar', :by => 3
|
82
|
+
|
83
|
+
q = Librato::Metrics::Queue.new
|
84
|
+
cc.flush_to(q)
|
85
|
+
|
86
|
+
expected = Set.new [{:name=>"foo", :value=>1},
|
87
|
+
{:name=>"foo", :value=>4, :source=>"foobar"},
|
88
|
+
{:name=>"bar", :value=>2}]
|
89
|
+
queued = Set.new(q.gauges)
|
90
|
+
queued.each { |hash| hash.delete(:measure_time) }
|
91
|
+
assert_equal queued, expected
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Librato
|
4
|
+
class Collector
|
5
|
+
class GroupTest < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def test_increment
|
8
|
+
collector = Collector.new
|
9
|
+
collector.group 'foo' do |g|
|
10
|
+
g.increment :bar
|
11
|
+
end
|
12
|
+
assert_equal 1, collector.counters['foo.bar']
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_measure
|
16
|
+
collector = Collector.new
|
17
|
+
collector.group 'foo' do |g|
|
18
|
+
g.measure :baz, 23
|
19
|
+
end
|
20
|
+
assert_equal 23, collector.aggregate['foo.baz'][:sum]
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_timing
|
24
|
+
collector = Collector.new
|
25
|
+
collector.group 'foo' do |g|
|
26
|
+
g.timing :bam, 32.0
|
27
|
+
end
|
28
|
+
assert_equal 32.0, collector.aggregate['foo.bam'][:sum]
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_timing_block
|
32
|
+
collector = Collector.new
|
33
|
+
collector.group 'foo' do |g|
|
34
|
+
g.timing :bak do
|
35
|
+
sleep 0.01
|
36
|
+
end
|
37
|
+
end
|
38
|
+
assert_in_delta 10.0, collector.aggregate['foo.bak'][:sum], 2
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_nesting
|
42
|
+
collector = Collector.new
|
43
|
+
collector.group 'foo' do |g|
|
44
|
+
g.group :bar do |b|
|
45
|
+
b.increment :baz, 2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
assert_equal 2, collector.counters['foo.bar.baz']
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Librato
|
4
|
+
class CollectorTest < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def test_proxy_object_access
|
7
|
+
collector = Collector.new
|
8
|
+
assert collector.aggregate, 'should have aggregate object'
|
9
|
+
assert collector.counters, 'should have counter object'
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_basic_grouping
|
13
|
+
collector = Collector.new
|
14
|
+
collector.group 'foo' do |g|
|
15
|
+
g.increment :bar
|
16
|
+
g.measure :baz, 23
|
17
|
+
end
|
18
|
+
assert_equal 1, collector.counters['foo.bar']
|
19
|
+
assert_equal 23, collector.aggregate['foo.baz'][:sum]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Librato
|
4
|
+
class Rack
|
5
|
+
class ConfigurationTest < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
clear_env_vars
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
clear_env_vars
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_defaults
|
16
|
+
config = Configuration.new
|
17
|
+
assert_equal 60, config.flush_interval
|
18
|
+
assert_equal Librato::Metrics.api_endpoint, config.api_endpoint
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_environment_variable_config
|
22
|
+
ENV['LIBRATO_USER'] = 'foo@bar.com'
|
23
|
+
ENV['LIBRATO_TOKEN'] = 'api_key'
|
24
|
+
ENV['LIBRATO_SOURCE'] = 'source'
|
25
|
+
config = Configuration.new
|
26
|
+
assert_equal 'foo@bar.com', config.user
|
27
|
+
assert_equal 'api_key', config.token
|
28
|
+
assert_equal 'source', config.source
|
29
|
+
#assert Librato::Rails.explicit_source, 'source is explicit'
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_legacy_env_variable_config
|
33
|
+
ENV['LIBRATO_METRICS_USER'] = 'foo@bar.com'
|
34
|
+
ENV['LIBRATO_METRICS_TOKEN'] = 'api_key'
|
35
|
+
ENV['LIBRATO_METRICS_SOURCE'] = 'source'
|
36
|
+
config = Configuration.new
|
37
|
+
assert_equal 'foo@bar.com', config.user
|
38
|
+
assert_equal 'api_key', config.token
|
39
|
+
assert_equal 'source', config.source
|
40
|
+
# assert Librato::Rails.explicit_source, 'source is explicit'
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_explicit_source
|
44
|
+
config = Configuration.new
|
45
|
+
assert !config.explicit_source?
|
46
|
+
config.source = 'tessaract'
|
47
|
+
assert config.explicit_source?
|
48
|
+
config.source = nil
|
49
|
+
assert !config.explicit_source?, 'source should no long be explicit when reset'
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_prefix_change_notification
|
53
|
+
config = Configuration.new
|
54
|
+
listener = listener_object
|
55
|
+
config.register_listener(listener)
|
56
|
+
config.prefix = 'newfoo'
|
57
|
+
assert_equal 'newfoo', listener.prefix
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def clear_env_vars
|
63
|
+
ENV.delete('LIBRATO_USER')
|
64
|
+
ENV.delete('LIBRATO_TOKEN')
|
65
|
+
ENV.delete('LIBRATO_SOURCE')
|
66
|
+
ENV.delete('LIBRATO_LOG_LEVEL')
|
67
|
+
# legacy
|
68
|
+
ENV.delete('LIBRATO_METRICS_USER')
|
69
|
+
ENV.delete('LIBRATO_METRICS_TOKEN')
|
70
|
+
ENV.delete('LIBRATO_METRICS_SOURCE')
|
71
|
+
end
|
72
|
+
|
73
|
+
def listener_object
|
74
|
+
listener = Object.new
|
75
|
+
def listener.prefix=(prefix)
|
76
|
+
@prefix = prefix
|
77
|
+
end
|
78
|
+
def listener.prefix
|
79
|
+
@prefix
|
80
|
+
end
|
81
|
+
listener
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Librato
|
5
|
+
class Rack
|
6
|
+
class LoggerTest < MiniTest::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@buffer = StringIO.new
|
10
|
+
#log_object = ::Logger.new(@buffer) # stdlib logger
|
11
|
+
@logger = Logger.new(@buffer) # rack logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_log_levels
|
15
|
+
assert_equal :info, @logger.log_level, 'should default to info'
|
16
|
+
|
17
|
+
@logger.log_level = :debug
|
18
|
+
assert_equal :debug, @logger.log_level, 'should accept symbols'
|
19
|
+
|
20
|
+
@logger.log_level = 'trace'
|
21
|
+
assert_equal :trace, @logger.log_level, 'should accept strings'
|
22
|
+
|
23
|
+
assert_raises(InvalidLogLevel) { @logger.log_level = :foo }
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_simple_logging
|
27
|
+
@logger.log_level = :info
|
28
|
+
|
29
|
+
# logging at log level
|
30
|
+
@logger.log :info, 'a log message'
|
31
|
+
assert_equal 1, buffer_lines.length, 'should have added a line'
|
32
|
+
assert buffer_lines[0].index('a log message'), 'should log message'
|
33
|
+
|
34
|
+
# logging above level
|
35
|
+
@logger.log :error, 'an error message'
|
36
|
+
assert_equal 2, buffer_lines.length, 'should have added a line'
|
37
|
+
assert buffer_lines[1].index('an error message'), 'should log message'
|
38
|
+
|
39
|
+
# logging below level
|
40
|
+
@logger.log :debug, 'a debug message'
|
41
|
+
assert_equal 2, buffer_lines.length, 'should not have added a line'
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_logging_through_stdlib_logger_object
|
45
|
+
stdlib_logger = ::Logger.new(@buffer)
|
46
|
+
@logger = Logger.new(stdlib_logger)
|
47
|
+
|
48
|
+
@logger.log_level = :info
|
49
|
+
|
50
|
+
# logging at log level
|
51
|
+
@logger.log :info, 'a log message'
|
52
|
+
assert_equal 1, buffer_lines.length, 'should have added a line'
|
53
|
+
assert buffer_lines[0].index('a log message'), 'should log message'
|
54
|
+
|
55
|
+
# logging above level
|
56
|
+
@logger.log :error, 'an error message'
|
57
|
+
assert_equal 2, buffer_lines.length, 'should have added a line'
|
58
|
+
assert buffer_lines[1].index('an error message'), 'should log message'
|
59
|
+
|
60
|
+
# logging below level
|
61
|
+
@logger.log :debug, 'a debug message'
|
62
|
+
assert_equal 2, buffer_lines.length, 'should not have added a line'
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_block_logging
|
66
|
+
@logger.log_level = :info
|
67
|
+
|
68
|
+
# logging at log level
|
69
|
+
@logger.log(:info) { "log statement" }
|
70
|
+
assert_equal 1, buffer_lines.length, 'should have added a line'
|
71
|
+
assert buffer_lines[0].index('log statement'), 'should log message'
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_log_prefix
|
75
|
+
assert_equal '[librato-rack] ', @logger.prefix
|
76
|
+
|
77
|
+
@logger.prefix = '[test prefix] '
|
78
|
+
@logger.log :error, 'an error message'
|
79
|
+
assert buffer_lines[0].index('[test prefix] '), 'should use prefix'
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def buffer_lines
|
85
|
+
@buffer.rewind
|
86
|
+
@buffer.readlines
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|