time_bandits 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|