timber 2.6.2 → 3.0.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.
Files changed (142) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +8 -38
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +30 -284
  5. data/Rakefile +78 -0
  6. data/lib/timber.rb +6 -6
  7. data/lib/timber/config.rb +1 -83
  8. data/lib/timber/config/integrations.rb +1 -47
  9. data/lib/timber/context.rb +3 -24
  10. data/lib/timber/contexts.rb +2 -30
  11. data/lib/timber/contexts/http.rb +16 -36
  12. data/lib/timber/contexts/release.rb +12 -23
  13. data/lib/timber/contexts/runtime.rb +9 -36
  14. data/lib/timber/contexts/session.rb +8 -21
  15. data/lib/timber/contexts/system.rb +9 -16
  16. data/lib/timber/contexts/user.rb +13 -33
  17. data/lib/timber/current_context.rb +16 -78
  18. data/lib/timber/event.rb +12 -9
  19. data/lib/timber/events.rb +1 -33
  20. data/lib/timber/events/controller_call.rb +20 -31
  21. data/lib/timber/events/error.rb +18 -26
  22. data/lib/timber/events/exception.rb +1 -0
  23. data/lib/timber/events/sql_query.rb +14 -24
  24. data/lib/timber/events/template_render.rb +13 -24
  25. data/lib/timber/integration.rb +1 -1
  26. data/lib/timber/integrator.rb +1 -1
  27. data/lib/timber/log_devices/http.rb +98 -19
  28. data/lib/timber/log_entry.rb +6 -24
  29. data/lib/timber/logger.rb +5 -14
  30. data/lib/timber/util.rb +1 -6
  31. data/lib/timber/util/non_nil_hash_builder.rb +3 -1
  32. data/lib/timber/version.rb +1 -1
  33. data/spec/README.md +2 -8
  34. data/spec/spec_helper.rb +0 -7
  35. data/spec/support/timber.rb +1 -3
  36. data/spec/timber/current_context_spec.rb +12 -50
  37. data/spec/timber/events/controller_call_spec.rb +4 -4
  38. data/spec/timber/events/error_spec.rb +4 -9
  39. data/spec/timber/log_devices/http_spec.rb +26 -2
  40. data/spec/timber/log_entry_spec.rb +12 -6
  41. data/spec/timber/logger_spec.rb +27 -68
  42. data/timber.gemspec +1 -1
  43. metadata +5 -139
  44. data/gemfiles/rails-3.0.gemfile +0 -5
  45. data/gemfiles/rails-3.1.gemfile +0 -5
  46. data/gemfiles/rails-3.2.gemfile +0 -5
  47. data/gemfiles/rails-4.0.gemfile +0 -9
  48. data/gemfiles/rails-4.1.gemfile +0 -9
  49. data/gemfiles/rails-4.2.gemfile +0 -9
  50. data/gemfiles/rails-5.0.gemfile +0 -9
  51. data/gemfiles/rails-5.1.gemfile +0 -9
  52. data/gemfiles/rails-edge.gemfile +0 -7
  53. data/lib/timber/cli.rb +0 -60
  54. data/lib/timber/cli/api.rb +0 -183
  55. data/lib/timber/cli/api/application.rb +0 -34
  56. data/lib/timber/cli/config_file.rb +0 -71
  57. data/lib/timber/cli/file_helper.rb +0 -53
  58. data/lib/timber/cli/installer.rb +0 -70
  59. data/lib/timber/cli/installers.rb +0 -102
  60. data/lib/timber/cli/installers/config_file.rb +0 -51
  61. data/lib/timber/cli/installers/other.rb +0 -59
  62. data/lib/timber/cli/installers/rails.rb +0 -225
  63. data/lib/timber/cli/installers/root.rb +0 -116
  64. data/lib/timber/cli/io.rb +0 -100
  65. data/lib/timber/cli/io/ansi.rb +0 -22
  66. data/lib/timber/cli/io/messages.rb +0 -198
  67. data/lib/timber/cli/os_helper.rb +0 -74
  68. data/lib/timber/config/integrations/rack.rb +0 -74
  69. data/lib/timber/contexts/custom.rb +0 -44
  70. data/lib/timber/contexts/organization.rb +0 -48
  71. data/lib/timber/events/custom.rb +0 -53
  72. data/lib/timber/events/http_request.rb +0 -71
  73. data/lib/timber/events/http_response.rb +0 -81
  74. data/lib/timber/frameworks.rb +0 -19
  75. data/lib/timber/frameworks/rails.rb +0 -27
  76. data/lib/timber/integrations.rb +0 -29
  77. data/lib/timber/integrations/action_controller.rb +0 -18
  78. data/lib/timber/integrations/action_controller/log_subscriber.rb +0 -27
  79. data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +0 -46
  80. data/lib/timber/integrations/action_dispatch.rb +0 -23
  81. data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +0 -53
  82. data/lib/timber/integrations/action_view.rb +0 -18
  83. data/lib/timber/integrations/action_view/log_subscriber.rb +0 -27
  84. data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +0 -83
  85. data/lib/timber/integrations/active_record.rb +0 -18
  86. data/lib/timber/integrations/active_record/log_subscriber.rb +0 -26
  87. data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +0 -53
  88. data/lib/timber/integrations/rack.rb +0 -27
  89. data/lib/timber/integrations/rack/error_event.rb +0 -64
  90. data/lib/timber/integrations/rack/http_context.rb +0 -27
  91. data/lib/timber/integrations/rack/http_events.rb +0 -210
  92. data/lib/timber/integrations/rack/middleware.rb +0 -28
  93. data/lib/timber/integrations/rack/session_context.rb +0 -65
  94. data/lib/timber/integrations/rack/user_context.rb +0 -135
  95. data/lib/timber/integrations/rails.rb +0 -22
  96. data/lib/timber/integrations/rails/rack_logger.rb +0 -60
  97. data/lib/timber/overrides.rb +0 -12
  98. data/lib/timber/overrides/active_support_3_tagged_logging.rb +0 -111
  99. data/lib/timber/overrides/active_support_buffered_logger.rb +0 -22
  100. data/lib/timber/overrides/active_support_tagged_logging.rb +0 -66
  101. data/lib/timber/overrides/lograge.rb +0 -18
  102. data/lib/timber/overrides/rails_stdout_logging.rb +0 -21
  103. data/lib/timber/util/active_support_log_subscriber.rb +0 -37
  104. data/lib/timber/util/attribute_normalizer.rb +0 -89
  105. data/lib/timber/util/hash.rb +0 -90
  106. data/lib/timber/util/request.rb +0 -72
  107. data/lib/timber/util/struct.rb +0 -16
  108. data/spec/rails/tagged_logging_spec.rb +0 -44
  109. data/spec/support/action_controller.rb +0 -8
  110. data/spec/support/active_record.rb +0 -32
  111. data/spec/support/rails.rb +0 -67
  112. data/spec/support/rails/templates/_partial.html +0 -1
  113. data/spec/support/rails/templates/template.html +0 -1
  114. data/spec/timber/cli/config_file_spec.rb +0 -26
  115. data/spec/timber/cli/installers/config_file_spec.rb +0 -36
  116. data/spec/timber/cli/installers/other_spec.rb +0 -49
  117. data/spec/timber/cli/installers/rails_spec.rb +0 -364
  118. data/spec/timber/cli/installers/root_spec.rb +0 -73
  119. data/spec/timber/config_spec.rb +0 -28
  120. data/spec/timber/contexts/custom_spec.rb +0 -11
  121. data/spec/timber/contexts/organization_spec.rb +0 -11
  122. data/spec/timber/contexts/runtime_spec.rb +0 -11
  123. data/spec/timber/contexts/system_spec.rb +0 -11
  124. data/spec/timber/contexts/user_spec.rb +0 -11
  125. data/spec/timber/contexts_spec.rb +0 -49
  126. data/spec/timber/event_spec.rb +0 -10
  127. data/spec/timber/events/custom_spec.rb +0 -36
  128. data/spec/timber/events/http_request_spec.rb +0 -32
  129. data/spec/timber/events/http_response_spec.rb +0 -12
  130. data/spec/timber/events_spec.rb +0 -55
  131. data/spec/timber/integrations/action_controller/log_subscriber_spec.rb +0 -55
  132. data/spec/timber/integrations/action_dispatch/debug_exceptions_spec.rb +0 -53
  133. data/spec/timber/integrations/action_view/log_subscriber_spec.rb +0 -115
  134. data/spec/timber/integrations/active_record/log_subscriber_spec.rb +0 -46
  135. data/spec/timber/integrations/rack/error_event_spec.rb +0 -63
  136. data/spec/timber/integrations/rack/http_context_spec.rb +0 -60
  137. data/spec/timber/integrations/rack/http_events_spec.rb +0 -101
  138. data/spec/timber/integrations/rack/session_context_spec.rb +0 -62
  139. data/spec/timber/integrations/rails/rack_logger_spec.rb +0 -58
  140. data/spec/timber/util/attribute_normalizer_spec.rb +0 -90
  141. data/spec/timber/util/hash_spec.rb +0 -30
  142. data/spec/timber/util/request_spec.rb +0 -10
@@ -1,28 +0,0 @@
1
- module Timber
2
- module Integrations
3
- module Rack
4
- # Base class that all Timber Rack middlewares extend. See the class level methods for
5
- # configuration options.
6
- class Middleware
7
- class << self
8
- # Easily enable / disable specific middlewares.
9
- #
10
- # @example
11
- # Timber::Integrations::Rack::UserContext.enabled = false
12
- def enabled=(value)
13
- @enabled = value
14
- end
15
-
16
- # Accessor method for {#enabled=}.
17
- def enabled?
18
- @enabled != false
19
- end
20
- end
21
-
22
- def initialize(app)
23
- @app = app
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,65 +0,0 @@
1
- begin
2
- require "rails"
3
- rescue Exception
4
- end
5
-
6
- require "timber/config"
7
- require "timber/contexts/session"
8
- require "timber/integrations/rack/middleware"
9
-
10
- module Timber
11
- module Integrations
12
- module Rack
13
- # A Rack middleware that is responsible for adding the Session context
14
- # {Timber::Contexts::Session}.
15
- class SessionContext < Middleware
16
- def call(env)
17
- id = get_session_id(env)
18
- if id
19
- context = Contexts::Session.new(id: id)
20
- CurrentContext.with(context) do
21
- @app.call(env)
22
- end
23
- else
24
- @app.call(env)
25
- end
26
- end
27
-
28
- private
29
- def get_session_id(env)
30
- if defined?(::Rails)
31
- session_key = ::Rails.application.config.session_options[:key]
32
- request = ::ActionDispatch::Request.new(env)
33
- Timber::Config.instance.debug { "Rails detected, extracting session_id from cookie" }
34
- extract_from_cookie(request, session_key)
35
-
36
- elsif session = env['rack.session']
37
- if session.respond_to?(:id)
38
- Timber::Config.instance.debug { "Rack env session detected, using id attribute" }
39
- session.id
40
- elsif session.respond_to?(:[])
41
- Timber::Config.instance.debug { "Rack env session detected, using the session_id key" }
42
- session["session_id"]
43
- else
44
- Timber::Config.instance.debug { "Rack env session detected but could not extract id" }
45
- nil
46
- end
47
- else
48
- Timber::Config.instance.debug { "No session data could be detected, skipping" }
49
-
50
- nil
51
- end
52
- rescue Exception => e
53
- nil
54
- end
55
-
56
- def extract_from_cookie(request, session_key)
57
- data = request
58
- .cookie_jar
59
- .signed_or_encrypted[session_key] || {}
60
- data["session_id"]
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,135 +0,0 @@
1
- require "timber/config"
2
- require "timber/contexts/user"
3
- require "timber/integrations/rack/middleware"
4
-
5
- module Timber
6
- module Integrations
7
- module Rack
8
- # This is a Rack middleware responsible for setting the user context.
9
- # See {Timber::Contexts::User} for more information on the user context.
10
- #
11
- # ## Why a Rack middleware?
12
- #
13
- # We use a Rack middleware because we want to set the user context as early as
14
- # possible, and before the initial incoming request log line:
15
- #
16
- # Started GET /welcome
17
- #
18
- # The above log line is logged in a request middleware, before it reaches
19
- # the controller.
20
- #
21
- # If, for example, we set the user context in a controller, the log line above
22
- # will not have the user context attached. This is because it is logged before
23
- # the controller is executed. This is not ideal, and it's why we take a middleware
24
- # approach here. If for some reason you cannot identify the user at the middleware
25
- # level then setting it in the controller is perfectly fine, just be aware of the
26
- # above downside.
27
- #
28
- # ## Authentication frameworks automatically detected:
29
- #
30
- # If you use any of the following authentication frameworks, Timber will
31
- # automatically set the user context for you.
32
- #
33
- # * Devise, or any Warden based authentication strategy
34
- # * Clearance
35
- #
36
- # Or, you can use your own custom authentication, see the {.custom_user_context}
37
- # class method for more details.
38
- #
39
- # @note This middleware is automatically inserted for frameworks we support.
40
- # Such as Rails. See {Timber::Frameworks} for a comprehensive list.
41
- class UserContext < Middleware
42
- class << self
43
- # The custom user context allows you to hook in and set your own custom
44
- # user context. This is used in situations where either:
45
- #
46
- # 1. Timber does not automatically support your authentication strategy (see module level docs)
47
- # 2. You need to customize your authentication beyond Timber's defaults.
48
- #
49
- # @example Setting your own custom user context
50
- # Timber::Integrations::Rack::UserContext.custom_user_hash = lambda do |rack_env|
51
- # rack_env['my_custom_key'].user
52
- # end
53
- def custom_user_hash=(proc)
54
- if proc && !proc.is_a?(Proc)
55
- raise ArgumentError.new("The value passed to #custom_user_hash must be a Proc")
56
- end
57
-
58
- @custom_user_hash = proc
59
- end
60
-
61
- # Accessor method for {#custom_user_hash=}.
62
- def custom_user_hash
63
- @custom_user_hash
64
- end
65
- end
66
-
67
- def call(env)
68
- user_hash = get_user_hash(env)
69
- if user_hash
70
- context = Contexts::User.new(user_hash)
71
- CurrentContext.with(context) do
72
- @app.call(env)
73
- end
74
- else
75
- @app.call(env)
76
- end
77
- end
78
-
79
- private
80
- def get_user_hash(env)
81
- # The order is relevant here. The 'warden' key can be set, but
82
- # not return a user, in which case the user data might be in another key.
83
- if self.class.custom_user_hash.is_a?(Proc)
84
- Timber::Config.instance.debug { "Obtaining user context from the custom user hash" }
85
- self.class.custom_user_hash.call(env)
86
- elsif env[:clearance] && env[:clearance].signed_in?
87
- Timber::Config.instance.debug { "Obtaining user context from the clearance user" }
88
- user = env[:clearance].current_user
89
- get_user_object_hash(user)
90
- elsif env['warden'] && (user = env['warden'].user)
91
- Timber::Config.instance.debug { "Obtaining user context from the warden user" }
92
- get_user_object_hash(user)
93
- else
94
- Timber::Config.instance.debug { "Could not locate any user data" }
95
- nil
96
- end
97
- end
98
-
99
- def get_user_object_hash(user)
100
- id = try_user_id(user)
101
- name = try_user_name(user)
102
- email = try_user_email(user)
103
-
104
- if id || name || email
105
- {id: id, name: name, email: email}
106
- else
107
- nil
108
- end
109
- end
110
-
111
- def try_user_id(user)
112
- user.respond_to?(:id) ? user.id : nil
113
- end
114
-
115
- def try_user_name(user)
116
- if user.respond_to?(:name) && user.name.is_a?(String)
117
- user.name
118
- elsif user.respond_to?(:first_name) && user.first_name.is_a?(String) && user.respond_to?(:last_name) && user.last_name.is_a?(String)
119
- "#{user.first_name} #{user.last_name}"
120
- else
121
- nil
122
- end
123
- end
124
-
125
- def try_user_email(user)
126
- if user.respond_to?(:email) && user.email.is_a?(String)
127
- user.email
128
- else
129
- nil
130
- end
131
- end
132
- end
133
- end
134
- end
135
- end
@@ -1,22 +0,0 @@
1
- require "timber/integration"
2
- require "timber/integrations/rack/http_events"
3
- require "timber/integrations/rails/rack_logger"
4
-
5
- module Timber
6
- module Integrations
7
- # Module for holding *all* Rails integrations. This module does *not*
8
- # extend {Integration} because it's dependent on {Rack::HTTPEvents}. This
9
- # module simply disables the default HTTP request logging.
10
- module Rails
11
- def self.enabled?
12
- Rack::HTTPEvents.enabled?
13
- end
14
-
15
- def self.integrate!
16
- return false if !enabled?
17
-
18
- RackLogger.integrate!
19
- end
20
- end
21
- end
22
- end
@@ -1,60 +0,0 @@
1
- require "timber/integrator"
2
-
3
- module Timber
4
- module Integrations
5
- module Rails
6
- # Disables the default rail's rack logging. Note, we cannot simply uninstall this rack
7
- # middleware because rails couples this with ActiveSupport instrumentation. As such,
8
- # we simply disable the logger and let our Rack middleware handle the logging.
9
- #
10
- # See: https://github.com/rails/rails/blob/80e66cc4d90bf8c15d1a5f6e3152e90147f00772/railties/lib/rails/rack/logger.rb#L34
11
- #
12
- # @private
13
- class RackLogger < Integrator
14
-
15
- # @private
16
- module InstanceMethods
17
- LOGGER = ::Logger.new(nil)
18
-
19
- def self.included(klass)
20
- klass.class_eval do
21
- private
22
- if ::Rails::VERSION::MAJOR == 3
23
- # Rails 3.2 calls Rails.logger directly in call_app, so we
24
- # will just replace it with a version that doesn't
25
- def call_app(_, env)
26
- # Put some space between requests in development logs.
27
- if ::Rails.env.development?
28
- ::Rails.logger.info ''
29
- ::Rails.logger.info ''
30
- end
31
- @app.call(env)
32
- ensure
33
- ActiveSupport::LogSubscriber.flush_all!
34
- end
35
- end
36
-
37
- # Rails > 3.2 uses a logger method. Muting logs is accomplished by
38
- # passing a dummy logger instance with a nil log device.
39
- def logger
40
- LOGGER
41
- end
42
- end
43
- end
44
- end
45
-
46
- def initialize
47
- require "rails/rack/logger"
48
- rescue LoadError => e
49
- raise RequirementNotMetError.new(e.message)
50
- end
51
-
52
- def integrate!
53
- return true if ::Rails::Rack::Logger.include?(InstanceMethods)
54
-
55
- ::Rails::Rack::Logger.send(:include, InstanceMethods)
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,12 +0,0 @@
1
- # The order is relevant
2
- require "timber/overrides/active_support_3_tagged_logging"
3
- require "timber/overrides/active_support_tagged_logging"
4
- require "timber/overrides/active_support_buffered_logger"
5
- require "timber/overrides/lograge"
6
- require "timber/overrides/rails_stdout_logging"
7
-
8
- module Timber
9
- # @private
10
- module Overrides
11
- end
12
- end
@@ -1,111 +0,0 @@
1
- # Please note, this patch is merely an upgrade, backporting improved tagged logging code
2
- # from newer versions of Rails:
3
- # https://github.com/rails/rails/blob/5-1-stable/activesupport/lib/active_support/tagged_logging.rb
4
- # The behavior of tagged logging will not change in any way.
5
- #
6
- # This patch is specifically for Rails 3. The legacy approach to wrapping the logger in
7
- # ActiveSupport::TaggedLogging is rather poor, hence the reason it was changed entirely
8
- # for Rails 4 and 5. The problem is that ActiveSupport::TaggedLogging is a wrapping
9
- # class that entirely redefines the public API for the logger. As a result, any deviations
10
- # from this API in the logger are not exposed (such as accepting event data as a second argument).
11
- # This is assuming, so we're fixing it here.
12
-
13
- begin
14
- require "active_support/tagged_logging"
15
-
16
- # Instead of patching the class we're pulling the code from Rails master. This brings in
17
- # a number of improvements while also addressing the issue above.
18
- if ActiveSupport::TaggedLogging.instance_of?(Class)
19
- ActiveSupport.send(:remove_const, :TaggedLogging)
20
-
21
- require "active_support/core_ext/module/delegation"
22
- require "active_support/core_ext/object/blank"
23
- require "logger"
24
-
25
- module ActiveSupport
26
- # Wraps any standard Logger object to provide tagging capabilities.
27
- #
28
- # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
29
- # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
30
- # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
31
- # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
32
- #
33
- # This is used by the default Rails.logger as configured by Railties to make
34
- # it easy to stamp log lines with subdomains, request ids, and anything else
35
- # to aid debugging of multi-user production applications.
36
- module TaggedLogging
37
- module Formatter # :nodoc:
38
- # This method is invoked when a log event occurs.
39
- def call(severity, timestamp, progname, msg)
40
- super(severity, timestamp, progname, "#{tags_text}#{msg}")
41
- end
42
-
43
- def tagged(*tags)
44
- new_tags = push_tags(*tags)
45
- yield self
46
- ensure
47
- pop_tags(new_tags.size)
48
- end
49
-
50
- def push_tags(*tags)
51
- tags.flatten.reject(&:blank?).tap do |new_tags|
52
- current_tags.concat new_tags
53
- end
54
- end
55
-
56
- def pop_tags(size = 1)
57
- current_tags.pop size
58
- end
59
-
60
- def clear_tags!
61
- current_tags.clear
62
- end
63
-
64
- def current_tags
65
- # We use our object ID here to avoid conflicting with other instances
66
- thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}".freeze
67
- Thread.current[thread_key] ||= []
68
- end
69
-
70
- def tags_text
71
- tags = current_tags
72
- if tags.any?
73
- tags.collect { |tag| "[#{tag}] " }.join
74
- end
75
- end
76
- end
77
-
78
- # Simple formatter which only displays the message.
79
- class SimpleFormatter < ::Logger::Formatter
80
- # This method is invoked when a log event occurs
81
- def call(severity, timestamp, progname, msg)
82
- "#{String === msg ? msg : msg.inspect}\n"
83
- end
84
- end
85
-
86
- def self.new(logger)
87
- if logger.respond_to?(:formatter=) && logger.respond_to?(:formatter)
88
- # Ensure we set a default formatter so we aren't extending nil!
89
- logger.formatter ||= SimpleFormatter.new
90
- logger.formatter.extend Formatter
91
- end
92
-
93
- logger.extend(self)
94
- end
95
-
96
- delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
97
-
98
- def tagged(*tags)
99
- formatter.tagged(*tags) { yield self }
100
- end
101
-
102
- def flush
103
- clear_tags!
104
- super if defined?(super)
105
- end
106
- end
107
- end
108
- end
109
-
110
- rescue Exception
111
- end
@@ -1,22 +0,0 @@
1
- # This adds a #formatter and #formatter= method to the legacy ActiveSupport::BufferedLogger
2
- # class. This bug was never resolved due to it being phased out past Rails >= 4.
3
-
4
- begin
5
- require "active_support/buffered_logger"
6
-
7
- class ActiveSupport::BufferedLogger
8
- def formatter
9
- if @log.respond_to?(:formatter)
10
- @log.formatter
11
- end
12
- end
13
-
14
- def formatter=(value)
15
- if @log.respond_to?(:formatter=)
16
- @log.formatter = value
17
- end
18
- end
19
- end
20
-
21
- rescue Exception
22
- end