timber 1.1.14 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -2
  3. data/.travis.yml +47 -0
  4. data/Gemfile +1 -28
  5. data/README.md +83 -298
  6. data/bin/timber +13 -0
  7. data/gemfiles/rails-3.0.gemfile +5 -0
  8. data/gemfiles/rails-3.1.gemfile +5 -0
  9. data/gemfiles/rails-3.2.gemfile +5 -0
  10. data/gemfiles/rails-4.0.gemfile +9 -0
  11. data/gemfiles/rails-4.1.gemfile +9 -0
  12. data/gemfiles/rails-4.2.gemfile +9 -0
  13. data/gemfiles/rails-5.0.gemfile +9 -0
  14. data/gemfiles/rails-edge.gemfile +7 -0
  15. data/lib/timber.rb +7 -7
  16. data/lib/timber/cli.rb +72 -0
  17. data/lib/timber/cli/api.rb +104 -0
  18. data/lib/timber/cli/application.rb +28 -0
  19. data/lib/timber/cli/install.rb +186 -0
  20. data/lib/timber/cli/io_helper.rb +58 -0
  21. data/lib/timber/cli/messages.rb +170 -0
  22. data/lib/timber/config.rb +47 -6
  23. data/lib/timber/contexts/http.rb +2 -2
  24. data/lib/timber/current_context.rb +1 -1
  25. data/lib/timber/event.rb +8 -0
  26. data/lib/timber/events.rb +2 -0
  27. data/lib/timber/events/controller_call.rb +12 -3
  28. data/lib/timber/events/exception.rb +4 -3
  29. data/lib/timber/events/http_client_request.rb +61 -0
  30. data/lib/timber/events/http_client_response.rb +47 -0
  31. data/lib/timber/events/http_server_request.rb +15 -23
  32. data/lib/timber/events/http_server_response.rb +9 -9
  33. data/lib/timber/events/sql_query.rb +2 -2
  34. data/lib/timber/events/template_render.rb +2 -2
  35. data/lib/timber/frameworks/rails.rb +31 -6
  36. data/lib/timber/integrations.rb +22 -0
  37. data/lib/timber/integrations/action_controller/log_subscriber.rb +25 -0
  38. data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +40 -0
  39. data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +51 -0
  40. data/lib/timber/integrations/action_view/log_subscriber.rb +25 -0
  41. data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +73 -0
  42. data/lib/timber/integrations/active_record/log_subscriber.rb +25 -0
  43. data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +39 -0
  44. data/lib/timber/integrations/active_support/tagged_logging.rb +71 -0
  45. data/lib/timber/integrations/rack.rb +16 -0
  46. data/lib/timber/integrations/rack/exception_event.rb +28 -0
  47. data/lib/timber/integrations/rack/http_context.rb +25 -0
  48. data/lib/timber/integrations/rack/http_events.rb +46 -0
  49. data/lib/timber/integrations/rack/user_context.rb +59 -0
  50. data/lib/timber/integrations/rails/rack_logger.rb +49 -0
  51. data/lib/timber/integrator.rb +24 -0
  52. data/lib/timber/log_devices/http.rb +14 -21
  53. data/lib/timber/log_entry.rb +1 -1
  54. data/lib/timber/logger.rb +38 -12
  55. data/lib/timber/overrides.rb +9 -0
  56. data/lib/timber/overrides/lograge.rb +14 -0
  57. data/lib/timber/overrides/rails_server.rb +10 -0
  58. data/lib/timber/util.rb +2 -0
  59. data/lib/timber/util/active_support_log_subscriber.rb +13 -9
  60. data/lib/timber/util/http_event.rb +54 -0
  61. data/lib/timber/util/request.rb +44 -0
  62. data/lib/timber/version.rb +1 -1
  63. data/spec/README.md +5 -9
  64. data/spec/spec_helper.rb +1 -4
  65. data/spec/support/action_controller.rb +7 -3
  66. data/spec/support/active_record.rb +23 -19
  67. data/spec/support/rails.rb +56 -32
  68. data/spec/support/timber.rb +2 -3
  69. data/spec/support/webmock.rb +1 -0
  70. data/spec/timber/integrations/action_controller/log_subscriber_spec.rb +55 -0
  71. data/spec/timber/integrations/action_dispatch/debug_exceptions_spec.rb +53 -0
  72. data/spec/timber/integrations/action_view/log_subscriber_spec.rb +115 -0
  73. data/spec/timber/integrations/active_record/log_subscriber_spec.rb +46 -0
  74. data/spec/timber/integrations/rack/http_context_spec.rb +60 -0
  75. data/spec/timber/integrations/rails/rack_logger_spec.rb +58 -0
  76. data/spec/timber/logger_spec.rb +45 -9
  77. data/timber.gemspec +29 -3
  78. metadata +143 -46
  79. data/Appraisals +0 -41
  80. data/circle.yml +0 -33
  81. data/lib/timber/overrides/logger_add.rb +0 -38
  82. data/lib/timber/probe.rb +0 -23
  83. data/lib/timber/probes.rb +0 -23
  84. data/lib/timber/probes/action_controller_log_subscriber.rb +0 -20
  85. data/lib/timber/probes/action_controller_log_subscriber/log_subscriber.rb +0 -64
  86. data/lib/timber/probes/action_controller_user_context.rb +0 -52
  87. data/lib/timber/probes/action_dispatch_debug_exceptions.rb +0 -80
  88. data/lib/timber/probes/action_view_log_subscriber.rb +0 -20
  89. data/lib/timber/probes/action_view_log_subscriber/log_subscriber.rb +0 -69
  90. data/lib/timber/probes/active_record_log_subscriber.rb +0 -20
  91. data/lib/timber/probes/active_record_log_subscriber/log_subscriber.rb +0 -31
  92. data/lib/timber/probes/active_support_tagged_logging.rb +0 -63
  93. data/lib/timber/probes/rails_rack_logger.rb +0 -77
  94. data/lib/timber/rack_middlewares.rb +0 -12
  95. data/lib/timber/rack_middlewares/http_context.rb +0 -30
  96. data/spec/support/action_view.rb +0 -4
  97. data/spec/support/coveralls.rb +0 -2
  98. data/spec/support/simplecov.rb +0 -9
  99. data/spec/timber/overrides/logger_add_spec.rb +0 -26
  100. data/spec/timber/probes/action_controller_log_subscriber_spec.rb +0 -65
  101. data/spec/timber/probes/action_controller_user_context_spec.rb +0 -53
  102. data/spec/timber/probes/action_dispatch_debug_exceptions_spec.rb +0 -48
  103. data/spec/timber/probes/action_view_log_subscriber_spec.rb +0 -107
  104. data/spec/timber/probes/active_record_log_subscriber_spec.rb +0 -47
  105. data/spec/timber/probes/rails_rack_logger_spec.rb +0 -46
  106. data/spec/timber/rack_middlewares/http_context_spec.rb +0 -47
@@ -1,23 +0,0 @@
1
- module Timber
2
- # Base class for `Timber::Probes::*`.
3
- # @private
4
- class Probe
5
- class RequirementNotMetError < StandardError; end
6
-
7
- class << self
8
- def insert!(*args)
9
- new(*args).insert!
10
- Config.instance.logger.debug("Inserted probe #{name}")
11
- true
12
- # RequirementUnsatisfiedError is the only silent failure we support
13
- rescue RequirementNotMetError => e
14
- Config.instance.logger.debug("Failed inserting probe #{name}: #{e.message}")
15
- false
16
- end
17
- end
18
-
19
- def insert!
20
- raise NotImplementedError.new
21
- end
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- require "timber/probes/action_controller_log_subscriber"
2
- require "timber/probes/action_controller_user_context"
3
- require "timber/probes/action_dispatch_debug_exceptions"
4
- require "timber/probes/action_view_log_subscriber"
5
- require "timber/probes/active_record_log_subscriber"
6
- require "timber/probes/active_support_tagged_logging"
7
- require "timber/probes/rails_rack_logger"
8
-
9
- module Timber
10
- # Namespace for all probes.
11
- # @private
12
- module Probes
13
- def self.insert!
14
- ActionControllerLogSubscriber.insert!
15
- ActionControllerUserContext.insert!
16
- ActionDispatchDebugExceptions.insert!
17
- ActionViewLogSubscriber.insert!
18
- ActiveRecordLogSubscriber.insert!
19
- ActiveSupportTaggedLogging.insert!
20
- RailsRackLogger.insert!
21
- end
22
- end
23
- end
@@ -1,20 +0,0 @@
1
- module Timber
2
- module Probes
3
- # Responsible for automatically tracking controller call and http response events
4
- # for applications that use `ActionController`.
5
- class ActionControllerLogSubscriber < Probe
6
- def initialize
7
- require "action_controller/log_subscriber"
8
- require "timber/probes/action_controller_log_subscriber/log_subscriber"
9
- rescue LoadError => e
10
- raise RequirementNotMetError.new(e.message)
11
- end
12
-
13
- def insert!
14
- return true if Util::ActiveSupportLogSubscriber.subscribed?(:action_controller, LogSubscriber)
15
- Util::ActiveSupportLogSubscriber.unsubscribe(:action_controller, ::ActionController::LogSubscriber)
16
- LogSubscriber.attach_to(:action_controller)
17
- end
18
- end
19
- end
20
- end
@@ -1,64 +0,0 @@
1
- module Timber
2
- module Probes
3
- class ActionControllerLogSubscriber < Probe
4
- # The log subscriber that replaces the default `ActionController::LogSubscriber`.
5
- # The intent of this subscriber is to, as transparently as possible, properly
6
- # track events that are being logged here. This LogSubscriber will never change
7
- # default behavior / log messages.
8
- class LogSubscriber < ::ActionController::LogSubscriber
9
- def start_processing(event)
10
- info do
11
- payload = event.payload
12
- params = payload[:params].except(*INTERNAL_PARAMS)
13
- format = extract_format(payload)
14
- format = format.to_s.upcase if format.is_a?(Symbol)
15
-
16
- Events::ControllerCall.new(
17
- controller: payload[:controller],
18
- action: payload[:action],
19
- format: format,
20
- params: params
21
- )
22
- end
23
- end
24
-
25
- def process_action(event)
26
- info do
27
- payload = event.payload
28
- additions = ActionController::Base.log_process_action(payload)
29
-
30
- status = payload[:status]
31
- if status.nil? && payload[:exception].present?
32
- exception_class_name = payload[:exception].first
33
- status = extract_status(exception_class_name)
34
- end
35
-
36
- Events::HTTPServerResponse.new(
37
- status: status,
38
- time_ms: event.duration,
39
- additions: additions
40
- )
41
- end
42
- end
43
-
44
- private
45
- def extract_format(payload)
46
- if payload.key?(:format)
47
- payload[:format] # rails > 4.X
48
- elsif payload.key?(:formats)
49
- payload[:formats].first # rails 3.X
50
- end
51
- end
52
-
53
- def extract_status(exception_class_name)
54
- if defined?(ActionDispatch::ExceptionWrapper)
55
- ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
56
- else
57
- # Rails 3.X
58
- Rack::Utils.status_code(ActionDispatch::ShowExceptions.rescue_responses[exception_class_name]) rescue nil
59
- end
60
- end
61
- end
62
- end
63
- end
64
- end
@@ -1,52 +0,0 @@
1
- module Timber
2
- module Probes
3
- # Responsible for automatically tracking controller call and http response events
4
- # for applications that use `ActionController`.
5
- class ActionControllerUserContext < Probe
6
- module AroundFilter
7
- def self.included(klass)
8
- klass.class_eval do
9
- if klass.respond_to?(:around_action)
10
- around_action :_timber_capture_user_context
11
- else
12
- around_filter :_timber_capture_user_context
13
- end
14
-
15
- private
16
- def _timber_capture_user_context
17
- if respond_to?(:current_user, true)
18
- id = Timber::Util::Object.try(current_user, :id)
19
- name = Timber::Util::Object.try(current_user, :name)
20
- if !name
21
- first_name = Timber::Util::Object.try(current_user, :first_name)
22
- last_name = Timber::Util::Object.try(current_user, :last_name)
23
- if first_name || last_name
24
- name = [first_name, last_name].compact.join(" ")
25
- end
26
- end
27
- email = Timber::Util::Object.try(current_user, :email)
28
- user_context = Timber::Contexts::User.new(:id => id, :name => name, :email => email)
29
- Timber::CurrentContext.with(user_context) do
30
- yield
31
- end
32
- else
33
- yield
34
- end
35
- end
36
- end
37
- end
38
- end
39
-
40
- def initialize
41
- require "action_controller"
42
- rescue LoadError => e
43
- raise RequirementNotMetError.new(e.message)
44
- end
45
-
46
- def insert!
47
- return true if ActionController::Base.include?(AroundFilter)
48
- ActionController::Base.send(:include, AroundFilter)
49
- end
50
- end
51
- end
52
- end
@@ -1,80 +0,0 @@
1
- module Timber
2
- module Probes
3
- # Reponsible for automatically tracking exception events in Rails applications. While
4
- # still preserving the default log style.
5
- class ActionDispatchDebugExceptions < Probe
6
- # For Rails >= 3.1
7
- # @private
8
- module DebugExceptionsInstanceMethods
9
- def self.included(klass)
10
- klass.class_eval do
11
- private
12
- def log_error(request, wrapper)
13
- logger = logger(request)
14
- return unless logger
15
-
16
- exception = wrapper.exception
17
-
18
- trace = wrapper.application_trace
19
- trace = wrapper.framework_trace if trace.empty?
20
-
21
- event = Events::Exception.new(
22
- name: exception.class.name,
23
- exception_message: exception.message,
24
- backtrace: trace
25
- )
26
-
27
- logger.fatal event
28
- end
29
- end
30
- end
31
- end
32
-
33
- # For Rails < 3.1
34
- # @private
35
- module ShowExceptionsInstanceMethods #:nodoc:
36
- def self.included(klass)
37
- klass.class_eval do
38
- private
39
- # We have to monkey patch because ruby < 2.0 does not support prepend.
40
- alias_method :_timber_old_log_error, :log_error
41
-
42
- def log_error(exception)
43
- return unless logger
44
-
45
- event = Events::Exception.new(
46
- name: exception.class.name,
47
- exception_message: exception.message,
48
- backtrace: application_trace(exception)
49
- )
50
-
51
- logger.fatal event
52
- end
53
- end
54
- end
55
- end
56
-
57
- def initialize
58
- begin
59
- # Rails >= 3.1
60
- require "action_dispatch/middleware/debug_exceptions"
61
- rescue LoadError
62
- # Rails < 3.1
63
- require "action_dispatch/middleware/show_exceptions"
64
- end
65
- rescue LoadError => e
66
- raise RequirementNotMetError.new(e.message)
67
- end
68
-
69
- def insert!
70
- if defined?(::ActionDispatch::DebugExceptions)
71
- return true if ::ActionDispatch::DebugExceptions.include?(DebugExceptionsInstanceMethods)
72
- ::ActionDispatch::DebugExceptions.send(:include, DebugExceptionsInstanceMethods)
73
- else
74
- return true if ::ActionDispatch::ShowExceptions.include?(ShowExceptionsInstanceMethods)
75
- ::ActionDispatch::ShowExceptions.send(:include, ShowExceptionsInstanceMethods)
76
- end
77
- end
78
- end
79
- end
80
- end
@@ -1,20 +0,0 @@
1
- module Timber
2
- module Probes
3
- # Reponsible for automatically tracking template rendering events in `ActionView` while
4
- # still preserving the default log style.
5
- class ActionViewLogSubscriber < Probe
6
- def initialize
7
- require "action_view/log_subscriber"
8
- require "timber/probes/action_view_log_subscriber/log_subscriber"
9
- rescue LoadError => e
10
- raise RequirementNotMetError.new(e.message)
11
- end
12
-
13
- def insert!
14
- return true if Util::ActiveSupportLogSubscriber.subscribed?(:action_view, LogSubscriber)
15
- Util::ActiveSupportLogSubscriber.unsubscribe(:action_view, ::ActionView::LogSubscriber)
16
- LogSubscriber.attach_to(:action_view)
17
- end
18
- end
19
- end
20
- end
@@ -1,69 +0,0 @@
1
- module Timber
2
- module Probes
3
- class ActionViewLogSubscriber < Probe
4
- # The log subscriber that replaces the default `ActionView::LogSubscriber`.
5
- # The intent of this subscriber is to, as transparently as possible, properly
6
- # track events that are being logged here. This LogSubscriber will never change
7
- # default behavior / log messages.
8
- class LogSubscriber < ::ActionView::LogSubscriber
9
- def render_template(event)
10
- info do
11
- full_name = from_rails_root(event.payload[:identifier])
12
- message = " Rendered #{full_name}"
13
- message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
14
- message << " (#{event.duration.round(1)}ms)"
15
-
16
- Events::TemplateRender.new(
17
- name: full_name,
18
- time_ms: event.duration,
19
- message: message
20
- )
21
- end
22
- end
23
-
24
- def render_partial(event)
25
- info do
26
- full_name = from_rails_root(event.payload[:identifier])
27
- message = " Rendered #{full_name}"
28
- message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
29
- message << " (#{event.duration.round(1)}ms)"
30
- message << " #{cache_message(event.payload)}" if event.payload.key?(:cache_hit)
31
-
32
- Events::TemplateRender.new(
33
- name: full_name,
34
- time_ms: event.duration,
35
- message: message
36
- )
37
- end
38
- end
39
-
40
- def render_collection(event)
41
- if respond_to?(:render_count, true)
42
- info do
43
- identifier = event.payload[:identifier] || "templates"
44
- full_name = from_rails_root(identifier)
45
- message = " Rendered collection of #{full_name}" \
46
- " #{render_count(event.payload)} (#{event.duration.round(1)}ms)"
47
-
48
- Events::TemplateRender.new(
49
- name: full_name,
50
- time_ms: event.duration,
51
- message: message
52
- )
53
- end
54
- else
55
- # Older versions of rails delegate this method to #render_template
56
- render_template(event)
57
- end
58
- end
59
-
60
- private
61
- def log_rendering_start(payload)
62
- # Consolidates 2 template rendering events into 1. We don't need 2 events for
63
- # rendering a template. If you disagree, please feel free to open a PR and we
64
- # can make this an option.
65
- end
66
- end
67
- end
68
- end
69
- end
@@ -1,20 +0,0 @@
1
- module Timber
2
- module Probes
3
- # Reponsible for automatimcally tracking SQL query events in `ActiveRecord`, while still
4
- # preserving the default log style.
5
- class ActiveRecordLogSubscriber < Probe
6
- def initialize
7
- require "active_record/log_subscriber"
8
- require "timber/probes/active_record_log_subscriber/log_subscriber"
9
- rescue LoadError => e
10
- raise RequirementNotMetError.new(e.message)
11
- end
12
-
13
- def insert!
14
- return true if Util::ActiveSupportLogSubscriber.subscribed?(:active_record, LogSubscriber)
15
- Util::ActiveSupportLogSubscriber.unsubscribe(:active_record, ::ActiveRecord::LogSubscriber)
16
- LogSubscriber.attach_to(:active_record)
17
- end
18
- end
19
- end
20
- end
@@ -1,31 +0,0 @@
1
- module Timber
2
- module Probes
3
- class ActiveRecordLogSubscriber < Probe
4
- # The log subscriber that replaces the default `ActiveRecord::LogSubscriber`.
5
- # The intent of this subscriber is to, as transparently as possible, properly
6
- # track events that are being logged here. This LogSubscriber will never change
7
- # default behavior / log messages.
8
- class LogSubscriber < ::ActiveRecord::LogSubscriber #:nodoc:
9
- def sql(event)
10
- super(event)
11
-
12
- if @message
13
- payload = event.payload
14
- event = Events::SQLQuery.new(
15
- sql: payload[:sql],
16
- time_ms: event.duration,
17
- message: @message
18
- )
19
-
20
- logger.debug event
21
- end
22
- end
23
-
24
- private
25
- def debug(message)
26
- @message = message
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,63 +0,0 @@
1
- module Timber
2
- module Probes
3
- # Reponsible for automatimcally tracking SQL query events in `ActiveRecord`, while still
4
- # preserving the default log style.
5
- class ActiveSupportTaggedLogging < Probe
6
- module FormatterMethods
7
- def self.included(mod)
8
- mod.module_eval do
9
- alias_method :_timber_original_push_tags, :push_tags
10
- alias_method :_timber_original_pop_tags, :pop_tags
11
-
12
- def call(severity, timestamp, progname, msg)
13
- if is_a?(Timber::Logger::Formatter)
14
- # Don't convert the message into a string
15
- super(severity, timestamp, progname, msg)
16
- else
17
- super(severity, timestamp, progname, "#{tags_text}#{msg}")
18
- end
19
- end
20
- end
21
- end
22
- end
23
-
24
- module LoggerMethods
25
- def self.included(klass)
26
- klass.class_eval do
27
- def add(severity, message = nil, progname = nil, &block)
28
- if message.nil?
29
- if block_given?
30
- message = block.call
31
- else
32
- message = progname
33
- progname = nil #No instance variable for this like Logger
34
- end
35
- end
36
- if @logger.is_a?(Timber::Logger)
37
- @logger.add(severity, message, progname)
38
- else
39
- @logger.add(severity, "#{tags_text}#{message}", progname)
40
- end
41
- end
42
- end
43
- end
44
- end
45
-
46
- def initialize
47
- require "active_support/tagged_logging"
48
- rescue LoadError => e
49
- raise RequirementNotMetError.new(e.message)
50
- end
51
-
52
- def insert!
53
- if defined?(ActiveSupport::TaggedLogging::Formatter)
54
- return true if ActiveSupport::TaggedLogging::Formatter.include?(FormatterMethods)
55
- ActiveSupport::TaggedLogging::Formatter.send(:include, FormatterMethods)
56
- else
57
- return true if ActiveSupport::TaggedLogging.include?(LoggerMethods)
58
- ActiveSupport::TaggedLogging.send(:include, LoggerMethods)
59
- end
60
- end
61
- end
62
- end
63
- end