timber 2.0.24 → 2.1.0.rc1

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG +3 -0
  4. data/README.md +314 -59
  5. data/bin/timber +11 -2
  6. data/lib/timber.rb +2 -7
  7. data/lib/timber/cli.rb +16 -28
  8. data/lib/timber/cli/api.rb +80 -14
  9. data/lib/timber/cli/api/application.rb +30 -0
  10. data/lib/timber/cli/config_file.rb +66 -0
  11. data/lib/timber/cli/file_helper.rb +43 -0
  12. data/lib/timber/cli/installer.rb +58 -0
  13. data/lib/timber/cli/installers.rb +37 -0
  14. data/lib/timber/cli/installers/other.rb +47 -0
  15. data/lib/timber/cli/installers/rails.rb +255 -0
  16. data/lib/timber/cli/installers/root.rb +189 -0
  17. data/lib/timber/cli/io.rb +97 -0
  18. data/lib/timber/cli/io/ansi.rb +22 -0
  19. data/lib/timber/cli/io/messages.rb +213 -0
  20. data/lib/timber/cli/os_helper.rb +53 -0
  21. data/lib/timber/config.rb +97 -43
  22. data/lib/timber/config/integrations.rb +63 -0
  23. data/lib/timber/config/integrations/rack.rb +74 -0
  24. data/lib/timber/context.rb +13 -10
  25. data/lib/timber/contexts.rb +1 -0
  26. data/lib/timber/contexts/custom.rb +16 -3
  27. data/lib/timber/contexts/http.rb +10 -3
  28. data/lib/timber/contexts/organization.rb +4 -0
  29. data/lib/timber/contexts/release.rb +46 -0
  30. data/lib/timber/contexts/runtime.rb +7 -1
  31. data/lib/timber/contexts/session.rb +8 -1
  32. data/lib/timber/contexts/system.rb +5 -1
  33. data/lib/timber/contexts/user.rb +9 -2
  34. data/lib/timber/current_context.rb +43 -11
  35. data/lib/timber/events/controller_call.rb +4 -0
  36. data/lib/timber/events/custom.rb +13 -5
  37. data/lib/timber/events/exception.rb +4 -0
  38. data/lib/timber/events/http_client_request.rb +4 -0
  39. data/lib/timber/events/http_client_response.rb +4 -0
  40. data/lib/timber/events/http_server_request.rb +5 -0
  41. data/lib/timber/events/http_server_response.rb +15 -3
  42. data/lib/timber/events/sql_query.rb +3 -0
  43. data/lib/timber/events/template_render.rb +3 -0
  44. data/lib/timber/integration.rb +40 -0
  45. data/lib/timber/integrations.rb +21 -14
  46. data/lib/timber/integrations/action_controller.rb +18 -0
  47. data/lib/timber/integrations/action_controller/log_subscriber.rb +2 -0
  48. data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +6 -0
  49. data/lib/timber/integrations/action_dispatch.rb +23 -0
  50. data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +2 -0
  51. data/lib/timber/integrations/action_view.rb +18 -0
  52. data/lib/timber/integrations/action_view/log_subscriber.rb +2 -0
  53. data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +10 -0
  54. data/lib/timber/integrations/active_record.rb +18 -0
  55. data/lib/timber/integrations/active_record/log_subscriber.rb +2 -0
  56. data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +8 -0
  57. data/lib/timber/integrations/rack.rb +12 -2
  58. data/lib/timber/integrations/rack/exception_event.rb +38 -5
  59. data/lib/timber/integrations/rack/http_context.rb +4 -6
  60. data/lib/timber/integrations/rack/http_events.rb +177 -27
  61. data/lib/timber/integrations/rack/middleware.rb +28 -0
  62. data/lib/timber/integrations/rack/session_context.rb +5 -6
  63. data/lib/timber/integrations/rack/user_context.rb +90 -43
  64. data/lib/timber/integrations/rails.rb +22 -0
  65. data/lib/timber/integrations/rails/rack_logger.rb +2 -0
  66. data/lib/timber/integrator.rb +18 -3
  67. data/lib/timber/log_devices/http.rb +107 -99
  68. data/lib/timber/log_devices/http/dropping_sized_queue.rb +26 -0
  69. data/lib/timber/log_devices/http/flushable_sized_queue.rb +42 -0
  70. data/lib/timber/log_entry.rb +14 -2
  71. data/lib/timber/logger.rb +51 -36
  72. data/lib/timber/overrides.rb +2 -0
  73. data/lib/timber/overrides/active_support_3_tagged_logging.rb +103 -0
  74. data/lib/timber/overrides/active_support_tagged_logging.rb +53 -90
  75. data/lib/timber/timer.rb +21 -0
  76. data/lib/timber/util/hash.rb +1 -1
  77. data/lib/timber/util/http_event.rb +16 -3
  78. data/lib/timber/version.rb +1 -1
  79. data/spec/support/timber.rb +2 -3
  80. data/spec/timber/cli/installers/rails_spec.rb +160 -0
  81. data/spec/timber/cli/installers/root_spec.rb +100 -0
  82. data/spec/timber/config_spec.rb +28 -0
  83. data/spec/timber/current_context_spec.rb +61 -12
  84. data/spec/timber/events/custom_spec.rb +13 -2
  85. data/spec/timber/events/exception_spec.rb +15 -0
  86. data/spec/timber/events/http_server_request_spec.rb +3 -3
  87. data/spec/timber/integrations/rack/http_events_spec.rb +101 -0
  88. data/spec/timber/log_devices/http_spec.rb +20 -4
  89. data/spec/timber/log_entry_spec.rb +2 -1
  90. data/spec/timber/logger_spec.rb +8 -8
  91. metadata +40 -9
  92. data/benchmarks/rails.rb +0 -122
  93. data/lib/timber/cli/application.rb +0 -28
  94. data/lib/timber/cli/install.rb +0 -196
  95. data/lib/timber/cli/io_helper.rb +0 -65
  96. data/lib/timber/cli/messages.rb +0 -180
  97. data/lib/timber/integrations/active_support/tagged_logging.rb +0 -71
@@ -1,5 +1,8 @@
1
1
  require 'socket'
2
2
 
3
+ require "timber/contexts"
4
+ require "timber/events"
5
+
3
6
  module Timber
4
7
  # Represents a new log entry into the log. This is an intermediary class between
5
8
  # `Logger` and the log device that you set it up with.
@@ -32,6 +35,9 @@ module Timber
32
35
  @time_ms = options[:time_ms]
33
36
 
34
37
  context_snapshot = {} if context_snapshot.nil?
38
+
39
+ # Set the system context for each log entry since processes can be forked
40
+ # and the process ID could change.
35
41
  hostname = Socket.gethostname
36
42
  pid = Process.pid
37
43
  system_context = Contexts::System.new(hostname: hostname, pid: pid)
@@ -41,10 +47,16 @@ module Timber
41
47
  @event = event
42
48
  end
43
49
 
50
+ # Builds a hash representation of containing simply objects, suitable for serialization.
44
51
  def as_json(options = {})
45
52
  options ||= {}
46
- hash = {:level => level, :dt => formatted_dt, :message => message, :tags => tags,
47
- :time_ms => time_ms}
53
+ hash = {
54
+ :level => level,
55
+ :dt => formatted_dt,
56
+ :message => message,
57
+ :tags => tags,
58
+ :time_ms => time_ms
59
+ }
48
60
 
49
61
  if !event.nil?
50
62
  hash[:event] = event.as_json
data/lib/timber/logger.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  require "logger"
2
2
  require "msgpack"
3
3
 
4
+ require "timber/current_context"
5
+ require "timber/event"
6
+ require "timber/log_devices/http"
7
+ require "timber/log_entry"
8
+
4
9
  module Timber
5
10
  # The Timber Logger behaves exactly like `::Logger`, except that it supports a transparent API
6
11
  # for logging structured messages. It ensures your log messages are communicated properly
@@ -72,47 +77,49 @@ module Timber
72
77
  "FATAL" => :fatal,
73
78
  "UNKNOWN" => :unknown
74
79
  }
80
+ EMPTY_ARRAY = []
75
81
 
76
82
  private
77
- def build_log_entry(severity, time, progname, msg)
78
- level = SEVERITY_MAP.fetch(severity)
83
+ def build_log_entry(severity, time, progname, logged_obj)
79
84
  context_snapshot = CurrentContext.instance.snapshot
80
-
85
+ level = SEVERITY_MAP.fetch(severity)
81
86
  tags = extract_active_support_tagged_logging_tags
82
- time_ms = nil
83
- if msg.is_a?(Hash)
84
- if msg.key?(:tag) || msg.key?(:tags)
85
- tags = tags.clone
86
- tags << msg.delete(:tag) if msg.key?(:tag)
87
- tags += msg.delete(:tags) if msg.key?(:tags)
88
- tags.uniq!
89
- end
90
- time_ms = msg.delete(:time_ms) if msg.key?(:time_ms)
91
-
92
- msg = msg[:message] if msg.length == 1
93
- end
94
87
 
95
- event = Events.build(msg)
88
+ if logged_obj.is_a?(Event)
89
+ LogEntry.new(level, time, progname, logged_obj.message, context_snapshot, logged_obj,
90
+ tags: tags)
91
+ elsif logged_obj.is_a?(Hash)
92
+ # Extract the tags
93
+ tags = tags.clone
94
+ tags << logged_obj.delete(:tag) if logged_obj.key?(:tag)
95
+ tags += logged_obj.delete(:tags) if logged_obj.key?(:tags)
96
+ tags.uniq!
97
+
98
+ # Extract the time_ms
99
+ time_ms = logged_obj.delete(:time_ms)
96
100
 
97
- if event
98
- LogEntry.new(level, time, progname, event.message, context_snapshot, event, tags: tags, time_ms: time_ms)
101
+ # Build the event
102
+ event = Events.build(logged_obj)
103
+ message = event ? event.message : logged_obj[:message]
104
+
105
+ LogEntry.new(level, time, progname, message, context_snapshot, event, tags: tags,
106
+ time_ms: time_ms)
99
107
  else
100
- LogEntry.new(level, time, progname, msg, context_snapshot, nil, tags: tags, time_ms: time_ms)
108
+ LogEntry.new(level, time, progname, logged_obj, context_snapshot, nil, tags: tags)
101
109
  end
102
110
  end
103
111
 
104
- # Because of all the crazy ways Rails has attempted this we need this crazy method.
112
+ # Because of all the crazy ways Rails has attempted tags, we need this crazy method.
105
113
  def extract_active_support_tagged_logging_tags
106
114
  Thread.current[:activesupport_tagged_logging_tags] ||
107
115
  Thread.current["activesupport_tagged_logging_tags:#{object_id}"] ||
108
- []
116
+ EMPTY_ARRAY
109
117
  end
110
118
  end
111
119
 
112
120
  # For use in development and test environments where you do not want metadata
113
121
  # included in the log lines.
114
- class SimpleFormatter < Formatter
115
-
122
+ class MessageOnlyFormatter < Formatter
116
123
  # This method is invoked when a log event occurs
117
124
  def call(severity, timestamp, progname, msg)
118
125
  log_entry = build_log_entry(severity, timestamp, progname, msg)
@@ -127,19 +134,17 @@ module Timber
127
134
  #
128
135
  # My log message @metadata {"level":"info","dt":"2016-09-01T07:00:00.000000-05:00"}
129
136
  #
130
- class StringFormatter < Formatter
131
- METADATA_CALLOUT = "@metadata".freeze
137
+ class AugmentedFormatter < Formatter
138
+ METADATA_CALLOUT = " @metadata ".freeze
139
+ NEW_LINE = "\n".freeze
140
+ ESCAPED_NEW_LINE = "\\n".freeze
132
141
 
133
142
  def call(severity, time, progname, msg)
134
143
  log_entry = build_log_entry(severity, time, progname, msg)
135
-
136
- if Config.instance.append_metadata?
137
- metadata = log_entry.to_json(:except => [:message])
138
- # use << for concatenation for performance reasons
139
- log_entry.message.gsub("\n", "\\n") << " " << METADATA_CALLOUT << " " << metadata << "\n"
140
- else
141
- log_entry.message + "\n"
142
- end
144
+ metadata = log_entry.to_json(:except => [:message])
145
+ # use << for concatenation for performance reasons
146
+ log_entry.message.gsub(NEW_LINE, ESCAPED_NEW_LINE) << METADATA_CALLOUT <<
147
+ metadata << NEW_LINE
143
148
  end
144
149
  end
145
150
 
@@ -176,7 +181,7 @@ module Timber
176
181
  include ::LoggerSilence if defined?(::LoggerSilence)
177
182
 
178
183
  # Creates a new Timber::Logger instances. Accepts the same arguments as `::Logger.new`.
179
- # The only difference is that it default the formatter to {HybridFormatter}. Using
184
+ # The only difference is that it default the formatter to {AugmentedFormatter}. Using
180
185
  # a different formatter is easy. For example, if you prefer your logs in JSON.
181
186
  #
182
187
  # @example Changing your formatter
@@ -193,7 +198,7 @@ module Timber
193
198
  if args.size == 1 and args.first.is_a?(LogDevices::HTTP)
194
199
  self.formatter = PassThroughFormatter.new
195
200
  else
196
- self.formatter = StringFormatter.new
201
+ self.formatter = AugmentedFormatter.new
197
202
  end
198
203
 
199
204
  self.level = environment_level
@@ -203,6 +208,9 @@ module Timber
203
208
  @initialized = true
204
209
  end
205
210
 
211
+ # Sets a new formatted on the logger.
212
+ #
213
+ # @note The formatter cannot be changed if you are using the HTTP logger backend.
206
214
  def formatter=(value)
207
215
  if @initialized && @logdev && @logdev.dev.is_a?(Timber::LogDevices::HTTP) && !value.is_a?(PassThroughFormatter)
208
216
  raise ArgumentError.new("The formatter cannot be changed when using the " +
@@ -219,6 +227,13 @@ module Timber
219
227
  Timber::CurrentContext.with(context, &block)
220
228
  end
221
229
 
230
+ # Patch to ensure that the {#level} method is used instead of `@level`.
231
+ # This is required because of Rails' monkey patching on Logger via `::LoggerSilence`.
232
+ def add(severity, message = nil, progname = nil, &block)
233
+ return true if @logdev.nil? || (severity || UNKNOWN) < level
234
+ super
235
+ end
236
+
222
237
  # Backwards compatibility with older ActiveSupport::Logger versions
223
238
  Logger::Severity.constants.each do |severity|
224
239
  class_eval(<<-EOT, __FILE__, __LINE__ + 1)
@@ -226,7 +241,7 @@ module Timber
226
241
  progname = args.first
227
242
  options = args.last
228
243
 
229
- if args.length == 2 and options.is_a?(Hash) && options != {}
244
+ if args.length == 2 and options.is_a?(Hash) && options.length > 0
230
245
  progname = options.merge(message: progname)
231
246
  end
232
247
 
@@ -1,3 +1,5 @@
1
+ # The order is relevant
2
+ require "timber/overrides/active_support_3_tagged_logging"
1
3
  require "timber/overrides/active_support_tagged_logging"
2
4
  require "timber/overrides/lograge"
3
5
  require "timber/overrides/rails_stdout_logging"
@@ -0,0 +1,103 @@
1
+ # This patch is specifically for Rails 3. The legacy approach to wrapping the logger in
2
+ # ActiveSupport::TaggedLogging is rather poor, hence the reason it was changed entirely
3
+ # for Rails 4 and 5. The problem is that ActiveSupport::TaggedLogging is a wrapping
4
+ # class that entirely redefines the public API for the logger. As a result, any deviations
5
+ # from this API in the logger are not exposed (such as accepting event data as a second argument).
6
+ # This is assuming, so we're fixing it here.
7
+
8
+ begin
9
+ require "active_support/tagged_logging"
10
+
11
+ # Instead of patching the class we're pulling the code from Rails master. This brings in
12
+ # a number of improvements while also addressing the issue above.
13
+ if ActiveSupport::TaggedLogging.instance_of?(Class)
14
+ ActiveSupport.send(:remove_const, :TaggedLogging)
15
+
16
+ require "active_support/core_ext/module/delegation"
17
+ require "active_support/core_ext/object/blank"
18
+ require "logger"
19
+
20
+ module ActiveSupport
21
+ # Wraps any standard Logger object to provide tagging capabilities.
22
+ #
23
+ # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
24
+ # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
25
+ # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
26
+ # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
27
+ #
28
+ # This is used by the default Rails.logger as configured by Railties to make
29
+ # it easy to stamp log lines with subdomains, request ids, and anything else
30
+ # to aid debugging of multi-user production applications.
31
+ module TaggedLogging
32
+ module Formatter # :nodoc:
33
+ # This method is invoked when a log event occurs.
34
+ def call(severity, timestamp, progname, msg)
35
+ super(severity, timestamp, progname, "#{tags_text}#{msg}")
36
+ end
37
+
38
+ def tagged(*tags)
39
+ new_tags = push_tags(*tags)
40
+ yield self
41
+ ensure
42
+ pop_tags(new_tags.size)
43
+ end
44
+
45
+ def push_tags(*tags)
46
+ tags.flatten.reject(&:blank?).tap do |new_tags|
47
+ current_tags.concat new_tags
48
+ end
49
+ end
50
+
51
+ def pop_tags(size = 1)
52
+ current_tags.pop size
53
+ end
54
+
55
+ def clear_tags!
56
+ current_tags.clear
57
+ end
58
+
59
+ def current_tags
60
+ # We use our object ID here to avoid conflicting with other instances
61
+ thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}".freeze
62
+ Thread.current[thread_key] ||= []
63
+ end
64
+
65
+ def tags_text
66
+ tags = current_tags
67
+ if tags.any?
68
+ tags.collect { |tag| "[#{tag}] " }.join
69
+ end
70
+ end
71
+ end
72
+
73
+ # Simple formatter which only displays the message.
74
+ class SimpleFormatter < ::Logger::Formatter
75
+ # This method is invoked when a log event occurs
76
+ def call(severity, timestamp, progname, msg)
77
+ "#{String === msg ? msg : msg.inspect}\n"
78
+ end
79
+ end
80
+
81
+ def self.new(logger)
82
+ # Ensure we set a default formatter so we aren't extending nil!
83
+ logger.formatter ||= SimpleFormatter.new
84
+ logger.formatter.extend Formatter
85
+ logger.extend(self)
86
+ end
87
+
88
+ delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
89
+
90
+ def tagged(*tags)
91
+ formatter.tagged(*tags) { yield self }
92
+ end
93
+
94
+ def flush
95
+ clear_tags!
96
+ super if defined?(super)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ rescue Exception
103
+ end
@@ -1,103 +1,66 @@
1
- # This patch is specifically for Rails 3. The legacy approach to wrapping the logger in
2
- # ActiveSupport::TaggedLogging is rather poor, hence the reason it was changed entirely
3
- # for Rails 4 and 5. The problem is that ActiveSupport::TaggedLogging is a wrapping
4
- # class that entirely redefines the public API for the logger. As a result, any deviations
5
- # from this API in the logger are not exposed (such as accepting event data as a second argument).
6
- # This is assuming, so we're fixing it here.
7
-
8
- begin
9
- require "active_support/tagged_logging"
10
-
11
- # Instead of patching the class we're pulling the code from Rails master. This brings in
12
- # a number of improvements while also addressing the issue above.
13
- if ActiveSupport::TaggedLogging.instance_of?(Class)
14
- ActiveSupport.send(:remove_const, :TaggedLogging)
15
-
16
- require "active_support/core_ext/module/delegation"
17
- require "active_support/core_ext/object/blank"
18
- require "logger"
19
-
20
- module ActiveSupport
21
- # Wraps any standard Logger object to provide tagging capabilities.
22
- #
23
- # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
24
- # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
25
- # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
26
- # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
27
- #
28
- # This is used by the default Rails.logger as configured by Railties to make
29
- # it easy to stamp log lines with subdomains, request ids, and anything else
30
- # to aid debugging of multi-user production applications.
31
- module TaggedLogging
32
- module Formatter # :nodoc:
33
- # This method is invoked when a log event occurs.
34
- def call(severity, timestamp, progname, msg)
35
- super(severity, timestamp, progname, "#{tags_text}#{msg}")
36
- end
37
-
38
- def tagged(*tags)
39
- new_tags = push_tags(*tags)
40
- yield self
41
- ensure
42
- pop_tags(new_tags.size)
43
- end
44
-
45
- def push_tags(*tags)
46
- tags.flatten.reject(&:blank?).tap do |new_tags|
47
- current_tags.concat new_tags
1
+ # This is an override instead of an integration because without this Timber would not
2
+ # work properly if ActiveSupport::TaggedLogging is used.
3
+ #
4
+ # This is called after 'active_support_3_tagged_logging' where the constant is loaded and
5
+ # replaced. I want to make sure we don't attempt to load it again undoing the patches
6
+ # applied there.
7
+ if defined?(ActiveSupport::TaggedLogging)
8
+ module Timber
9
+ module Overrides
10
+ # @private
11
+ module ActiveSupportTaggedLogging
12
+ # @private
13
+ module FormatterMethods
14
+ def self.included(mod)
15
+ mod.module_eval do
16
+ alias_method :_timber_original_push_tags, :push_tags
17
+ alias_method :_timber_original_pop_tags, :pop_tags
18
+
19
+ def call(severity, timestamp, progname, msg)
20
+ if is_a?(Timber::Logger::Formatter)
21
+ # Don't convert the message into a string
22
+ super(severity, timestamp, progname, msg)
23
+ else
24
+ super(severity, timestamp, progname, "#{tags_text}#{msg}")
25
+ end
26
+ end
48
27
  end
49
28
  end
29
+ end
50
30
 
51
- def pop_tags(size = 1)
52
- current_tags.pop size
53
- end
54
-
55
- def clear_tags!
56
- current_tags.clear
57
- end
58
-
59
- def current_tags
60
- # We use our object ID here to avoid conflicting with other instances
61
- thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}".freeze
62
- Thread.current[thread_key] ||= []
63
- end
64
-
65
- def tags_text
66
- tags = current_tags
67
- if tags.any?
68
- tags.collect { |tag| "[#{tag}] " }.join
31
+ # @private
32
+ module LoggerMethods
33
+ def self.included(klass)
34
+ klass.class_eval do
35
+ def add(severity, message = nil, progname = nil, &block)
36
+ if message.nil?
37
+ if block_given?
38
+ message = block.call
39
+ else
40
+ message = progname
41
+ progname = nil #No instance variable for this like Logger
42
+ end
43
+ end
44
+ if @logger.is_a?(Timber::Logger)
45
+ @logger.add(severity, message, progname)
46
+ else
47
+ @logger.add(severity, "#{tags_text}#{message}", progname)
48
+ end
49
+ end
69
50
  end
70
51
  end
71
52
  end
72
53
 
73
- # Simple formatter which only displays the message.
74
- class SimpleFormatter < ::Logger::Formatter
75
- # This method is invoked when a log event occurs
76
- def call(severity, timestamp, progname, msg)
77
- "#{String === msg ? msg : msg.inspect}\n"
54
+ if defined?(::ActiveSupport::TaggedLogging::Formatter)
55
+ if !::ActiveSupport::TaggedLogging::Formatter.include?(FormatterMethods)
56
+ ::ActiveSupport::TaggedLogging::Formatter.send(:include, FormatterMethods)
57
+ end
58
+ else
59
+ if !::ActiveSupport::TaggedLogging.include?(LoggerMethods)
60
+ ::ActiveSupport::TaggedLogging.send(:include, LoggerMethods)
78
61
  end
79
- end
80
-
81
- def self.new(logger)
82
- # Ensure we set a default formatter so we aren't extending nil!
83
- logger.formatter ||= SimpleFormatter.new
84
- logger.formatter.extend Formatter
85
- logger.extend(self)
86
- end
87
-
88
- delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
89
-
90
- def tagged(*tags)
91
- formatter.tagged(*tags) { yield self }
92
- end
93
-
94
- def flush
95
- clear_tags!
96
- super if defined?(super)
97
62
  end
98
63
  end
99
64
  end
100
65
  end
101
-
102
- rescue Exception
103
66
  end