nunes 0.1.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.
- data/.gitignore +17 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +150 -0
- data/lib/nunes.rb +39 -0
- data/lib/nunes/adapter.rb +56 -0
- data/lib/nunes/adapters/default.rb +10 -0
- data/lib/nunes/adapters/memory.rb +62 -0
- data/lib/nunes/adapters/timing_aliased.rb +17 -0
- data/lib/nunes/instrumentable.rb +102 -0
- data/lib/nunes/subscriber.rb +69 -0
- data/lib/nunes/subscribers/action_controller.rb +80 -0
- data/lib/nunes/subscribers/action_mailer.rb +33 -0
- data/lib/nunes/subscribers/action_view.rb +44 -0
- data/lib/nunes/subscribers/active_record.rb +33 -0
- data/lib/nunes/subscribers/active_support.rb +58 -0
- data/lib/nunes/subscribers/nunes.rb +24 -0
- data/lib/nunes/version.rb +3 -0
- data/nunes.gemspec +22 -0
- data/script/bootstrap +21 -0
- data/script/test +25 -0
- data/script/watch +30 -0
- data/test/adapter_test.rb +40 -0
- data/test/adapters/default_test.rb +26 -0
- data/test/adapters/timing_aliased_test.rb +26 -0
- data/test/cache_instrumentation_test.rb +79 -0
- data/test/controller_instrumentation_test.rb +88 -0
- data/test/fake_udp_socket_test.rb +26 -0
- data/test/helper.rb +25 -0
- data/test/instrumentable_test.rb +100 -0
- data/test/mailer_instrumentation_test.rb +26 -0
- data/test/model_instrumentation_test.rb +55 -0
- data/test/nunes_test.rb +20 -0
- data/test/rails_app/.gitignore +15 -0
- data/test/rails_app/Rakefile +7 -0
- data/test/rails_app/app/assets/images/rails.png +0 -0
- data/test/rails_app/app/assets/javascripts/application.js +15 -0
- data/test/rails_app/app/assets/stylesheets/application.css +13 -0
- data/test/rails_app/app/controllers/application_controller.rb +3 -0
- data/test/rails_app/app/controllers/posts_controller.rb +28 -0
- data/test/rails_app/app/helpers/application_helper.rb +2 -0
- data/test/rails_app/app/mailers/.gitkeep +0 -0
- data/test/rails_app/app/mailers/post_mailer.rb +11 -0
- data/test/rails_app/app/models/.gitkeep +0 -0
- data/test/rails_app/app/models/post.rb +2 -0
- data/test/rails_app/app/views/layouts/application.html.erb +14 -0
- data/test/rails_app/app/views/post_mailer/created.text.erb +1 -0
- data/test/rails_app/app/views/posts/_post.html.erb +1 -0
- data/test/rails_app/app/views/posts/index.html.erb +5 -0
- data/test/rails_app/config.ru +4 -0
- data/test/rails_app/config/application.rb +67 -0
- data/test/rails_app/config/boot.rb +6 -0
- data/test/rails_app/config/database.yml +6 -0
- data/test/rails_app/config/environment.rb +5 -0
- data/test/rails_app/config/environments/development.rb +31 -0
- data/test/rails_app/config/environments/production.rb +64 -0
- data/test/rails_app/config/environments/test.rb +35 -0
- data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_app/config/initializers/force_test_schema_load.rb +3 -0
- data/test/rails_app/config/initializers/inflections.rb +15 -0
- data/test/rails_app/config/initializers/mime_types.rb +5 -0
- data/test/rails_app/config/initializers/secret_token.rb +7 -0
- data/test/rails_app/config/initializers/session_store.rb +8 -0
- data/test/rails_app/config/initializers/wrap_parameters.rb +10 -0
- data/test/rails_app/config/locales/en.yml +5 -0
- data/test/rails_app/config/routes.rb +8 -0
- data/test/rails_app/db/migrate/20130417154459_create_posts.rb +8 -0
- data/test/rails_app/db/schema.rb +22 -0
- data/test/rails_app/db/seeds.rb +7 -0
- data/test/rails_app/lib/assets/.gitkeep +0 -0
- data/test/rails_app/lib/tasks/.gitkeep +0 -0
- data/test/rails_app/public/404.html +26 -0
- data/test/rails_app/public/422.html +26 -0
- data/test/rails_app/public/500.html +25 -0
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/rails_app/public/index.html +241 -0
- data/test/rails_app/public/robots.txt +5 -0
- data/test/rails_app/script/rails +6 -0
- data/test/subscriber_test.rb +50 -0
- data/test/support/adapter_test_helpers.rb +33 -0
- data/test/support/fake_udp_socket.rb +50 -0
- data/test/view_instrumentation_test.rb +30 -0
- metadata +205 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class AdapterTest < ActiveSupport::TestCase
|
4
|
+
test "wrap for statsd" do
|
5
|
+
client_with_gauge_and_timing = Class.new do
|
6
|
+
def increment(*args); end
|
7
|
+
def gauge(*args); end
|
8
|
+
def timing(*args); end
|
9
|
+
end.new
|
10
|
+
|
11
|
+
adapter = Nunes::Adapter.wrap(client_with_gauge_and_timing)
|
12
|
+
assert_instance_of Nunes::Adapters::Default, adapter
|
13
|
+
end
|
14
|
+
|
15
|
+
test "wrap for instrumental" do
|
16
|
+
client_with_gauge_but_not_timing = Class.new do
|
17
|
+
def increment(*args); end
|
18
|
+
def gauge(*args); end
|
19
|
+
end.new
|
20
|
+
|
21
|
+
adapter = Nunes::Adapter.wrap(client_with_gauge_but_not_timing)
|
22
|
+
assert_instance_of Nunes::Adapters::TimingAliased, adapter
|
23
|
+
end
|
24
|
+
|
25
|
+
test "wrap for adapter" do
|
26
|
+
memory = Nunes::Adapters::Memory.new
|
27
|
+
adapter = Nunes::Adapter.wrap(memory)
|
28
|
+
assert_equal memory, adapter
|
29
|
+
end
|
30
|
+
|
31
|
+
test "wrap with hash" do
|
32
|
+
hash = {}
|
33
|
+
adapter = Nunes::Adapter.wrap(hash)
|
34
|
+
assert_instance_of Nunes::Adapters::Memory, adapter
|
35
|
+
end
|
36
|
+
|
37
|
+
test "wrap with nil" do
|
38
|
+
assert_raises(ArgumentError) { Nunes::Adapter.wrap(nil) }
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "helper"
|
2
|
+
require "minitest/mock"
|
3
|
+
|
4
|
+
class DefaultAdapterTest < ActiveSupport::TestCase
|
5
|
+
test "passes increment along" do
|
6
|
+
mock = MiniTest::Mock.new
|
7
|
+
mock.expect :increment, nil, ["single", 1]
|
8
|
+
mock.expect :increment, nil, ["double", 2]
|
9
|
+
|
10
|
+
client = Nunes::Adapters::Default.new(mock)
|
11
|
+
client.increment("single")
|
12
|
+
client.increment("double", 2)
|
13
|
+
|
14
|
+
mock.verify
|
15
|
+
end
|
16
|
+
|
17
|
+
test "passes timing along" do
|
18
|
+
mock = MiniTest::Mock.new
|
19
|
+
mock.expect :timing, nil, ["foo", 23]
|
20
|
+
|
21
|
+
client = Nunes::Adapters::Default.new(mock)
|
22
|
+
client.timing("foo", 23)
|
23
|
+
|
24
|
+
mock.verify
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "helper"
|
2
|
+
require "minitest/mock"
|
3
|
+
|
4
|
+
class TimingAliasedAdapterTest < ActiveSupport::TestCase
|
5
|
+
test "passes increment along" do
|
6
|
+
mock = MiniTest::Mock.new
|
7
|
+
mock.expect :increment, nil, ["single", 1]
|
8
|
+
mock.expect :increment, nil, ["double", 2]
|
9
|
+
|
10
|
+
client = Nunes::Adapters::TimingAliased.new(mock)
|
11
|
+
client.increment("single")
|
12
|
+
client.increment("double", 2)
|
13
|
+
|
14
|
+
mock.verify
|
15
|
+
end
|
16
|
+
|
17
|
+
test "sends timing to gauge" do
|
18
|
+
mock = MiniTest::Mock.new
|
19
|
+
mock.expect :gauge, nil, ["foo", 23]
|
20
|
+
|
21
|
+
client = Nunes::Adapters::TimingAliased.new(mock)
|
22
|
+
client.timing("foo", 23)
|
23
|
+
|
24
|
+
mock.verify
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class CacheInstrumentationTest < ActiveSupport::TestCase
|
4
|
+
attr_reader :cache
|
5
|
+
|
6
|
+
setup :setup_subscriber, :setup_cache
|
7
|
+
teardown :teardown_subscriber, :teardown_cache
|
8
|
+
|
9
|
+
def setup_subscriber
|
10
|
+
@subscriber = Nunes::Subscribers::ActiveSupport.subscribe(adapter)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown_subscriber
|
14
|
+
ActiveSupport::Notifications.unsubscribe @subscriber if @subscriber
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_cache
|
18
|
+
ActiveSupport::Cache::MemoryStore.instrument = true
|
19
|
+
@cache = ActiveSupport::Cache::MemoryStore.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown_cache
|
23
|
+
ActiveSupport::Cache::MemoryStore.instrument = nil
|
24
|
+
@cache = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
test "cache_read miss" do
|
28
|
+
cache.read('foo')
|
29
|
+
|
30
|
+
assert_timer "active_support.cache_read"
|
31
|
+
assert_counter "active_support.cache_miss"
|
32
|
+
end
|
33
|
+
|
34
|
+
test "cache_read hit" do
|
35
|
+
cache.write('foo', 'bar')
|
36
|
+
adapter.clear
|
37
|
+
cache.read('foo')
|
38
|
+
|
39
|
+
assert_timer "active_support.cache_read"
|
40
|
+
assert_counter "active_support.cache_hit"
|
41
|
+
end
|
42
|
+
|
43
|
+
test "cache_generate" do
|
44
|
+
cache.fetch('foo') { |key| :generate_me_please }
|
45
|
+
assert_timer "active_support.cache_generate"
|
46
|
+
end
|
47
|
+
|
48
|
+
test "cache_fetch with hit" do
|
49
|
+
cache.write('foo', 'bar')
|
50
|
+
adapter.clear
|
51
|
+
cache.fetch('foo') { |key| :never_gets_here }
|
52
|
+
|
53
|
+
assert_timer "active_support.cache_fetch"
|
54
|
+
assert_timer "active_support.cache_fetch_hit"
|
55
|
+
end
|
56
|
+
|
57
|
+
test "cache_fetch with miss" do
|
58
|
+
cache.fetch('foo') { 'foo value set here' }
|
59
|
+
|
60
|
+
assert_timer "active_support.cache_fetch"
|
61
|
+
assert_timer "active_support.cache_generate"
|
62
|
+
assert_timer "active_support.cache_write"
|
63
|
+
end
|
64
|
+
|
65
|
+
test "cache_write" do
|
66
|
+
cache.write('foo', 'bar')
|
67
|
+
assert_timer "active_support.cache_write"
|
68
|
+
end
|
69
|
+
|
70
|
+
test "cache_delete" do
|
71
|
+
cache.delete('foo')
|
72
|
+
assert_timer "active_support.cache_delete"
|
73
|
+
end
|
74
|
+
|
75
|
+
test "cache_exist?" do
|
76
|
+
cache.exist?('foo')
|
77
|
+
assert_timer "active_support.cache_exist"
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class ControllerInstrumentationTest < ActionController::TestCase
|
4
|
+
tests PostsController
|
5
|
+
|
6
|
+
setup :setup_subscriber
|
7
|
+
teardown :teardown_subscriber
|
8
|
+
|
9
|
+
def setup_subscriber
|
10
|
+
@subscriber = Nunes::Subscribers::ActionController.subscribe(adapter)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown_subscriber
|
14
|
+
ActiveSupport::Notifications.unsubscribe @subscriber if @subscriber
|
15
|
+
end
|
16
|
+
|
17
|
+
test "process_action" do
|
18
|
+
get :index
|
19
|
+
|
20
|
+
assert_response :success
|
21
|
+
|
22
|
+
assert_counter "action_controller.status.200"
|
23
|
+
assert_counter "action_controller.format.html"
|
24
|
+
|
25
|
+
assert_timer "action_controller.runtime"
|
26
|
+
assert_timer "action_controller.view_runtime"
|
27
|
+
|
28
|
+
assert_timer "action_controller.posts.index.runtime"
|
29
|
+
assert_timer "action_controller.posts.index.view_runtime"
|
30
|
+
end
|
31
|
+
|
32
|
+
test "send_data" do
|
33
|
+
get :some_data
|
34
|
+
|
35
|
+
assert_response :success
|
36
|
+
|
37
|
+
assert_counter "action_controller.status.200"
|
38
|
+
|
39
|
+
assert_timer "action_controller.runtime"
|
40
|
+
assert_timer "action_controller.view_runtime"
|
41
|
+
|
42
|
+
assert_timer "action_controller.posts.some_data.runtime"
|
43
|
+
assert_timer "action_controller.posts.some_data.view_runtime"
|
44
|
+
end
|
45
|
+
|
46
|
+
test "send_file" do
|
47
|
+
get :some_file
|
48
|
+
|
49
|
+
assert_response :success
|
50
|
+
|
51
|
+
assert_counter"action_controller.status.200"
|
52
|
+
|
53
|
+
assert_timer "action_controller.runtime"
|
54
|
+
assert_timer "action_controller.posts.some_file.runtime"
|
55
|
+
|
56
|
+
assert ! adapter.timer?("action_controller.view_runtime")
|
57
|
+
assert ! adapter.timer?("action_controller.posts.some_file.view_runtime")
|
58
|
+
end
|
59
|
+
|
60
|
+
test "redirect_to" do
|
61
|
+
get :some_redirect
|
62
|
+
|
63
|
+
assert_response :redirect
|
64
|
+
|
65
|
+
assert_counter "action_controller.status.302"
|
66
|
+
|
67
|
+
assert_timer "action_controller.runtime"
|
68
|
+
assert_timer "action_controller.posts.some_redirect.runtime"
|
69
|
+
|
70
|
+
assert_no_timer "action_controller.view_runtime"
|
71
|
+
assert_no_timer "action_controller.posts.some_redirect.view_runtime"
|
72
|
+
end
|
73
|
+
|
74
|
+
test "action with exception" do
|
75
|
+
get :some_boom rescue StandardError # catch the boom
|
76
|
+
|
77
|
+
assert_response :success
|
78
|
+
|
79
|
+
assert_counter "action_controller.exception.RuntimeError"
|
80
|
+
assert_counter "action_controller.format.html"
|
81
|
+
|
82
|
+
assert_timer "action_controller.runtime"
|
83
|
+
assert_timer "action_controller.posts.some_boom.runtime"
|
84
|
+
|
85
|
+
assert_no_timer "action_controller.view_runtime"
|
86
|
+
assert_no_timer "action_controller.posts.some_boom.view_runtime"
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class FakeUdpSocketTest < ActiveSupport::TestCase
|
4
|
+
test "timer boolean" do
|
5
|
+
socket = FakeUdpSocket.new
|
6
|
+
socket.send "action_controller.posts.index.runtime:2|ms"
|
7
|
+
assert_equal true, socket.timer?("action_controller.posts.index.runtime")
|
8
|
+
assert_equal false, socket.timer?("action_controller.posts.index.faketime")
|
9
|
+
end
|
10
|
+
|
11
|
+
test "counter boolean" do
|
12
|
+
socket = FakeUdpSocket.new
|
13
|
+
socket.send "action_controller.status.200:1|c"
|
14
|
+
assert_equal true, socket.counter?("action_controller.status.200")
|
15
|
+
assert_equal false, socket.counter?("action_controller.status.400")
|
16
|
+
end
|
17
|
+
|
18
|
+
test "send, recv and clear" do
|
19
|
+
socket = FakeUdpSocket.new
|
20
|
+
socket.send "foo"
|
21
|
+
socket.send "bar"
|
22
|
+
assert_equal "foo", socket.recv
|
23
|
+
socket.clear
|
24
|
+
assert_nil socket.recv
|
25
|
+
end
|
26
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
require "rails/test_help"
|
5
|
+
require "action_mailer"
|
6
|
+
|
7
|
+
# require everything in the support directory
|
8
|
+
root = Pathname(__FILE__).dirname.join("..").expand_path
|
9
|
+
Dir[root.join("test/support/**/*.rb")].each { |f| require f }
|
10
|
+
|
11
|
+
class ActionController::TestCase
|
12
|
+
include AdapterTestHelpers
|
13
|
+
end
|
14
|
+
|
15
|
+
class ActionMailer::TestCase
|
16
|
+
include AdapterTestHelpers
|
17
|
+
end
|
18
|
+
|
19
|
+
class ActiveSupport::TestCase
|
20
|
+
include AdapterTestHelpers
|
21
|
+
end
|
22
|
+
|
23
|
+
require "rails_app/config/environment"
|
24
|
+
|
25
|
+
require "nunes"
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class InstrumentationTest < ActiveSupport::TestCase
|
4
|
+
attr_reader :thing_class
|
5
|
+
|
6
|
+
setup :setup_subscriber, :setup_class
|
7
|
+
teardown :teardown_subscriber, :teardown_class
|
8
|
+
|
9
|
+
def setup_subscriber
|
10
|
+
@subscriber = Nunes::Subscribers::Nunes.subscribe(adapter)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown_subscriber
|
14
|
+
ActiveSupport::Notifications.unsubscribe @subscriber if @subscriber
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_class
|
18
|
+
@thing_class = Class.new {
|
19
|
+
extend Nunes::Instrumentable
|
20
|
+
|
21
|
+
def self.name
|
22
|
+
'Thing'
|
23
|
+
end
|
24
|
+
|
25
|
+
def yo(args = {})
|
26
|
+
:dude
|
27
|
+
end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def teardown_class
|
32
|
+
@thing_class = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
test "adds methods when extended" do
|
36
|
+
assert thing_class.respond_to?(:instrument_method_time)
|
37
|
+
end
|
38
|
+
|
39
|
+
test "attempting to instrument time for method twice" do
|
40
|
+
thing_class.instrument_method_time :yo
|
41
|
+
|
42
|
+
assert_raises(ArgumentError, "already instrumented yo for Thing") do
|
43
|
+
thing_class.instrument_method_time :yo
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
test "instrument_method_time" do
|
48
|
+
thing_class.instrument_method_time :yo
|
49
|
+
|
50
|
+
event = slurp_events { thing_class.new.yo(some: 'thing') }.last
|
51
|
+
|
52
|
+
assert_not_nil event, "No events were found."
|
53
|
+
assert_equal "thing.yo", event.payload[:metric]
|
54
|
+
assert_equal [{some: "thing"}], event.payload[:arguments]
|
55
|
+
assert_equal :dude, event.payload[:result]
|
56
|
+
assert_in_delta 0, event.duration, 0.1
|
57
|
+
|
58
|
+
assert_timer "thing.yo"
|
59
|
+
end
|
60
|
+
|
61
|
+
test "instrument_method_time with custom name in hash" do
|
62
|
+
thing_class.instrument_method_time :yo, name: 'Thingy.yohoho'
|
63
|
+
|
64
|
+
event = slurp_events { thing_class.new.yo(some: 'thing') }.last
|
65
|
+
|
66
|
+
assert_not_nil event, "No events were found."
|
67
|
+
assert_equal "thingy.yohoho", event.payload[:metric]
|
68
|
+
|
69
|
+
assert_timer "thingy.yohoho"
|
70
|
+
end
|
71
|
+
|
72
|
+
test "instrument_method_time with custom name as string" do
|
73
|
+
thing_class.instrument_method_time :yo, 'Thingy.yohoho'
|
74
|
+
|
75
|
+
event = slurp_events { thing_class.new.yo(some: 'thing') }.last
|
76
|
+
|
77
|
+
assert_not_nil event, "No events were found."
|
78
|
+
assert_equal "thingy.yohoho", event.payload[:metric]
|
79
|
+
|
80
|
+
assert_timer "thingy.yohoho"
|
81
|
+
end
|
82
|
+
|
83
|
+
test "instrument_method_time with custom payload" do
|
84
|
+
thing_class.instrument_method_time :yo, payload: {pay: "loadin"}
|
85
|
+
|
86
|
+
event = slurp_events { thing_class.new.yo(some: 'thing') }.last
|
87
|
+
|
88
|
+
assert_not_nil event, "No events were found."
|
89
|
+
assert_equal "loadin", event.payload[:pay]
|
90
|
+
|
91
|
+
assert_timer "thing.yo"
|
92
|
+
end
|
93
|
+
|
94
|
+
def slurp_events(&block)
|
95
|
+
events = []
|
96
|
+
callback = lambda { |*args| events << ActiveSupport::Notifications::Event.new(*args) }
|
97
|
+
ActiveSupport::Notifications.subscribed(callback, Nunes::Instrumentable::MethodTimeEventName, &block)
|
98
|
+
events
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class MailerInstrumentationTest < ActionMailer::TestCase
|
4
|
+
tests PostMailer
|
5
|
+
|
6
|
+
setup :setup_subscriber
|
7
|
+
teardown :teardown_subscriber
|
8
|
+
|
9
|
+
def setup_subscriber
|
10
|
+
@subscriber = Nunes::Subscribers::ActionMailer.subscribe(adapter)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown_subscriber
|
14
|
+
ActiveSupport::Notifications.unsubscribe @subscriber if @subscriber
|
15
|
+
end
|
16
|
+
|
17
|
+
test "deliver" do
|
18
|
+
PostMailer.created.deliver
|
19
|
+
assert_timer "action_mailer.deliver.post_mailer"
|
20
|
+
end
|
21
|
+
|
22
|
+
test "receive" do
|
23
|
+
PostMailer.receive PostMailer.created
|
24
|
+
assert_timer "action_mailer.receive.post_mailer"
|
25
|
+
end
|
26
|
+
end
|