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
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NWE3YzllNzNjMGYzNmZiYWFlNTc4ODNjNzE2NTc4MTJiNDM2ODFlMA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDRiZmU5NDZjZjkzNWVlMTg4NDVhNjk1MWRlZTAyMjg0NGI4NDNhYg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MGFjMjNkNWNjOGY4NjA5YTM0MTZmMmQwMzIwZDU2MzEyNjk4Y2QzN2EzM2Qy
|
10
|
+
ZjA3ZmE1NDZkN2Y5ODM0NDViNTMzNzc1M2NmZTM4Nzk2ZmQ2YmRlZTg5MGEy
|
11
|
+
MmJmNGUyZWZhMDAzMWMzNmNlMjIwNjg1ZDNiMTlkMTc3OTk0OGU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YzgzYjM2ZjMxMTUyMTNlOTJhMDY3MjBjMmZkY2E4OTExMGQ3Nzg0NjUyYWRk
|
14
|
+
MTdhM2UzNzY3MmE1YWMxYTk0MmYxNTc2YWM2NTQ1ZjBhNDQyYTg0MDExYjg5
|
15
|
+
MmE0OWUxZjE2OGNjMWRmZTRkYTg1NDljMTFmMWVhNmQzYjcwZjQ=
|
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -55,33 +55,42 @@ With these two new time consumers, the log line changes to
|
|
55
55
|
|
56
56
|
Sidenote for Germans: you can use the word "Gesabbel" (eng: drivel) as a mnemonic here ;-)
|
57
57
|
|
58
|
-
It's
|
58
|
+
It's realtively straightforward to write additional time consumers; the more difficult part of this is
|
59
|
+
monkey patching the code which you want to instrument. Have a look at consumers under
|
60
|
+
lib/time_bandits/time_consumers and the corresponding patches under lib/time_bandits/monkey_patches.
|
59
61
|
|
60
62
|
|
61
63
|
== Prerequisites
|
62
64
|
|
63
|
-
Rails 3.x is required. The
|
64
|
-
|
65
|
+
Rails >= 3.x is required. The gem will raise an error if you try to use it with an incompatible
|
66
|
+
version.
|
65
67
|
|
66
|
-
You'll need a ruby with the railsexpress GC patches applied, if you want to include GC and
|
67
|
-
|
68
|
-
|
68
|
+
You'll need a ruby with the railsexpress GC patches applied, if you want to include GC and heap size
|
69
|
+
information in the completed line. This is very useful, especially if you want to analyze your rails
|
70
|
+
logs using logjam (see http://github.com/skaes/logjam/).
|
69
71
|
|
70
|
-
Ruby
|
71
|
-
|
72
|
-
https://github.com/skaes/rvm-patchsets).
|
72
|
+
Ruby only contains a subset of the railsexpress patches. To get the full monty, you can use for example
|
73
|
+
rvm and the railsexpress rvm patchsets (see https://github.com/skaes/rvm-patchsets).
|
73
74
|
|
74
75
|
|
75
76
|
== History
|
76
77
|
|
77
|
-
This plugin started from the code of the 'custom_benchmark' plugin written by
|
78
|
-
|
79
|
-
rewrite, hence we changed the name.
|
78
|
+
This plugin started from the code of the 'custom_benchmark' plugin written by tylerkovacs. However, we
|
79
|
+
changed so much of the code that is is practically a full rewrite, hence we changed the name.
|
80
80
|
|
81
|
+
== Release Notes
|
82
|
+
|
83
|
+
version 0.5:
|
84
|
+
- has dropped rails 2 support
|
85
|
+
- relies on ActiveSupport::Notifications
|
86
|
+
- is suposedly thread safe
|
87
|
+
- all measurements are thread local (except GC statistics)
|
88
|
+
- times are all measured in milliseconds internally
|
89
|
+
- added class TimeBandits::TimeConsumers::BaseConsumer to simplify writing custom consumers
|
81
90
|
|
82
91
|
== License
|
83
92
|
|
84
|
-
Copyright (c) 2009
|
93
|
+
Copyright (c) 2009-2012 Stefan Kaes <skaes@railsexpress.de>
|
85
94
|
|
86
95
|
Permission is hereby granted, free of charge, to any person obtaining
|
87
96
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,2 +1,16 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
include Rake::DSL
|
6
|
+
|
7
|
+
$:.unshift 'lib'
|
8
|
+
require 'time_bandits'
|
9
|
+
|
10
|
+
task :default => :test
|
11
|
+
|
12
|
+
Rake::TestTask.new do |t|
|
13
|
+
t.libs << "test"
|
14
|
+
t.test_files = FileList['test/**/*_test.rb']
|
15
|
+
t.verbose = true
|
16
|
+
end
|
data/lib/time_bandits.rb
CHANGED
@@ -13,9 +13,11 @@ module TimeBandits
|
|
13
13
|
autoload :JMX, 'time_bandits/time_consumers/jmx'
|
14
14
|
autoload :MemCache, 'time_bandits/time_consumers/mem_cache'
|
15
15
|
autoload :Memcached, 'time_bandits/time_consumers/memcached'
|
16
|
+
autoload :Dalli, 'time_bandits/time_consumers/dalli'
|
16
17
|
end
|
17
18
|
|
18
19
|
require 'time_bandits/railtie' if defined?(Rails) && Rails::VERSION::STRING >= "3.0"
|
20
|
+
require 'time_bandits/time_consumers/base_consumer'
|
19
21
|
|
20
22
|
mattr_accessor :time_bandits
|
21
23
|
self.time_bandits = []
|
@@ -33,7 +35,7 @@ module TimeBandits
|
|
33
35
|
end
|
34
36
|
|
35
37
|
def self.runtime
|
36
|
-
time_bandits.map{|b| b.runtime}.join("
|
38
|
+
time_bandits.map{|b| b.runtime}.join("| ")
|
37
39
|
end
|
38
40
|
|
39
41
|
def self.metrics
|
@@ -8,7 +8,6 @@ module ActionController #:nodoc:
|
|
8
8
|
# patch to ensure that the completed line is always written to the log.
|
9
9
|
# this is not necessary anymore with rails 4.
|
10
10
|
def process_action(action, *args)
|
11
|
-
|
12
11
|
raw_payload = get_raw_payload
|
13
12
|
ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload.dup)
|
14
13
|
|
@@ -48,8 +47,7 @@ module ActionController #:nodoc:
|
|
48
47
|
consumed_before_rendering = TimeBandits.consumed
|
49
48
|
runtime = yield
|
50
49
|
consumed_during_rendering = TimeBandits.consumed - consumed_before_rendering
|
51
|
-
|
52
|
-
runtime - consumed_during_rendering*1000
|
50
|
+
runtime - consumed_during_rendering
|
53
51
|
end
|
54
52
|
|
55
53
|
private
|
@@ -92,14 +90,29 @@ module ActionController #:nodoc:
|
|
92
90
|
|
93
91
|
class LogSubscriber
|
94
92
|
# the original method logs the completed line.
|
95
|
-
# but we do it in the middleware.
|
93
|
+
# but we do it in the middleware, unless we're in test mode. don't ask.
|
96
94
|
def process_action(event)
|
97
95
|
payload = event.payload
|
98
96
|
additions = ActionController::Base.log_process_action(payload)
|
97
|
+
|
99
98
|
Thread.current.thread_variable_set(
|
100
99
|
:time_bandits_completed_info,
|
101
100
|
[ event.duration, additions, payload[:view_runtime], "#{payload[:controller]}##{payload[:action]}" ]
|
102
101
|
)
|
102
|
+
|
103
|
+
# this an ugly hack to encure completed lines show up in the test logs
|
104
|
+
# TODO: move this code to some other place
|
105
|
+
return unless Rails.env.test? && Rails::VERSION::STRING >= "3.2"
|
106
|
+
|
107
|
+
status = payload[:status]
|
108
|
+
if status.nil? && payload[:exception].present?
|
109
|
+
exception_class_name = payload[:exception].first
|
110
|
+
status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
|
111
|
+
end
|
112
|
+
message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms" % event.duration
|
113
|
+
message << " (#{additions.join(" | ")})" unless additions.blank?
|
114
|
+
|
115
|
+
info(message)
|
103
116
|
end
|
104
117
|
end
|
105
118
|
|
@@ -6,48 +6,23 @@ require 'memcache'
|
|
6
6
|
raise "MemCache needs to be loaded before monkey patching it" unless defined?(MemCache)
|
7
7
|
|
8
8
|
class MemCache
|
9
|
-
@@cache_latency = 0.0
|
10
|
-
@@cache_touches = 0
|
11
|
-
@@cache_misses = 0
|
12
|
-
|
13
|
-
def self.reset_benchmarks
|
14
|
-
@@cache_latency = 0.0
|
15
|
-
@@cache_touches = 0
|
16
|
-
@@cache_misses = 0
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.get_benchmarks
|
20
|
-
[@@cache_latency, @@cache_touches, @@cache_misses]
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.cache_runtime
|
24
|
-
sprintf "MC: %.3f(%dr,%dm)", @@cache_latency * 1000, @@cache_touches, @@cache_misses
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.metrics
|
28
|
-
{
|
29
|
-
:memcache_time => @@cache_latency * 1000,
|
30
|
-
:memcache_calls => @@cache_touches,
|
31
|
-
:memcache_misses => @@cache_misses
|
32
|
-
}
|
33
|
-
end
|
34
9
|
|
35
10
|
def get_with_benchmark(key, raw = false)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
11
|
+
ActiveSupport::Notifications.instrument("get.memcache") do |payload|
|
12
|
+
val = get_without_benchmark(key, raw)
|
13
|
+
payload[:misses] = val.nil? ? 1 : 0
|
14
|
+
val
|
15
|
+
end
|
41
16
|
end
|
42
17
|
alias_method :get_without_benchmark, :get
|
43
18
|
alias_method :get, :get_with_benchmark
|
44
19
|
|
45
20
|
def get_multi_with_benchmark(*keys)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
21
|
+
ActiveSupport::Notifications.instrument("get.memcache") do |payload|
|
22
|
+
results = get_multi_without_benchmark(*keys)
|
23
|
+
payload[:misses] = keys.size - results.size
|
24
|
+
results
|
25
|
+
end
|
51
26
|
end
|
52
27
|
alias_method :get_multi_without_benchmark, :get_multi
|
53
28
|
alias_method :get_multi, :get_multi_with_benchmark
|
@@ -6,79 +6,38 @@ require 'memcached'
|
|
6
6
|
raise "Memcached needs to be loaded before monkey patching it" unless defined?(Memcached)
|
7
7
|
|
8
8
|
class Memcached
|
9
|
-
|
10
|
-
def self.reset_benchmarks
|
11
|
-
@@cache_latency = 0.0
|
12
|
-
@@cache_calls = 0
|
13
|
-
@@cache_misses = 0
|
14
|
-
@@cache_reads = 0
|
15
|
-
@@cache_writes = 0
|
16
|
-
end
|
17
|
-
self.reset_benchmarks
|
18
|
-
|
19
|
-
def self.get_benchmarks
|
20
|
-
[@@cache_latency, @@cache_calls, @@cache_reads, @@cache_misses, @@cache_writes]
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.cache_runtime
|
24
|
-
sprintf "MC: %.3f(%dr,%dm,%dw,%dc)", @@cache_latency * 1000, @@cache_reads, @@cache_misses, @@cache_writes, @@cache_calls
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.metrics
|
28
|
-
{
|
29
|
-
:memcache_time => @@cache_latency * 1000,
|
30
|
-
:memcache_calls => @@cache_calls,
|
31
|
-
:memcache_misses => @@cache_misses,
|
32
|
-
:memcache_reads => @@cache_reads,
|
33
|
-
:memcache_writes => @@cache_writes
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
9
|
def get_with_benchmark(key, marshal = true)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@@cache_latency += Benchmark.realtime do
|
10
|
+
ActiveSupport::Notifications.instrument("get.memcached") do |payload|
|
11
|
+
if key.is_a?(Array)
|
12
|
+
payload[:reads] = (num_keys = key.size)
|
13
|
+
results = []
|
43
14
|
begin
|
44
15
|
results = get_without_benchmark(key, marshal)
|
45
16
|
rescue Memcached::NotFound
|
46
17
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
@@cache_reads += 1
|
53
|
-
@@cache_latency += Benchmark.realtime do
|
18
|
+
payload[:misses] = num_keys - results.size
|
19
|
+
results
|
20
|
+
else
|
21
|
+
val = nil
|
22
|
+
payload[:reads] = 1
|
54
23
|
begin
|
55
24
|
val = get_without_benchmark(key, marshal)
|
56
25
|
rescue Memcached::NotFound
|
57
26
|
end
|
27
|
+
payload[:misses] = val.nil? ? 1 : 0
|
28
|
+
val
|
58
29
|
end
|
59
|
-
@@cache_misses += 1 if val.nil?
|
60
|
-
val
|
61
30
|
end
|
62
31
|
end
|
63
32
|
alias_method :get_without_benchmark, :get
|
64
33
|
alias_method :get, :get_with_benchmark
|
65
34
|
|
66
35
|
def set_with_benchmark(*args)
|
67
|
-
|
68
|
-
|
69
|
-
result = nil
|
70
|
-
exception = nil
|
71
|
-
@@cache_latency += Benchmark.realtime do
|
72
|
-
begin
|
73
|
-
set_without_benchmark(*args)
|
74
|
-
rescue Exception => exception
|
75
|
-
end
|
36
|
+
ActiveSupport::Notifications.instrument("set.memcached") do
|
37
|
+
set_without_benchmark(*args)
|
76
38
|
end
|
77
|
-
raise exception if exception
|
78
|
-
result
|
79
39
|
end
|
80
40
|
alias_method :set_without_benchmark, :set
|
81
41
|
alias_method :set, :set_with_benchmark
|
82
42
|
|
83
43
|
end
|
84
|
-
|
@@ -55,7 +55,7 @@ module TimeBandits
|
|
55
55
|
completed_info = Thread.current.thread_variable_get(:time_bandits_completed_info)
|
56
56
|
additions = completed_info[1] if completed_info
|
57
57
|
|
58
|
-
message = "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms" %
|
58
|
+
message = "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms" % run_time
|
59
59
|
message << " (#{additions.join(' | ')})" unless additions.blank?
|
60
60
|
info message
|
61
61
|
ensure
|
@@ -77,7 +77,7 @@ module TimeBandits
|
|
77
77
|
status = resp ? resp.first.to_i : 500
|
78
78
|
completed_info = Thread.current.thread_variable_get(:time_bandits_completed_info)
|
79
79
|
additions = completed_info[1] if completed_info
|
80
|
-
message = "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms" %
|
80
|
+
message = "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms" % run_time
|
81
81
|
message << " (#{additions.join(' | ')})" unless additions.blank?
|
82
82
|
logger.info message
|
83
83
|
end
|
data/lib/time_bandits/railtie.rb
CHANGED
@@ -13,16 +13,21 @@ module TimeBandits
|
|
13
13
|
initializer "time_bandits" do |app|
|
14
14
|
app.config.middleware.swap("Rails::Rack::Logger", "TimeBandits::Rack::Logger")
|
15
15
|
|
16
|
-
# rails 4 inserts Rack::Lock in development, but not in production.
|
17
|
-
# time bandits are not thread safe yet, so we insert the Rack::Lock middleware in production.
|
18
|
-
# TODO: make time_bandits thread safe
|
19
|
-
if Rails::VERSION::STRING >= "4.0" && Rails.env.production?
|
20
|
-
app.config.middleware.insert_before("TimeBandits::Rack::Logger", "Rack::Lock")
|
21
|
-
end
|
22
|
-
|
23
16
|
ActiveSupport.on_load(:action_controller) do
|
24
17
|
require 'time_bandits/monkey_patches/action_controller'
|
25
18
|
include ActionController::TimeBanditry
|
19
|
+
|
20
|
+
# make sure TimeBandits.reset is called in test environment as middlewares are not executed
|
21
|
+
if Rails.env.test?
|
22
|
+
require 'action_controller/test_case'
|
23
|
+
module ActionController::TestCase::Behavior
|
24
|
+
def process_with_time_bandits(*args)
|
25
|
+
TimeBandits.reset
|
26
|
+
process_without_time_bandits(*args)
|
27
|
+
end
|
28
|
+
alias_method_chain :process, :time_bandits
|
29
|
+
end
|
30
|
+
end
|
26
31
|
end
|
27
32
|
|
28
33
|
ActiveSupport.on_load(:active_record) do
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module TimeBandits::TimeConsumers
|
2
|
+
class BaseConsumer
|
3
|
+
class << self
|
4
|
+
def instance
|
5
|
+
Thread.current.thread_variable_get(name) ||
|
6
|
+
Thread.current.thread_variable_set(name, new)
|
7
|
+
end
|
8
|
+
|
9
|
+
def prefix(sym)
|
10
|
+
@metrics_prefix = sym
|
11
|
+
end
|
12
|
+
|
13
|
+
# first symbol is used as time measurement
|
14
|
+
def fields(*symbols)
|
15
|
+
@struct = Struct.new(*(symbols.map{|s| "#{@metrics_prefix}_#{s}".to_sym}))
|
16
|
+
symbols.each do |name|
|
17
|
+
class_eval(<<-"EVA", __FILE__, __LINE__ + 1)
|
18
|
+
def #{name}; @counters.#{@metrics_prefix}_#{name}; end
|
19
|
+
def #{name}=(v); @counters.#{@metrics_prefix}_#{name} = v; end
|
20
|
+
EVA
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def format(f, *keys)
|
25
|
+
@runtime_format = f
|
26
|
+
@runtime_keys = keys.map{|s| "#{@metrics_prefix}_#{s}".to_sym}
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :metrics_prefix, :struct, :timer_name, :runtime_format, :runtime_keys
|
30
|
+
|
31
|
+
def method_missing(m, *args)
|
32
|
+
(i = instance).respond_to?(m) ? i.send(m,*args) : super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@counters = self.class.struct.new
|
38
|
+
reset
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset
|
42
|
+
@counters.length.times{|i| @counters[i] = 0}
|
43
|
+
end
|
44
|
+
|
45
|
+
def metrics
|
46
|
+
@counters.members.each_with_object({}){|m,h| h[m] = @counters.send(m)}
|
47
|
+
end
|
48
|
+
|
49
|
+
def consumed
|
50
|
+
@counters[0]
|
51
|
+
end
|
52
|
+
|
53
|
+
def runtime
|
54
|
+
self.class.runtime_format % metrics.values_at(*self.class.runtime_keys)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module TimeBandits::TimeConsumers
|
2
|
+
class Dalli < BaseConsumer
|
3
|
+
prefix :memcache
|
4
|
+
fields :time, :calls, :misses, :reads, :writes
|
5
|
+
format "DALLI: %.3f(%dr,%dm,%dw,%dc)", :time, :reads, :misses, :writes, :calls
|
6
|
+
|
7
|
+
class Subscriber < ActiveSupport::LogSubscriber
|
8
|
+
# cache events are: read write fetch_hit generate delete read_multi increment decrement clear
|
9
|
+
def cache_read(event)
|
10
|
+
i = cache(event)
|
11
|
+
i.reads += 1
|
12
|
+
i.misses += 1 unless event.payload[:hit]
|
13
|
+
end
|
14
|
+
|
15
|
+
def cache_read_multi(event)
|
16
|
+
i = cache(event)
|
17
|
+
i.reads += event.payload[:key].size
|
18
|
+
end
|
19
|
+
|
20
|
+
def cache_write(event)
|
21
|
+
i = cache(event)
|
22
|
+
i.writes += 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def cache_increment(event)
|
26
|
+
i = cache(event)
|
27
|
+
i.writes += 1
|
28
|
+
end
|
29
|
+
|
30
|
+
def cache_decrement(event)
|
31
|
+
i = cache(event)
|
32
|
+
i.writes += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
def cache_delete(event)
|
36
|
+
i = cache(event)
|
37
|
+
i.writes += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def cache(event)
|
42
|
+
i = Dalli.instance
|
43
|
+
i.time += event.duration
|
44
|
+
i.calls += 1
|
45
|
+
i
|
46
|
+
end
|
47
|
+
end
|
48
|
+
Subscriber.attach_to :active_support
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|