time_bandits 0.4.1 → 0.5.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.
- checksums.yaml +8 -8
- data/Gemfile +6 -0
- data/README.rdoc +22 -13
- data/Rakefile +14 -0
- data/lib/time_bandits.rb +3 -1
- data/lib/time_bandits/monkey_patches/action_controller.rb +17 -4
- data/lib/time_bandits/monkey_patches/memcache-client.rb +10 -35
- data/lib/time_bandits/monkey_patches/memcached.rb +13 -54
- data/lib/time_bandits/rack/logger.rb +1 -1
- data/lib/time_bandits/rack/logger40.rb +1 -1
- data/lib/time_bandits/railtie.rb +12 -7
- data/lib/time_bandits/time_consumers/base_consumer.rb +57 -0
- data/lib/time_bandits/time_consumers/dalli.rb +51 -0
- data/lib/time_bandits/time_consumers/database.rb +10 -30
- data/lib/time_bandits/time_consumers/garbage_collection.rb +7 -11
- data/lib/time_bandits/time_consumers/mem_cache.rb +12 -15
- data/lib/time_bandits/time_consumers/memcached.rb +19 -14
- data/lib/time_bandits/version.rb +1 -1
- data/test/test_helper.rb +18 -0
- data/test/unit/active_support_notifications_test.rb +64 -0
- data/test/unit/base_test.rb +63 -0
- data/test/unit/memcached_test.rb +60 -0
- data/time_bandits.gemspec +2 -0
- metadata +41 -7
- data/init.rb +0 -12
- data/lib/time_bandits/monkey_patches/action_controller_rails2.rb +0 -162
- data/lib/time_bandits/monkey_patches/active_record_rails2.rb +0 -86
- data/lib/time_bandits/time_consumers/database_rails2.rb +0 -61
@@ -8,42 +8,22 @@
|
|
8
8
|
module TimeBandits
|
9
9
|
module TimeConsumers
|
10
10
|
# provide a time consumer interface to ActiveRecord
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Thread.current.thread_variable_get(:time_bandits_database_info) ||
|
16
|
-
Thread.current.thread_variable_set(:time_bandits_database_info, [0.0, 0, 0])
|
17
|
-
end
|
18
|
-
|
19
|
-
def info=(info)
|
20
|
-
Thread.current.thread_variable_set(:time_bandits_database_info, info)
|
21
|
-
end
|
11
|
+
class Database < TimeBandits::TimeConsumers::BaseConsumer
|
12
|
+
prefix :db
|
13
|
+
fields :time, :calls, :sql_query_cache_hits
|
14
|
+
format "ActiveRecord: %.3fms(%dq,%dh)", :time, :calls, :sql_query_cache_hits
|
22
15
|
|
23
16
|
def reset
|
24
17
|
reset_stats
|
25
|
-
|
18
|
+
super
|
26
19
|
end
|
27
20
|
|
28
21
|
def consumed
|
29
22
|
time, calls, hits = reset_stats
|
30
|
-
i =
|
31
|
-
i
|
32
|
-
i
|
33
|
-
i
|
34
|
-
end
|
35
|
-
|
36
|
-
def runtime
|
37
|
-
time, calls, hits = *info
|
38
|
-
sprintf "ActiveRecord: %.3fms(%dq,%dh)", time*1000, calls, hits
|
39
|
-
end
|
40
|
-
|
41
|
-
def metrics
|
42
|
-
{
|
43
|
-
:db_time => info[0]*1000,
|
44
|
-
:db_calls => info[1],
|
45
|
-
:db_sql_query_cache_hits => info[2]
|
46
|
-
}
|
23
|
+
i = Database.instance
|
24
|
+
i.sql_query_cache_hits += hits
|
25
|
+
i.calls += calls
|
26
|
+
i.time += time
|
47
27
|
end
|
48
28
|
|
49
29
|
private
|
@@ -53,7 +33,7 @@ module TimeBandits
|
|
53
33
|
hits = s.reset_query_cache_hits
|
54
34
|
calls = s.reset_call_count
|
55
35
|
time = s.reset_runtime
|
56
|
-
[time
|
36
|
+
[time, calls, hits]
|
57
37
|
end
|
58
38
|
end
|
59
39
|
end
|
@@ -49,8 +49,8 @@ module TimeBandits
|
|
49
49
|
0.0
|
50
50
|
end
|
51
51
|
|
52
|
-
def consumed_gc_time
|
53
|
-
(GC.time - @consumed).to_f /
|
52
|
+
def consumed_gc_time # ms
|
53
|
+
(GC.time - @consumed).to_f / 1000
|
54
54
|
end
|
55
55
|
|
56
56
|
def collections
|
@@ -81,11 +81,7 @@ module TimeBandits
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
|
85
|
-
GCFORMAT = "GC: %.3f(%d) | HP: %d(%d,%d,%d,%d)"
|
86
|
-
else
|
87
|
-
GCFORMAT= "GC: %.3f(%d), HP: %d(%d,%d,%d,%d)"
|
88
|
-
end
|
84
|
+
GCFORMAT = "GC: %.3f(%d) | HP: %d(%d,%d,%d,%d)"
|
89
85
|
|
90
86
|
def runtime
|
91
87
|
heap_slots = GC.heap_slots
|
@@ -93,12 +89,12 @@ module TimeBandits
|
|
93
89
|
allocated_objects = self.allocated_objects
|
94
90
|
allocated_size = self.allocated_size
|
95
91
|
GCHacks.heap_dump if heap_growth > 0 && @@heap_dumps_enabled && defined?(GCHacks)
|
96
|
-
GCFORMAT % [consumed_gc_time
|
92
|
+
GCFORMAT % [consumed_gc_time, collections, heap_growth, heap_slots, allocated_objects, allocated_size, live_data_set_size]
|
97
93
|
end
|
98
94
|
|
99
95
|
def metrics
|
100
96
|
{
|
101
|
-
:gc_time => consumed_gc_time
|
97
|
+
:gc_time => consumed_gc_time,
|
102
98
|
:gc_calls => collections,
|
103
99
|
:heap_growth => heap_growth,
|
104
100
|
:heap_size => GC.heap_slots,
|
@@ -111,12 +107,12 @@ module TimeBandits
|
|
111
107
|
else
|
112
108
|
|
113
109
|
def runtime
|
114
|
-
"GC: %.3f(%d)" % [consumed_gc_time
|
110
|
+
"GC: %.3f(%d)" % [consumed_gc_time, collections]
|
115
111
|
end
|
116
112
|
|
117
113
|
def metrics
|
118
114
|
{
|
119
|
-
:gc_time => consumed_gc_time
|
115
|
+
:gc_time => consumed_gc_time,
|
120
116
|
:gc_calls => collections
|
121
117
|
}
|
122
118
|
end
|
@@ -4,26 +4,23 @@
|
|
4
4
|
# time_bandit TimeBandits::TimeConsumers::MemCache
|
5
5
|
#
|
6
6
|
require 'time_bandits/monkey_patches/memcache-client'
|
7
|
+
|
7
8
|
module TimeBandits
|
8
9
|
module TimeConsumers
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def consumed
|
16
|
-
::MemCache.get_benchmarks.first
|
17
|
-
end
|
18
|
-
|
19
|
-
def runtime
|
20
|
-
::MemCache.cache_runtime
|
21
|
-
end
|
10
|
+
class Memcache < BaseConsumer
|
11
|
+
prefix :memcache
|
12
|
+
fields :time, :calls, :misses
|
13
|
+
format "MC: %.3f(%dr,%dm)", :time, :calls, :misses
|
22
14
|
|
23
|
-
|
24
|
-
|
15
|
+
class Subscriber < ActiveSupport::LogSubscriber
|
16
|
+
def get(event)
|
17
|
+
i = Memcache.instance
|
18
|
+
i.time += event.duration
|
19
|
+
i.calls += 1
|
20
|
+
i.misses += event.payload[:misses]
|
25
21
|
end
|
26
22
|
end
|
23
|
+
Subscriber.attach_to :memcache
|
27
24
|
end
|
28
25
|
end
|
29
26
|
end
|
@@ -4,26 +4,31 @@
|
|
4
4
|
# time_bandit TimeBandits::TimeConsumers::Memcached
|
5
5
|
#
|
6
6
|
require 'time_bandits/monkey_patches/memcached'
|
7
|
+
|
7
8
|
module TimeBandits
|
8
9
|
module TimeConsumers
|
9
|
-
class Memcached
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
10
|
+
class Memcached < BaseConsumer
|
11
|
+
prefix :memcache
|
12
|
+
fields :time, :calls, :misses, :reads, :writes
|
13
|
+
format "MC: %.3f(%dr,%dm,%dw,%dc)", :time, :reads, :misses, :writes, :calls
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
class Subscriber < ActiveSupport::LogSubscriber
|
16
|
+
def get(event)
|
17
|
+
i = Memcached.instance
|
18
|
+
i.time += event.duration
|
19
|
+
i.calls += 1
|
20
|
+
payload = event.payload
|
21
|
+
i.reads += payload[:reads]
|
22
|
+
i.misses += payload[:misses]
|
17
23
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def metrics
|
24
|
-
::Memcached.metrics
|
24
|
+
def set(event)
|
25
|
+
i = Memcached.instance
|
26
|
+
i.time += event.duration
|
27
|
+
i.calls += 1
|
28
|
+
i.writes += 1
|
25
29
|
end
|
26
30
|
end
|
31
|
+
Subscriber.attach_to :memcached
|
27
32
|
end
|
28
33
|
end
|
29
34
|
end
|
data/lib/time_bandits/version.rb
CHANGED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'active_support/testing/declarative'
|
4
|
+
|
5
|
+
require 'minitest/pride'
|
6
|
+
|
7
|
+
class Test::Unit::TestCase
|
8
|
+
extend ActiveSupport::Testing::Declarative
|
9
|
+
end
|
10
|
+
|
11
|
+
require_relative '../lib/time_bandits'
|
12
|
+
|
13
|
+
ActiveSupport::LogSubscriber.class_eval do
|
14
|
+
# need a logger, otherwise no data will be collected
|
15
|
+
def logger
|
16
|
+
@logger ||= Logger.new(STDOUT)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require 'active_support/notifications'
|
3
|
+
require 'active_support/log_subscriber'
|
4
|
+
require 'thread_variables/access'
|
5
|
+
|
6
|
+
class ActiveSupportNotificationsTest < Test::Unit::TestCase
|
7
|
+
class SimpleConsumer < TimeBandits::TimeConsumers::BaseConsumer
|
8
|
+
prefix :simple
|
9
|
+
fields :time, :calls
|
10
|
+
format "Simple: %.1fms(%d calls)", :time, :calls
|
11
|
+
|
12
|
+
class Subscriber < ActiveSupport::LogSubscriber
|
13
|
+
def work(event)
|
14
|
+
i = SimpleConsumer.instance
|
15
|
+
i.time += event.duration
|
16
|
+
i.calls += 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
Subscriber.attach_to :simple
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup
|
23
|
+
TimeBandits.time_bandits = []
|
24
|
+
TimeBandits.add SimpleConsumer
|
25
|
+
TimeBandits.reset
|
26
|
+
end
|
27
|
+
|
28
|
+
test "getting metrics" do
|
29
|
+
assert_equal({:simple_calls => 0, :simple_time => 0}, TimeBandits.metrics)
|
30
|
+
end
|
31
|
+
|
32
|
+
test "formatting" do
|
33
|
+
assert_equal "Simple: 0.0ms(0 calls)", TimeBandits.runtime
|
34
|
+
end
|
35
|
+
|
36
|
+
test "foreground work gets accounted for in milliseconds" do
|
37
|
+
work
|
38
|
+
check_work
|
39
|
+
end
|
40
|
+
|
41
|
+
test "background work is ignored" do
|
42
|
+
Thread.new do
|
43
|
+
work
|
44
|
+
check_work
|
45
|
+
end.join
|
46
|
+
m = TimeBandits.metrics
|
47
|
+
assert_equal 0, m[:simple_calls]
|
48
|
+
assert_equal 0, m[:simple_time]
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def work
|
53
|
+
2.times do
|
54
|
+
ActiveSupport::Notifications.instrument("work.simple") { sleep 0.1 }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
def check_work
|
58
|
+
m = TimeBandits.metrics
|
59
|
+
assert_equal 2, m[:simple_calls]
|
60
|
+
assert 200 < m[:simple_time]
|
61
|
+
assert 300 > m[:simple_time]
|
62
|
+
assert_equal m[:simple_time], TimeBandits.consumed
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class NoTimeBanditsTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
TimeBandits.time_bandits = []
|
6
|
+
end
|
7
|
+
|
8
|
+
test "getting list of all time bandits" do
|
9
|
+
assert_equal [], TimeBandits.time_bandits
|
10
|
+
test_clean_state
|
11
|
+
end
|
12
|
+
|
13
|
+
test "reset" do
|
14
|
+
assert_nothing_raised { TimeBandits.reset }
|
15
|
+
test_clean_state
|
16
|
+
end
|
17
|
+
|
18
|
+
test "benchmarking" do
|
19
|
+
logger = mock("logger")
|
20
|
+
logger.expects(:info)
|
21
|
+
TimeBandits.benchmark("foo", logger) { }
|
22
|
+
test_clean_state
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def test_clean_state
|
27
|
+
assert_equal Hash.new, TimeBandits.metrics
|
28
|
+
assert_equal 0, TimeBandits.consumed
|
29
|
+
assert_equal "", TimeBandits.runtime
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class DummyConsumerTest < Test::Unit::TestCase
|
34
|
+
module DummyConsumer
|
35
|
+
extend self
|
36
|
+
def consumed; 0; end
|
37
|
+
def runtime; "Dummy: 0ms"; end
|
38
|
+
def metrics; {:dummy_time => 0, :dummy_calls => 0}; end
|
39
|
+
def reset; end
|
40
|
+
end
|
41
|
+
|
42
|
+
def setup
|
43
|
+
TimeBandits.time_bandits = []
|
44
|
+
TimeBandits.add DummyConsumer
|
45
|
+
end
|
46
|
+
|
47
|
+
test "getting list of all time bandits" do
|
48
|
+
assert_equal [DummyConsumer], TimeBandits.time_bandits
|
49
|
+
end
|
50
|
+
|
51
|
+
test "adding consumer a second time does not change the list of time bandits" do
|
52
|
+
TimeBandits.add DummyConsumer
|
53
|
+
assert_equal [DummyConsumer], TimeBandits.time_bandits
|
54
|
+
end
|
55
|
+
|
56
|
+
test "reset" do
|
57
|
+
assert_nothing_raised { TimeBandits.reset }
|
58
|
+
end
|
59
|
+
|
60
|
+
test "getting metrics" do
|
61
|
+
assert_equal({:dummy_time => 0, :dummy_calls => 0}, TimeBandits.metrics)
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class MemcachedTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
TimeBandits.time_bandits = []
|
6
|
+
TimeBandits.add TimeBandits::TimeConsumers::Memcached
|
7
|
+
TimeBandits.reset
|
8
|
+
@cache = Memcached.new
|
9
|
+
end
|
10
|
+
|
11
|
+
test "getting metrics" do
|
12
|
+
nothing_measured = {
|
13
|
+
:memcache_time=>0,
|
14
|
+
:memcache_calls=>0,
|
15
|
+
:memcache_misses=>0,
|
16
|
+
:memcache_reads=>0,
|
17
|
+
:memcache_writes=>0
|
18
|
+
}
|
19
|
+
assert_equal nothing_measured, TimeBandits.metrics
|
20
|
+
end
|
21
|
+
|
22
|
+
test "formatting" do
|
23
|
+
assert_equal "MC: 0.000(0r,0m,0w,0c)", TimeBandits.runtime
|
24
|
+
end
|
25
|
+
|
26
|
+
test "foreground work gets accounted for" do
|
27
|
+
work
|
28
|
+
check_work
|
29
|
+
end
|
30
|
+
|
31
|
+
test "background work is ignored" do
|
32
|
+
Thread.new do
|
33
|
+
work
|
34
|
+
check_work
|
35
|
+
end.join
|
36
|
+
m = TimeBandits.metrics
|
37
|
+
assert_equal 0, m[:memcache_calls]
|
38
|
+
assert_equal 0, m[:memcache_reads]
|
39
|
+
assert_equal 0, m[:memcache_misses]
|
40
|
+
assert_equal 0, m[:memcache_writes]
|
41
|
+
assert_equal 0, m[:memcache_time]
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def work
|
46
|
+
2.times do
|
47
|
+
@cache.get("foo")
|
48
|
+
@cache.set("bar", 1)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
def check_work
|
52
|
+
m = TimeBandits.metrics
|
53
|
+
assert_equal 4, m[:memcache_calls]
|
54
|
+
assert_equal 2, m[:memcache_reads]
|
55
|
+
assert_equal 2, m[:memcache_misses]
|
56
|
+
assert_equal 2, m[:memcache_writes]
|
57
|
+
assert 0 < m[:memcache_time]
|
58
|
+
assert_equal m[:memcache_time], TimeBandits.consumed
|
59
|
+
end
|
60
|
+
end
|
data/time_bandits.gemspec
CHANGED
@@ -20,5 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.add_runtime_dependency("thread_variables")
|
21
21
|
s.add_runtime_dependency("activesupport", [">= 2.3.2"])
|
22
22
|
s.add_development_dependency("rake")
|
23
|
+
s.add_development_dependency("mocha")
|
24
|
+
s.add_development_dependency("ansi")
|
23
25
|
end
|
24
26
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: time_bandits
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Kaes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-07-
|
11
|
+
date: 2013-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
type: :development
|
53
53
|
prerelease: false
|
54
54
|
name: rake
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
version_requirements: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
name: mocha
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
type: :development
|
81
|
+
prerelease: false
|
82
|
+
name: ansi
|
55
83
|
description: Rails Completed Line on Steroids
|
56
84
|
email:
|
57
85
|
- skaes@railsexpress.de
|
@@ -65,25 +93,27 @@ files:
|
|
65
93
|
- README_RAILS2.rdoc
|
66
94
|
- Rakefile
|
67
95
|
- TODO
|
68
|
-
- init.rb
|
69
96
|
- lib/time_bandits.rb
|
70
97
|
- lib/time_bandits/monkey_patches/action_controller.rb
|
71
|
-
- lib/time_bandits/monkey_patches/action_controller_rails2.rb
|
72
98
|
- lib/time_bandits/monkey_patches/active_record.rb
|
73
|
-
- lib/time_bandits/monkey_patches/active_record_rails2.rb
|
74
99
|
- lib/time_bandits/monkey_patches/memcache-client.rb
|
75
100
|
- lib/time_bandits/monkey_patches/memcached.rb
|
76
101
|
- lib/time_bandits/rack/logger.rb
|
77
102
|
- lib/time_bandits/rack/logger40.rb
|
78
103
|
- lib/time_bandits/railtie.rb
|
104
|
+
- lib/time_bandits/time_consumers/base_consumer.rb
|
105
|
+
- lib/time_bandits/time_consumers/dalli.rb
|
79
106
|
- lib/time_bandits/time_consumers/database.rb
|
80
|
-
- lib/time_bandits/time_consumers/database_rails2.rb
|
81
107
|
- lib/time_bandits/time_consumers/garbage_collection.rb
|
82
108
|
- lib/time_bandits/time_consumers/jmx.rb
|
83
109
|
- lib/time_bandits/time_consumers/mem_cache.rb
|
84
110
|
- lib/time_bandits/time_consumers/memcached.rb
|
85
111
|
- lib/time_bandits/version.rb
|
86
112
|
- rails/init.rb
|
113
|
+
- test/test_helper.rb
|
114
|
+
- test/unit/active_support_notifications_test.rb
|
115
|
+
- test/unit/base_test.rb
|
116
|
+
- test/unit/memcached_test.rb
|
87
117
|
- time_bandits.gemspec
|
88
118
|
homepage: https://github.com/skaes/time_bandits/
|
89
119
|
licenses: []
|
@@ -108,4 +138,8 @@ rubygems_version: 2.0.5
|
|
108
138
|
signing_key:
|
109
139
|
specification_version: 4
|
110
140
|
summary: Custom performance logging for Rails
|
111
|
-
test_files:
|
141
|
+
test_files:
|
142
|
+
- test/test_helper.rb
|
143
|
+
- test/unit/active_support_notifications_test.rb
|
144
|
+
- test/unit/base_test.rb
|
145
|
+
- test/unit/memcached_test.rb
|