time_bandits 0.0.9 → 0.1.0

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