time_bandits 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ rdoc
2
+ pkg/*
3
+ *.gem
4
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in time_bandits.gemspec
4
+ gemspec
@@ -0,0 +1,98 @@
1
+ = Time Bandits
2
+
3
+ == About
4
+
5
+ Time Bandits is a plugin which enhances Rails' controller/view/db benchmark logging.
6
+
7
+ == Usage
8
+
9
+ Without configuration, the standard Rails 'Completed line' will change
10
+ from its default format
11
+
12
+ Completed in 56ms (View: 28, DB: 5) | 200 OK [http://127.0.0.1/jobs/info]
13
+
14
+ to:
15
+
16
+ Completed in 56.278ms (View: 28.488, DB: 5.111(2,0)) | 200 OK [http://127.0.0.1/jobs/info]
17
+
18
+ Here "DB: 5.111(2,0)" means that 2 DB queries were executed and there were 0 SQL query cache hits.
19
+
20
+ However, non-trivial applications also rather often use external services, which consume time that adds
21
+ to your total response time, and sometimes these external services are not under your control. In these
22
+ cases, it's very helpful to have an entry in your log file that records the time spent in the exterrnal
23
+ service (so that you can prove that it wasn't your rails app that slowed down during your slashdotting,
24
+ for example ;-).
25
+
26
+ Additional TimeConsumers can be added to the log using the "Timebandits.add" method.
27
+
28
+ Example:
29
+
30
+ TimeBandits.add TimeBandits::TimeConsumers::Memcached
31
+ TimeBandits.add TimeBandits::TimeConsumers::GarbageCollection.instance if GC.respond_to? :enable_stats
32
+
33
+ Here we've added two additional consumers, which are already provided with the plugin. (Note that GC
34
+ information requires a patched ruby, (e.g. http://github.com/skaes/matzruby, branch ruby187pl202patched
35
+ or Ruby Enterprise Edition).
36
+
37
+ With these two new time consumers, the log line changes to
38
+
39
+ Completed in 680.378ms (View: 28.488, DB: 5.111(2,0), MC: 5.382(6r,0m), GC: 120.100(1), HP: 0(2000000,546468,18682541,934967)) | 200 OK [http://127.0.0.1/jobs/info]
40
+
41
+ "MC: 5.382(6r,0m)" means that 6 memcache reads were performed and all keys were found in the cache (0 misses).
42
+
43
+ "GC: 120.100(1)" tells us that 1 garbage collection was triggered during the request, taking 120.100 milliseconds.
44
+
45
+ "HP: 0(2000000,546468,18682541,934967)" shows statistics on heap usage. The format is g(s,a,m,l), where
46
+
47
+ g: heap growth during the request (#slots)
48
+ s: size of the heap after request processing was completed (#slots)
49
+ a: number of object allocations during the request (#slots)
50
+ m: number of bytes allocated by the ruby x_malloc call (#bytes)
51
+ l: live data set size after last GC (#slots)
52
+
53
+ It's pretty easy to write additional time consumers; please refer to the source code.
54
+
55
+
56
+ == Prerequisites
57
+
58
+ Rails 2.3.2, 2.3.3 or 2.3.4 The plugin will raise an error if you try
59
+ to use it with a different version.
60
+
61
+ A ruby with the railsbench GC patches applied, if you want to include
62
+ GC and heap size information in the completed line. This is very
63
+ useful, especially if you want to analyze your rails logs using logjam
64
+ (see http://github.com/alpinegizmo/logjam/).
65
+
66
+
67
+ == History
68
+
69
+ This plugin started from the code of the 'custom_benchmark' plugin
70
+ written by tylerkovacs. However, we changed so much of the code that
71
+ is is practically a full rewrite, hence we changed the name.
72
+
73
+
74
+ == License
75
+
76
+ Copyright (c) 2009 Stefan Kaes <skaes@railsexpress.de>
77
+
78
+ Some portions Copyright (c) 2008 tylerkovacs
79
+
80
+ Permission is hereby granted, free of charge, to any person obtaining
81
+ a copy of this software and associated documentation files (the
82
+ "Software"), to deal in the Software without restriction, including
83
+ without limitation the rights to use, copy, modify, merge, publish,
84
+ distribute, sublicense, and/or sell copies of the Software, and to
85
+ permit persons to whom the Software is furnished to do so, subject to
86
+ the following conditions:
87
+
88
+ The above copyright notice and this permission notice shall be
89
+ included in all copies or substantial portions of the Software.
90
+
91
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
92
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
93
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
94
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
95
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
96
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
97
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
98
+
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,50 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module TimeBandits
4
+
5
+ module TimeConsumers
6
+ autoload :Database, 'time_bandits/time_consumers/database'
7
+ autoload :GarbageCollection, 'time_bandits/time_consumers/garbage_collection'
8
+ autoload :JMX, 'time_bandits/time_consumers/jmx'
9
+ autoload :MemCache, 'time_bandits/time_consumers/mem_cache'
10
+ autoload :Memcached, 'time_bandits/time_consumers/memcached'
11
+ end
12
+
13
+ require 'time_bandits/railtie' if defined?(Rails)
14
+
15
+ mattr_accessor :time_bandits
16
+ self.time_bandits = []
17
+ def self.add(bandit)
18
+ self.time_bandits << bandit unless self.time_bandits.include?(bandit)
19
+ end
20
+
21
+ def self.reset
22
+ time_bandits.each{|b| b.reset}
23
+ end
24
+
25
+ def self.consumed
26
+ time_bandits.map{|b| b.consumed}.sum
27
+ end
28
+
29
+ def self.runtime
30
+ time_bandits.map{|b| b.runtime}.join(", ")
31
+ end
32
+
33
+ def self.benchmark(title="Completed in", logger=Rails.logger)
34
+ reset
35
+ result = nil
36
+ e = nil
37
+ seconds = Benchmark.realtime do
38
+ begin
39
+ result = yield
40
+ rescue Exception => e
41
+ logger.error "Exception: #{e}"
42
+ end
43
+ end
44
+ consumed # needs to be called for DB time consumer
45
+ rc = e ? "500 Internal Server Error" : "200 OK"
46
+ logger.info "#{title} #{sprintf("%.3f", seconds * 1000)}ms (#{runtime}) | #{rc}"
47
+ raise e if e
48
+ result
49
+ end
50
+ end
@@ -0,0 +1,85 @@
1
+ require 'action_controller/metal/instrumentation'
2
+ require 'action_controller/log_subscriber'
3
+
4
+ module ActionController #:nodoc:
5
+
6
+ module Instrumentation
7
+
8
+ # patch to ensure that the completed line is always written to the log
9
+ def process_action(action, *args)
10
+ TimeBandits.reset
11
+
12
+ raw_payload = {
13
+ :controller => self.class.name,
14
+ :action => self.action_name,
15
+ :params => request.filtered_parameters,
16
+ :formats => request.formats.map(&:to_sym),
17
+ :method => request.method,
18
+ :path => (request.fullpath rescue "unknown")
19
+ }
20
+
21
+ ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload.dup)
22
+
23
+ exception = nil
24
+ result = ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
25
+ begin
26
+ super
27
+ rescue Exception => exception
28
+ response.status = 500
29
+ nil
30
+ ensure
31
+ payload[:status] = response.status
32
+ append_info_to_payload(payload)
33
+ end
34
+ end
35
+ raise exception if exception
36
+ result
37
+ end
38
+
39
+ # patch to ensure that render times are always recorded in the log
40
+ def render(*args)
41
+ render_output = nil
42
+ exception = nil
43
+ self.view_runtime = cleanup_view_runtime do
44
+ Benchmark.ms do
45
+ begin
46
+ render_output = super
47
+ rescue Exception => exception
48
+ end
49
+ end
50
+ end
51
+ raise exception if exception
52
+ render_output
53
+ end
54
+
55
+ def cleanup_view_runtime #:nodoc:
56
+ consumed_before_rendering = TimeBandits.consumed
57
+ runtime = yield
58
+ consumed_during_rendering = TimeBandits.consumed - consumed_before_rendering
59
+ runtime - consumed_during_rendering
60
+ end
61
+ end
62
+
63
+ class LogSubscriber
64
+ def process_action(event)
65
+ payload = event.payload
66
+ additions = ActionController::Base.log_process_action(payload)
67
+ Thread.current[:time_bandits_completed_info] = [event.duration, additions]
68
+ end
69
+ end
70
+
71
+ module TimeBanditry #:nodoc:
72
+ extend ActiveSupport::Concern
73
+
74
+ module ClassMethods
75
+ def log_process_action(payload) #:nodoc:
76
+ messages = super
77
+ TimeBandits.time_bandits.each do |bandit|
78
+ messages << bandit.runtime
79
+ end
80
+ messages
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,85 @@
1
+ # this file monkey patches class ActiveRecord::ConnectionAdapters::AbstractAdapter
2
+ # and the module module ActiveRecord::ConnectionAdapters::QueryCache
3
+ # to count the number of sql statements being executed.
4
+ # it needs to be adapted to each new rails version
5
+
6
+ raise "AR abstract adapter monkey patch for custom benchmarking is not compatible with your rails version" unless %w(2.3.2 2.3.3 2.3.4 2.3.8 2.3.9 2.3.10).include?(Rails::VERSION::STRING)
7
+
8
+ module ActiveRecord
9
+ module ConnectionAdapters
10
+ class ConnectionPool
11
+ attr_reader :connections
12
+ end
13
+
14
+ class AbstractAdapter
15
+ attr_accessor :call_count, :query_cache_hits
16
+
17
+ def initialize(connection, logger = nil) #:nodoc:
18
+ @connection, @logger = connection, logger
19
+ @runtime = 0
20
+ @call_count = 0
21
+ @last_verification = 0
22
+ @query_cache_enabled = false
23
+ @query_cache_hits = 0
24
+ end
25
+
26
+ def reset_call_count
27
+ calls = @call_count
28
+ @call_count = 0
29
+ calls
30
+ end
31
+
32
+ def reset_query_cache_hits
33
+ hits = @query_cache_hits
34
+ @query_cache_hits = 0
35
+ hits
36
+ end
37
+
38
+ protected
39
+ def log(sql, name)
40
+ if block_given?
41
+ result = nil
42
+ seconds = Benchmark.realtime { result = yield }
43
+ @runtime += seconds
44
+ @call_count += 1
45
+ log_info(sql, name, seconds * 1000)
46
+ result
47
+ else
48
+ log_info(sql, name, 0)
49
+ nil
50
+ end
51
+ rescue Exception => e
52
+ # Log message and raise exception.
53
+ # Set last_verification to 0, so that connection gets verified
54
+ # upon reentering the request loop
55
+ @last_verification = 0
56
+ message = "#{e.class.name}: #{e.message}: #{sql}"
57
+ log_info(message, name, 0)
58
+ raise ActiveRecord::StatementInvalid, message
59
+ end
60
+ end
61
+
62
+ module QueryCache
63
+ private
64
+ def cache_sql(sql)
65
+ result =
66
+ if @query_cache.has_key?(sql)
67
+ @query_cache_hits += 1
68
+ log_info(sql, "CACHE", 0.0)
69
+ @query_cache[sql]
70
+ else
71
+ @query_cache[sql] = yield
72
+ end
73
+
74
+ if Array === result
75
+ result.collect { |row| row.dup }
76
+ else
77
+ result.duplicable? ? result.dup : result
78
+ end
79
+ rescue TypeError
80
+ result
81
+ end
82
+ end
83
+ end
84
+ end
85
+
@@ -0,0 +1,48 @@
1
+ # Add this line to your ApplicationController (app/controllers/application.rb)
2
+ # to enable logging for memcache-client:
3
+ # time_bandit MemCache
4
+
5
+ require 'memcache'
6
+ raise "MemCache needs to be loaded before monkey patching it" unless defined?(MemCache)
7
+
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 get_with_benchmark(key, raw = false)
28
+ val = nil
29
+ @@cache_latency += Benchmark.realtime{ val=get_without_benchmark(key, raw) }
30
+ @@cache_touches += 1
31
+ @@cache_misses += 1 if val.nil?
32
+ val
33
+ end
34
+ alias_method :get_without_benchmark, :get
35
+ alias_method :get, :get_with_benchmark
36
+
37
+ def get_multi_with_benchmark(*keys)
38
+ results = nil
39
+ @@cache_latency += Benchmark.realtime{ results=get_multi_without_benchmark(*keys) }
40
+ @@cache_touches += 1
41
+ @@cache_misses += keys.size - results.size
42
+ results
43
+ end
44
+ alias_method :get_multi_without_benchmark, :get_multi
45
+ alias_method :get_multi, :get_multi_with_benchmark
46
+
47
+ end
48
+
@@ -0,0 +1,55 @@
1
+ # Add this line to your ApplicationController (app/controllers/application_controller.rb)
2
+ # to enable logging for memcached:
3
+ # time_bandit TimeBandits::TimeConsumers::Memcached
4
+
5
+ require 'memcached'
6
+ raise "Memcached needs to be loaded before monkey patching it" unless defined?(Memcached)
7
+
8
+ class Memcached
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 get_with_benchmark(key, marshal = true)
28
+ @@cache_touches += 1
29
+ if key.is_a?(Array)
30
+ results = []
31
+ @@cache_latency += Benchmark.realtime do
32
+ begin
33
+ results = get_without_benchmark(key, marshal)
34
+ rescue Memcached::NotFound
35
+ end
36
+ end
37
+ @@cache_misses += key.size - results.size
38
+ results
39
+ else
40
+ val = nil
41
+ @@cache_latency += Benchmark.realtime do
42
+ begin
43
+ val = get_without_benchmark(key, marshal)
44
+ rescue Memcached::NotFound
45
+ end
46
+ end
47
+ @@cache_misses += 1 if val.nil?
48
+ val
49
+ end
50
+ end
51
+ alias_method :get_without_benchmark, :get
52
+ alias_method :get, :get_with_benchmark
53
+
54
+ end
55
+
@@ -0,0 +1,36 @@
1
+ require 'rails/rack/logger'
2
+
3
+ module Rails
4
+ module Rack
5
+ class Logger
6
+
7
+ def call(env)
8
+ Thread.current[:time_bandits_completed_info] = nil
9
+ start_time = before_dispatch(env)
10
+ result = @app.call(env)
11
+ ensure
12
+ run_time = Time.now - start_time
13
+ status = result.first
14
+ duration, additions = Thread.current[:time_bandits_completed_info]
15
+ (additions ||= []).insert(0, "Controller: %.1fms" % duration)
16
+
17
+ message = "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms (#{additions.join(' | ')})" % (run_time*1000)
18
+ info message
19
+
20
+ after_dispatch(env)
21
+ end
22
+
23
+ protected
24
+ def before_dispatch(env)
25
+ start_time = Time.now
26
+ request = ActionDispatch::Request.new(env)
27
+ path = request.fullpath
28
+
29
+ info "\n\nStarted #{request.request_method} \"#{path}\" " \
30
+ "for #{request.ip} at #{start_time.to_default_s}"
31
+ start_time
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ module TimeBandits
2
+ class Railtie < Rails::Railtie
3
+
4
+ initializer "time_bandits" do
5
+ ActiveSupport.on_load(:action_controller) do
6
+ require 'time_bandits/monkey_patches/rails_rack_logger'
7
+ require 'time_bandits/monkey_patches/action_controller'
8
+ include ActionController::TimeBanditry
9
+ end
10
+
11
+ ActiveSupport.on_load(:active_record) do
12
+ require 'time_bandits/monkey_patches/activerecord_adapter'
13
+ TimeBandits.add TimeBandits::TimeConsumers::Database.instance
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,55 @@
1
+ # this consumer gets installed automatically by the plugin
2
+ # if this were not so
3
+ #
4
+ # time_bandit TimeBandits::TimeConsumers::Database.new
5
+ #
6
+ # would do the job
7
+
8
+ module TimeBandits
9
+ module TimeConsumers
10
+ # provide a time consumer interface to ActiveRecord for perform_action_with_benchmark and render_with_benchmark
11
+ class Database
12
+ def initialize
13
+ @consumed = 0.0
14
+ @call_count = 0
15
+ @query_cache_hits = 0
16
+ end
17
+ private :initialize
18
+
19
+ def self.instance
20
+ @instance ||= new
21
+ end
22
+
23
+ def reset
24
+ reset_stats
25
+ @call_count = 0
26
+ @consumed = 0.0
27
+ @query_cache_hits = 0
28
+ end
29
+
30
+ def consumed
31
+ hits, calls, time = reset_stats
32
+ @query_cache_hits += hits
33
+ @call_count += calls
34
+ @consumed += time
35
+ end
36
+
37
+ def runtime
38
+ sprintf "DB: %.3f(%d,%d)", @consumed * 1000, @call_count, @query_cache_hits
39
+ end
40
+
41
+ private
42
+ def all_connections
43
+ ActiveRecord::Base.connection_handler.connection_pools.values.map{|pool| pool.connections}.flatten
44
+ end
45
+
46
+ def reset_stats
47
+ connections = all_connections
48
+ hits = connections.map{|c| c.reset_query_cache_hits}.sum
49
+ calls = connections.map{|c| c.reset_call_count}.sum
50
+ time = connections.map{|c| c.reset_runtime}.sum
51
+ [hits, calls, time]
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,94 @@
1
+ # a time consumer implementation for garbage collection
2
+ module TimeBandits
3
+ module TimeConsumers
4
+ class GarbageCollection
5
+ @@heap_dumps_enabled = false
6
+ def self.heap_dumps_enabled=(v)
7
+ @@heap_dumps_enabled = v
8
+ end
9
+
10
+ def initialize
11
+ GC.enable_stats
12
+ reset
13
+ end
14
+ private :initialize
15
+
16
+ def self.instance
17
+ @instance ||= new
18
+ end
19
+
20
+ if GC.respond_to? :heap_slots
21
+
22
+ def reset
23
+ @consumed = GC.time
24
+ @collections = GC.collections
25
+ @allocated_objects = ObjectSpace.allocated_objects
26
+ @allocated_size = GC.allocated_size
27
+ @heap_slots = GC.heap_slots
28
+ end
29
+
30
+ else
31
+
32
+ def reset
33
+ @consumed = GC.time
34
+ @collections = GC.collections
35
+ end
36
+
37
+ end
38
+
39
+ def consumed
40
+ 0.0
41
+ end
42
+
43
+ def consumed_gc_time
44
+ (GC.time - @consumed).to_f / 1_000_000
45
+ end
46
+
47
+ def collections
48
+ GC.collections - @collections
49
+ end
50
+
51
+ if GC.respond_to? :heap_slots
52
+
53
+ def allocated_objects
54
+ ObjectSpace.allocated_objects - @allocated_objects
55
+ end
56
+
57
+ def allocated_size
58
+ GC.allocated_size - @allocated_size
59
+ end
60
+
61
+ def heap_growth
62
+ GC.heap_slots - @heap_slots
63
+ end
64
+
65
+ if GC.respond_to? :heap_slots_live_after_last_gc
66
+ def live_data_set_size
67
+ GC.heap_slots_live_after_last_gc
68
+ end
69
+ else
70
+ def live_data_set_size
71
+ 0
72
+ end
73
+ end
74
+
75
+ def runtime
76
+ heap_slots = GC.heap_slots
77
+ heap_growth = self.heap_growth
78
+ allocated_objects = self.allocated_objects
79
+ allocated_size = self.allocated_size
80
+ GCHacks.heap_dump if heap_growth > 0 && @@heap_dumps_enabled
81
+ "GC: %.3f(%d) | HP: %d(%d,%d,%d,%d)" %
82
+ [consumed_gc_time * 1000, collections, heap_growth, heap_slots, allocated_objects, allocated_size, live_data_set_size]
83
+ end
84
+
85
+ else
86
+
87
+ def runtime
88
+ "GC: %.3f(%d)" % [consumed_gc_time * 1000, collections]
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,77 @@
1
+ # a time consumer implementation for jruby, using jxm
2
+ #
3
+ # the gc counts and times reported are summed over all the garbage collectors
4
+ # heap_growth reflects changes in the committed size of the java heap
5
+ # heap_size is the committed size of the java heap
6
+ # allocated_size reflects changes in the active (used) part of the java heap
7
+ # java non-heap memory is not reported
8
+
9
+ module TimeBandits
10
+ module TimeConsumers
11
+ class JMX
12
+ def initialize
13
+ @server = ::JMX::MBeanServer.new
14
+ @memory_bean = @server["java.lang:type=Memory"]
15
+ @collectors = @server.query_names "java.lang:type=GarbageCollector,*"
16
+ reset
17
+ end
18
+ private :initialize
19
+
20
+ def self.instance
21
+ @instance ||= new
22
+ end
23
+
24
+ def consumed
25
+ 0.0
26
+ end
27
+
28
+ def gc_time
29
+ @collectors.to_array.map {|gc| @server[gc].collection_time}.sum
30
+ end
31
+
32
+ def gc_collections
33
+ @collectors.to_array.map {|gc| @server[gc].collection_count}.sum
34
+ end
35
+
36
+ def heap_size
37
+ @memory_bean.heap_memory_usage.committed
38
+ end
39
+
40
+ def heap_usage
41
+ @memory_bean.heap_memory_usage.used
42
+ end
43
+
44
+ def reset
45
+ @consumed = gc_time
46
+ @collections = gc_collections
47
+ @heap_committed = heap_size
48
+ @heap_used = heap_usage
49
+ end
50
+
51
+ def collections_delta
52
+ gc_collections - @collections
53
+ end
54
+
55
+ def gc_time_delta
56
+ (gc_time - @consumed).to_f
57
+ end
58
+
59
+ def heap_growth
60
+ heap_size - @heap_committed
61
+ end
62
+
63
+ def usage_growth
64
+ heap_usage - @heap_used
65
+ end
66
+
67
+ def allocated_objects
68
+ 0
69
+ end
70
+
71
+ def runtime
72
+ "GC: %.3f(%d), HP: %d(%d,%d,%d)" % [gc_time_delta, collections_delta, heap_growth, heap_size, allocated_objects, usage_growth]
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,25 @@
1
+ # a time consumer implementation for memchache
2
+ # install into application_controller.rb with the line
3
+ #
4
+ # time_bandit TimeBandits::TimeConsumers::MemCache
5
+ #
6
+ require 'time_bandits/monkey_patches/memcache-client'
7
+ module TimeBandits
8
+ module TimeConsumers
9
+ class MemCache
10
+ class << self
11
+ def reset
12
+ ::MemCache.reset_benchmarks
13
+ end
14
+
15
+ def consumed
16
+ ::MemCache.get_benchmarks.first
17
+ end
18
+
19
+ def runtime
20
+ ::MemCache.cache_runtime
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # a time consumer implementation for memchached
2
+ # install into application_controller.rb with the line
3
+ #
4
+ # time_bandit TimeBandits::TimeConsumers::Memcached
5
+ #
6
+ require 'time_bandits/monkey_patches/memcached'
7
+ module TimeBandits
8
+ module TimeConsumers
9
+ class Memcached
10
+ class << self
11
+ def reset
12
+ ::Memcached.reset_benchmarks
13
+ end
14
+
15
+ def consumed
16
+ ::Memcached.get_benchmarks.first
17
+ end
18
+
19
+ def runtime
20
+ ::Memcached.cache_runtime
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module TimeBandits
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "time_bandits/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "time_bandits"
7
+ s.version = TimeBandits::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Stefan Kaes"]
10
+ s.email = ["skaes@railsexpress.de"]
11
+ s.homepage = "https://github.com/skaes/time_bandits"
12
+ s.summary = %q{Custom performance logging for Rails}
13
+ s.description = %q{Enables customizable performance logging for Rails applications}
14
+
15
+ s.rubyforge_project = "time_bandits"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_runtime_dependency("activesupport", ["~> 3.0"])
23
+ end
24
+
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time_bandits
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Stefan Kaes
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-29 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ version: "3.0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: Enables customizable performance logging for Rails applications
37
+ email:
38
+ - skaes@railsexpress.de
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - .gitignore
47
+ - Gemfile
48
+ - README.rdoc
49
+ - Rakefile
50
+ - lib/time_bandits.rb
51
+ - lib/time_bandits/monkey_patches/action_controller.rb
52
+ - lib/time_bandits/monkey_patches/activerecord_adapter.rb
53
+ - lib/time_bandits/monkey_patches/memcache-client.rb
54
+ - lib/time_bandits/monkey_patches/memcached.rb
55
+ - lib/time_bandits/monkey_patches/rails_rack_logger.rb
56
+ - lib/time_bandits/railtie.rb
57
+ - lib/time_bandits/time_consumers/database.rb
58
+ - lib/time_bandits/time_consumers/garbage_collection.rb
59
+ - lib/time_bandits/time_consumers/jmx.rb
60
+ - lib/time_bandits/time_consumers/mem_cache.rb
61
+ - lib/time_bandits/time_consumers/memcached.rb
62
+ - lib/time_bandits/version.rb
63
+ - time_bandits.gemspec
64
+ has_rdoc: true
65
+ homepage: https://github.com/skaes/time_bandits
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 3
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ requirements: []
92
+
93
+ rubyforge_project: time_bandits
94
+ rubygems_version: 1.3.7
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: Custom performance logging for Rails
98
+ test_files: []
99
+