time_bandits 0.0.9 → 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 CHANGED
@@ -3,3 +3,5 @@ Gemfile.lock
3
3
  pkg/*
4
4
  *.gem
5
5
  .bundle
6
+ .DS_Store
7
+ .rvmrc
data/lib/time_bandits.rb CHANGED
@@ -18,6 +18,7 @@ module TimeBandits
18
18
 
19
19
  mattr_accessor :time_bandits
20
20
  self.time_bandits = []
21
+
21
22
  def self.add(bandit)
22
23
  self.time_bandits << bandit unless self.time_bandits.include?(bandit)
23
24
  end
@@ -34,6 +35,12 @@ module TimeBandits
34
35
  time_bandits.map{|b| b.runtime}.join(", ")
35
36
  end
36
37
 
38
+ def self.metrics
39
+ metrics = {}
40
+ time_bandits.each{|b| metrics.merge! b.metrics}
41
+ metrics
42
+ end
43
+
37
44
  def self.benchmark(title="Completed in", logger=Rails.logger)
38
45
  reset
39
46
  result = nil
@@ -42,7 +49,7 @@ module TimeBandits
42
49
  begin
43
50
  result = yield
44
51
  rescue Exception => e
45
- logger.error "Exception: #{e}"
52
+ logger.error "Exception: #{e}:\n#{e.backtrace[0..5].join("\n")}"
46
53
  end
47
54
  end
48
55
  consumed # needs to be called for DB time consumer
@@ -3,7 +3,6 @@
3
3
  #
4
4
  # the original rails stack looks like this:
5
5
  #
6
- # ApplicationController#process_with_unload_user
7
6
  # ActionController::SessionManagement#process_with_session_management_support
8
7
  # ActionController::Filters#process_with_filters
9
8
  # ActionController::Base#process
@@ -17,7 +16,6 @@
17
16
  #
18
17
  # with the plugin installed, the stack looks like this:
19
18
  #
20
- # ApplicationController#process_with_unload_user
21
19
  # ActionController::SessionManagement#process_with_session_management_support
22
20
  # ActionController::Filters#process_with_filters
23
21
  # ActionController::Base#process
@@ -31,6 +29,23 @@
31
29
  # =========================================================================================================
32
30
 
33
31
  module ActionController #:nodoc:
32
+
33
+ class Base
34
+ # this ugly hack is used to get the started_at and ip information into time bandits metrics
35
+ def request_origin
36
+ # this *needs* to be cached!
37
+ # otherwise you'd get different results if calling it more than once
38
+ @request_origin ||=
39
+ begin
40
+ remote_ip = request.remote_ip
41
+ t = Time.now
42
+ started_at = "#{t.to_s(:db)}.#{t.usec}"
43
+ request.env["time_bandits.metrics"] = {:ip => remote_ip, :started_at => started_at}
44
+ "#{remote_ip} at #{started_at}"
45
+ end
46
+ end
47
+ end
48
+
34
49
  module TimeBanditry #:nodoc:
35
50
  def self.included(base)
36
51
  base.class_eval do
@@ -88,6 +103,7 @@ module ActionController #:nodoc:
88
103
 
89
104
  logger.info(log_message)
90
105
  response.headers["X-Runtime"] = "#{sprintf("%.0f", seconds * 1000)}ms"
106
+ merge_metrics(seconds)
91
107
  else
92
108
  perform_action_without_time_bandits
93
109
  end
@@ -114,6 +130,7 @@ module ActionController #:nodoc:
114
130
 
115
131
  logger.info(log_message)
116
132
  response.headers["X-Runtime"] = "#{sprintf("%.0f", seconds * 1000)}ms"
133
+ merge_metrics(seconds)
117
134
  else
118
135
  rescue_action_without_time_bandits(exception)
119
136
  end
@@ -121,6 +138,16 @@ module ActionController #:nodoc:
121
138
 
122
139
  private
123
140
 
141
+ def merge_metrics(total_time_seconds)
142
+ basic_request_metrics = {
143
+ :total_time => total_time_seconds * 1000,
144
+ :view_time => (@view_runtime||0) * 1000,
145
+ :code => response.status.to_i,
146
+ :action => "#{self.class.name}\##{action_name}",
147
+ }
148
+ request.env["time_bandits.metrics"].merge!(TimeBandits.metrics).merge!(basic_request_metrics)
149
+ end
150
+
124
151
  def view_runtime
125
152
  "View: %.3f" % ((@view_runtime||0) * 1000)
126
153
  end
@@ -24,6 +24,14 @@ class MemCache
24
24
  sprintf "MC: %.3f(%dr,%dm)", @@cache_latency * 1000, @@cache_touches, @@cache_misses
25
25
  end
26
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
+
27
35
  def get_with_benchmark(key, raw = false)
28
36
  val = nil
29
37
  @@cache_latency += Benchmark.realtime{ val=get_without_benchmark(key, raw) }
@@ -6,27 +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
- @@cache_latency = 0.0
10
- @@cache_touches = 0
11
- @@cache_misses = 0
12
9
 
13
10
  def self.reset_benchmarks
14
11
  @@cache_latency = 0.0
15
- @@cache_touches = 0
12
+ @@cache_calls = 0
16
13
  @@cache_misses = 0
14
+ @@cache_reads = 0
15
+ @@cache_writes = 0
17
16
  end
17
+ self.reset_benchmarks
18
18
 
19
19
  def self.get_benchmarks
20
- [@@cache_latency, @@cache_touches, @@cache_misses]
20
+ [@@cache_latency, @@cache_calls, @@cache_reads, @@cache_misses, @@cache_writes]
21
21
  end
22
22
 
23
23
  def self.cache_runtime
24
- sprintf "MC: %.3f(%dr,%dm)", @@cache_latency * 1000, @@cache_touches, @@cache_misses
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
+ }
25
35
  end
26
36
 
27
37
  def get_with_benchmark(key, marshal = true)
28
- @@cache_touches += 1
38
+ @@cache_calls += 1
29
39
  if key.is_a?(Array)
40
+ @@cache_reads += (num_keys = key.size)
30
41
  results = []
31
42
  @@cache_latency += Benchmark.realtime do
32
43
  begin
@@ -34,10 +45,11 @@ class Memcached
34
45
  rescue Memcached::NotFound
35
46
  end
36
47
  end
37
- @@cache_misses += key.size - results.size
48
+ @@cache_misses += num_keys - results.size
38
49
  results
39
50
  else
40
51
  val = nil
52
+ @@cache_reads += 1
41
53
  @@cache_latency += Benchmark.realtime do
42
54
  begin
43
55
  val = get_without_benchmark(key, marshal)
@@ -51,5 +63,22 @@ class Memcached
51
63
  alias_method :get_without_benchmark, :get
52
64
  alias_method :get, :get_with_benchmark
53
65
 
66
+ def set_with_benchmark(*args)
67
+ @@cache_calls += 1
68
+ @@cache_writes += 1
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
76
+ end
77
+ raise exception if exception
78
+ result
79
+ end
80
+ alias_method :set_without_benchmark, :set
81
+ alias_method :set, :set_with_benchmark
82
+
54
83
  end
55
84
 
@@ -36,6 +36,14 @@ module TimeBandits
36
36
  sprintf "ActiveRecord: %.3fms(%dq,%dh)", *info
37
37
  end
38
38
 
39
+ def metrics
40
+ {
41
+ :db_calls => @call_count,
42
+ :db_sql_query_cache_hits => @query_cache_hits,
43
+ :db_time => @consumed * 1000
44
+ }
45
+ end
46
+
39
47
  private
40
48
 
41
49
  def reset_stats
@@ -36,6 +36,14 @@ module TimeBandits
36
36
  sprintf "DB: %.3f(%d,%d)", @consumed * 1000, @call_count, @query_cache_hits
37
37
  end
38
38
 
39
+ def metrics
40
+ {
41
+ :db_calls => @call_count,
42
+ :db_sql_query_cache_hits => @query_cache_hits,
43
+ :db_time => @consumed * 1000
44
+ }
45
+ end
46
+
39
47
  private
40
48
  def all_connections
41
49
  ActiveRecord::Base.connection_handler.connection_pools.values.map{|pool| pool.connections}.flatten
@@ -87,12 +87,31 @@ module TimeBandits
87
87
  GCFORMAT % [consumed_gc_time * 1000, collections, heap_growth, heap_slots, allocated_objects, allocated_size, live_data_set_size]
88
88
  end
89
89
 
90
+ def metrics
91
+ {
92
+ :gc_time => consumed_gc_time * 1000,
93
+ :gc_calls => collections,
94
+ :heap_growth => heap_growth,
95
+ :heap_size => GC.heap_slots,
96
+ :allocated_objects => allocated_objects,
97
+ :allocated_bytes => allocated_size,
98
+ :live_data_set_size => live_data_set_size
99
+ }
100
+ end
101
+
90
102
  else
91
103
 
92
104
  def runtime
93
105
  "GC: %.3f(%d)" % [consumed_gc_time * 1000, collections]
94
106
  end
95
107
 
108
+ def metrics
109
+ {
110
+ :gc_time => consumed_gc_time * 1000,
111
+ :gc_calls => collections
112
+ }
113
+ end
114
+
96
115
  end
97
116
  end
98
117
  end
@@ -19,6 +19,10 @@ module TimeBandits
19
19
  def runtime
20
20
  ::MemCache.cache_runtime
21
21
  end
22
+
23
+ def metrics
24
+ ::MemCache.metrics
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -19,6 +19,10 @@ module TimeBandits
19
19
  def runtime
20
20
  ::Memcached.cache_runtime
21
21
  end
22
+
23
+ def metrics
24
+ ::Memcached.metrics
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -1,3 +1,3 @@
1
1
  module TimeBandits
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_bandits
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
5
- prerelease: false
4
+ hash: 27
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 9
10
- version: 0.0.9
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Stefan Kaes
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-18 00:00:00 +02:00
18
+ date: 2011-08-28 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -99,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
99
  requirements: []
100
100
 
101
101
  rubyforge_project:
102
- rubygems_version: 1.3.7
102
+ rubygems_version: 1.6.2
103
103
  signing_key:
104
104
  specification_version: 3
105
105
  summary: Custom performance logging for Rails