time_bandits 0.3.1 → 0.4.0

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