time_bandits 0.3.1 → 0.4.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.
@@ -5,7 +5,8 @@ module ActionController #:nodoc:
5
5
 
6
6
  module Instrumentation
7
7
 
8
- # patch to ensure that the completed line is always written to the log
8
+ # patch to ensure that the completed line is always written to the log.
9
+ # this is not necessary anymore with rails 4.
9
10
  def process_action(action, *args)
10
11
 
11
12
  raw_payload = get_raw_payload
@@ -25,9 +26,9 @@ module ActionController #:nodoc:
25
26
  end
26
27
  raise exception if exception
27
28
  result
28
- end
29
+ end unless Rails::VERSION::STRING =~ /\A4\./
29
30
 
30
- # patch to ensure that render times are always recorded in the log
31
+ # patch to ensure that render times are always recorded in the log.
31
32
  def render(*args)
32
33
  render_output = nil
33
34
  exception = nil
@@ -53,7 +54,7 @@ module ActionController #:nodoc:
53
54
 
54
55
  private
55
56
 
56
- if Rails::VERSION::STRING =~ /^3\.[01]/
57
+ if Rails::VERSION::STRING =~ /\A3\.[01]/
57
58
  def get_raw_payload
58
59
  {
59
60
  :controller => self.class.name,
@@ -64,7 +65,7 @@ module ActionController #:nodoc:
64
65
  :path => (request.fullpath rescue "unknown")
65
66
  }
66
67
  end
67
- elsif Rails::VERSION::STRING =~ /^3\.2/
68
+ elsif Rails::VERSION::STRING =~ /\A3\.2/
68
69
  def get_raw_payload
69
70
  {
70
71
  :controller => self.class.name,
@@ -75,11 +76,12 @@ module ActionController #:nodoc:
75
76
  :path => (request.fullpath rescue "unknown")
76
77
  }
77
78
  end
78
- else
79
+ elsif Rails::VERSION::STRING !~ /\A4\.0/
79
80
  raise "time_bandits ActionController monkey patch is not compatible with your Rails version"
80
81
  end
81
82
 
82
83
  module ClassMethods
84
+ # patch to log rendering time with more precision
83
85
  def log_process_action(payload) #:nodoc:
84
86
  messages, view_runtime = [], payload[:view_runtime]
85
87
  messages << ("Views: %.3fms" % view_runtime.to_f) if view_runtime
@@ -89,6 +91,8 @@ module ActionController #:nodoc:
89
91
  end
90
92
 
91
93
  class LogSubscriber
94
+ # the original method logs the completed line.
95
+ # but we do it in the middleware.
92
96
  def process_action(event)
93
97
  payload = event.payload
94
98
  additions = ActionController::Base.log_process_action(payload)
@@ -99,6 +103,7 @@ module ActionController #:nodoc:
99
103
  end
100
104
  end
101
105
 
106
+ # this gets included in ActionController::Base
102
107
  module TimeBanditry #:nodoc:
103
108
  extend ActiveSupport::Concern
104
109
 
@@ -1,34 +1,59 @@
1
1
  module TimeBandits
2
2
  module Rack
3
3
  class Logger < ActiveSupport::LogSubscriber
4
- # TODO: how to deal with tags
5
- def initialize(app, tags=nil)
4
+ def initialize(app, taggers=nil)
6
5
  @app = app
6
+ @taggers = taggers || Rails.application.config.log_tags || []
7
7
  end
8
8
 
9
9
  def call(env)
10
+ request = ActionDispatch::Request.new(env)
11
+
12
+ if logger.respond_to?(:tagged) && !@taggers.empty?
13
+ logger.tagged(compute_tags(request)) { call_app(request, env) }
14
+ else
15
+ call_app(request, env)
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def call_app(request, env)
10
22
  start_time = Time.now
11
- before_dispatch(env, start_time)
23
+ before_dispatch(request, env, start_time)
12
24
  result = @app.call(env)
13
25
  ensure
14
26
  run_time = Time.now - start_time
15
27
  after_dispatch(env, result, run_time)
16
28
  end
17
29
 
18
- protected
19
- def before_dispatch(env, start_time)
30
+ def compute_tags(request)
31
+ @taggers.collect do |tag|
32
+ case tag
33
+ when Proc
34
+ tag.call(request)
35
+ when Symbol
36
+ request.send(tag)
37
+ else
38
+ tag
39
+ end
40
+ end
41
+ end
42
+
43
+ def before_dispatch(request, env, start_time)
20
44
  TimeBandits.reset
21
45
  Thread.current.thread_variable_set(:time_bandits_completed_info, nil)
22
46
 
23
- request = ActionDispatch::Request.new(env)
24
47
  path = request.filtered_path
25
48
 
26
- info "\n\nStarted #{request.request_method} \"#{path}\" for #{request.ip} at #{start_time.to_default_s}"
49
+ debug ""
50
+ info "Started #{request.request_method} \"#{path}\" for #{request.ip} at #{start_time.to_default_s}"
27
51
  end
28
52
 
29
53
  def after_dispatch(env, result, run_time)
30
- status = result ? result.first : 500
31
- duration, additions, view_time, action = Thread.current.thread_variable_get(:time_bandits_completed_info)
54
+ status = result ? result.first.to_i : 500
55
+ completed_info = Thread.current.thread_variable_get(:time_bandits_completed_info)
56
+ additions = completed_info[1] if completed_info
32
57
 
33
58
  message = "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms" % (run_time*1000)
34
59
  message << " (#{additions.join(' | ')})" unless additions.blank?
@@ -0,0 +1,94 @@
1
+ require 'active_support/core_ext/time/conversions'
2
+ require 'active_support/core_ext/object/blank'
3
+ require 'active_support/log_subscriber'
4
+ require 'action_dispatch/http/request'
5
+ require 'rack/body_proxy'
6
+
7
+ module TimeBandits
8
+ module Rack
9
+ # Sets log tags, logs the request, calls the app, and flushes the logs.
10
+ class Logger < ActiveSupport::LogSubscriber
11
+ def initialize(app, taggers = nil)
12
+ @app = app
13
+ @taggers = taggers || Rails.application.config.log_tags || []
14
+ @instrumenter = ActiveSupport::Notifications.instrumenter
15
+ end
16
+
17
+ def call(env)
18
+ request = ActionDispatch::Request.new(env)
19
+
20
+ if logger.respond_to?(:tagged) && !@taggers.empty?
21
+ logger.tagged(compute_tags(request)) { call_app(request, env) }
22
+ else
23
+ call_app(request, env)
24
+ end
25
+ end
26
+
27
+ protected
28
+
29
+ def call_app(request, env)
30
+ start_time = Time.now
31
+ start(request, start_time)
32
+ resp = @app.call(env)
33
+ resp[2] = ::Rack::BodyProxy.new(resp[2]) { finish(request) }
34
+ resp
35
+ rescue
36
+ finish(request)
37
+ raise
38
+ ensure
39
+ completed(request, Time.now - start_time, resp)
40
+ ActiveSupport::LogSubscriber.flush_all!
41
+ end
42
+
43
+ # Started GET "/session/new" for 127.0.0.1 at 2012-09-26 14:51:42 -0700
44
+ def started_request_message(request, start_time=Time.now)
45
+ 'Started %s "%s" for %s at %s' % [
46
+ request.request_method,
47
+ request.filtered_path,
48
+ request.ip,
49
+ start_time.to_default_s ]
50
+ end
51
+
52
+ def compute_tags(request)
53
+ @taggers.collect do |tag|
54
+ case tag
55
+ when Proc
56
+ tag.call(request)
57
+ when Symbol
58
+ request.send(tag)
59
+ else
60
+ tag
61
+ end
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def start(request, start_time)
68
+ TimeBandits.reset
69
+ Thread.current.thread_variable_set(:time_bandits_completed_info, nil)
70
+ @instrumenter.start 'action_dispatch.request', request: request
71
+
72
+ logger.debug ""
73
+ logger.info started_request_message(request, start_time)
74
+ end
75
+
76
+ def completed(request, run_time, resp)
77
+ status = resp ? resp.first.to_i : 500
78
+ completed_info = Thread.current.thread_variable_get(:time_bandits_completed_info)
79
+ additions = completed_info[1] if completed_info
80
+ message = "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in %.1fms" % (run_time*1000)
81
+ message << " (#{additions.join(' | ')})" unless additions.blank?
82
+ logger.info message
83
+ end
84
+
85
+ def finish(request)
86
+ @instrumenter.finish 'action_dispatch.request', request: request
87
+ end
88
+
89
+ def logger
90
+ @logger ||= Rails.logger
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,7 +1,11 @@
1
1
  module TimeBandits
2
2
 
3
3
  module Rack
4
- autoload :Logger, 'time_bandits/rack/logger'
4
+ if Rails::VERSION::STRING >= "4.0"
5
+ autoload :Logger, 'time_bandits/rack/logger40'
6
+ else
7
+ autoload :Logger, 'time_bandits/rack/logger'
8
+ end
5
9
  end
6
10
 
7
11
  class Railtie < Rails::Railtie
@@ -9,6 +13,13 @@ module TimeBandits
9
13
  initializer "time_bandits" do |app|
10
14
  app.config.middleware.swap("Rails::Rack::Logger", "TimeBandits::Rack::Logger")
11
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_after("Rack::Sendfile", "Rack::Lock")
21
+ end
22
+
12
23
  ActiveSupport.on_load(:action_controller) do
13
24
  require 'time_bandits/monkey_patches/action_controller'
14
25
  include ActionController::TimeBanditry
@@ -1,3 +1,3 @@
1
1
  module TimeBandits
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.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: 17
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 1
10
- version: 0.3.1
8
+ - 4
9
+ - 0
10
+ version: 0.4.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: 2013-02-26 00:00:00 Z
18
+ date: 2013-07-20 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: thread_variables
@@ -72,6 +72,7 @@ files:
72
72
  - lib/time_bandits/monkey_patches/memcache-client.rb
73
73
  - lib/time_bandits/monkey_patches/memcached.rb
74
74
  - lib/time_bandits/rack/logger.rb
75
+ - lib/time_bandits/rack/logger40.rb
75
76
  - lib/time_bandits/railtie.rb
76
77
  - lib/time_bandits/time_consumers/database.rb
77
78
  - lib/time_bandits/time_consumers/database_rails2.rb