rails_semantic_logger 4.2.1 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -6
  3. data/Rakefile +2 -2
  4. data/lib/rails_semantic_logger.rb +35 -0
  5. data/lib/rails_semantic_logger/action_controller/log_subscriber.rb +108 -0
  6. data/lib/rails_semantic_logger/action_view/log_subscriber.rb +108 -0
  7. data/lib/rails_semantic_logger/active_record/log_subscriber.rb +186 -0
  8. data/lib/rails_semantic_logger/delayed_job/plugin.rb +11 -0
  9. data/lib/rails_semantic_logger/engine.rb +80 -70
  10. data/lib/rails_semantic_logger/extensions/action_controller/live.rb +5 -3
  11. data/lib/rails_semantic_logger/extensions/action_dispatch/debug_exceptions.rb +8 -6
  12. data/lib/rails_semantic_logger/extensions/action_view/streaming_template_renderer.rb +8 -5
  13. data/lib/rails_semantic_logger/extensions/active_job/logging.rb +8 -5
  14. data/lib/rails_semantic_logger/extensions/active_model_serializers/logging.rb +11 -8
  15. data/lib/rails_semantic_logger/extensions/rails/server.rb +2 -2
  16. data/lib/rails_semantic_logger/rack/logger.rb +103 -0
  17. data/lib/rails_semantic_logger/version.rb +2 -2
  18. metadata +13 -14
  19. data/lib/rails_semantic_logger/extensions/action_controller/log_subscriber.rb +0 -111
  20. data/lib/rails_semantic_logger/extensions/action_controller/log_subscriber_processing.rb +0 -28
  21. data/lib/rails_semantic_logger/extensions/action_view/log_subscriber.rb +0 -12
  22. data/lib/rails_semantic_logger/extensions/active_record/log_subscriber.rb +0 -102
  23. data/lib/rails_semantic_logger/extensions/rails/rack/logger.rb +0 -63
  24. data/lib/rails_semantic_logger/extensions/rails/rack/logger_info_as_debug.rb +0 -30
@@ -0,0 +1,11 @@
1
+ module RailsSemanticLogger
2
+ module DelayedJob
3
+ class Plugin < Delayed::Plugin
4
+ callbacks do |lifecycle|
5
+ lifecycle.before(:execute) do |job, &block|
6
+ ::SemanticLogger.reopen
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,6 @@
1
+ require 'active_record/log_subscriber'
2
+ require 'action_controller/log_subscriber'
3
+
1
4
  module RailsSemanticLogger
2
5
  class Engine < ::Rails::Engine
3
6
  # Make the SemanticLogger config available in the Rails application config
@@ -16,22 +19,22 @@ module RailsSemanticLogger
16
19
  # end
17
20
  config.semantic_logger = ::SemanticLogger
18
21
 
19
- config.rails_semantic_logger = ActiveSupport::OrderedOptions.new
22
+ config.rails_semantic_logger = ActiveSupport::OrderedOptions.new
20
23
 
21
24
  # Convert Action Controller and Active Record text messages to semantic data
22
25
  # Rails -- Started -- { :ip => "127.0.0.1", :method => "GET", :path => "/dashboards/inquiry_recent_activity" }
23
26
  # UserController -- Completed #index -- { :action => "index", :db_runtime => 54.64, :format => "HTML", :method => "GET", :mongo_runtime => 0.0, :path => "/users", :status => 200, :status_message => "OK", :view_runtime => 709.88 }
24
- config.rails_semantic_logger.semantic = true
27
+ config.rails_semantic_logger.semantic = true
25
28
 
26
29
  # Change Rack started message to debug so that it does not appear in production
27
- config.rails_semantic_logger.started = false
30
+ config.rails_semantic_logger.started = false
28
31
 
29
32
  # Change Processing message to debug so that it does not appear in production
30
- config.rails_semantic_logger.processing = false
33
+ config.rails_semantic_logger.processing = false
31
34
 
32
35
  # Change Action View render log messages to debug so that they do not appear in production
33
36
  # ActionView::Base -- Rendered data/search/_user.html.haml (46.7ms)
34
- config.rails_semantic_logger.rendered = false
37
+ config.rails_semantic_logger.rendered = false
35
38
 
36
39
  # Override the Awesome Print options for logging Hash data as text:
37
40
  #
@@ -41,7 +44,7 @@ module RailsSemanticLogger
41
44
  #
42
45
  # Note: The option :multiline is set to false if not supplied.
43
46
  # Note: Has no effect if Awesome Print is not installed.
44
- config.rails_semantic_logger.ap_options = {multiline: false}
47
+ config.rails_semantic_logger.ap_options = {multiline: false}
45
48
 
46
49
  # Whether to automatically add an environment specific log file appender.
47
50
  # For Example: 'log/development.log'
@@ -54,7 +57,7 @@ module RailsSemanticLogger
54
57
  config.rails_semantic_logger.add_file_appender = true
55
58
 
56
59
  # Silence asset logging
57
- config.rails_semantic_logger.quiet_assets = false
60
+ config.rails_semantic_logger.quiet_assets = false
58
61
 
59
62
  # Override the output format for the primary Rails log file.
60
63
  #
@@ -90,18 +93,18 @@ module RailsSemanticLogger
90
93
  #
91
94
  # # In application.rb:
92
95
  # config.rails_semantic_logger.format = MyFormatter.new
93
- config.rails_semantic_logger.format = :default
96
+ config.rails_semantic_logger.format = :default
94
97
 
95
98
  # DEPRECATED
96
99
  # Instead, supply a Hash to config.log_tags
97
- config.rails_semantic_logger.named_tags = nil
100
+ config.rails_semantic_logger.named_tags = nil
98
101
 
99
102
  # Add a filter to the file logger [Regexp|Proc]
100
103
  # RegExp: Only include log messages where the class name matches the supplied
101
104
  # regular expression. All other messages will be ignored.
102
105
  # Proc: Only include log messages where the supplied Proc returns true.
103
106
  # The Proc must return true or false.
104
- config.rails_semantic_logger.filter = nil
107
+ config.rails_semantic_logger.filter = nil
105
108
 
106
109
  # Initialize SemanticLogger. In a Rails environment it will automatically
107
110
  # insert itself above the configured rails logger to add support for its
@@ -111,14 +114,18 @@ module RailsSemanticLogger
111
114
  Rails::Application::Bootstrap.initializers.delete_if { |i| i.name == :initialize_logger }
112
115
 
113
116
  initializer :initialize_logger, group: :all do
114
- config = Rails.application.config
117
+ config = Rails.application.config
115
118
 
116
119
  # Set the default log level based on the Rails config
117
120
  SemanticLogger.default_level = config.log_level
118
121
 
122
+ if defined?(Rails::Rack::Logger) && config.rails_semantic_logger.semantic
123
+ config.middleware.swap(Rails::Rack::Logger, RailsSemanticLogger::Rack::Logger, config.log_tags)
124
+ end
125
+
119
126
  # Existing loggers are ignored because servers like trinidad supply their
120
127
  # own file loggers which would result in duplicate logging to the same log file
121
- Rails.logger = config.logger = begin
128
+ Rails.logger = config.logger = begin
122
129
  if config.rails_semantic_logger.add_file_appender
123
130
  path = config.paths['log'].first
124
131
  FileUtils.mkdir_p(File.dirname(path)) unless File.exist?(File.dirname(path))
@@ -130,16 +137,16 @@ module RailsSemanticLogger
130
137
  formatter = {color: {ap: ap_options}} if (formatter == :default) && (config.colorize_logging != false)
131
138
 
132
139
  # Set internal logger to log to file only, in case another appender experiences errors during writes
133
- appender = SemanticLogger::Appender::File.new(file_name: path, level: config.log_level, formatter: formatter)
140
+ appender = SemanticLogger::Appender::File.new(
141
+ file_name: path,
142
+ level: config.log_level,
143
+ formatter: formatter
144
+ )
134
145
  appender.name = 'SemanticLogger'
135
146
  SemanticLogger::Processor.logger = appender
136
147
 
137
148
  # Check for previous file or stdout loggers
138
- if SemanticLogger::VERSION.to_f >= 4.2
139
- SemanticLogger.appenders.each { |appender| appender.formatter = formatter if appender.is_a?(SemanticLogger::Appender::File) }
140
- elsif config.colorize_logging == false
141
- SemanticLogger.appenders.each { |appender| appender.formatter = SemanticLogger::Formatters::Default.new if appender.is_a?(SemanticLogger::Appender::File) }
142
- end
149
+ SemanticLogger.appenders.each { |app| app.formatter = formatter if app.is_a?(SemanticLogger::Appender::File) }
143
150
  SemanticLogger.add_appender(file_name: path, formatter: formatter, filter: config.rails_semantic_logger.filter)
144
151
  end
145
152
 
@@ -153,54 +160,29 @@ module RailsSemanticLogger
153
160
 
154
161
  logger = SemanticLogger[Rails]
155
162
  logger.warn(
156
- "Rails Error: Unable to access log file. Please ensure that #{path} exists and is chmod 0666. " +
157
- "The log level has been raised to WARN and the output directed to STDERR until the problem is fixed.",
163
+ "Rails Error: Unable to access log file. Please ensure that #{path} exists and is chmod 0666. " \
164
+ 'The log level has been raised to WARN and the output directed to STDERR until the problem is fixed.',
158
165
  exc
159
166
  )
160
167
  logger
161
168
  end
162
169
 
163
170
  # Replace Rails loggers
164
- [:active_record, :action_controller, :action_mailer, :action_view].each do |name|
171
+ %i[active_record action_controller action_mailer action_view].each do |name|
165
172
  ActiveSupport.on_load(name) { include SemanticLogger::Loggable }
166
173
  end
167
174
  ActiveSupport.on_load(:action_cable) { self.logger = SemanticLogger['ActionCable'] }
168
175
  end
169
176
 
170
- # Support fork frameworks
171
- config.after_initialize do
172
- # Silence asset logging by applying a filter to the Rails logger itself, not any of the appenders.
173
- if config.rails_semantic_logger.quiet_assets && config.assets.prefix #&& defined?(Rails::Rack::Logger)
174
- assets_regex = %r(\A/{0,2}#{config.assets.prefix})
175
- if Rails.version.to_i >= 5
176
- Rails::Rack::Logger.logger.filter = -> log { log.payload[:path] !~ assets_regex if log.payload }
177
- else
178
- # Also strips the empty log lines
179
- Rails::Rack::Logger.logger.filter = -> log { log.payload.nil? ? (log.message != '') : (log.payload[:path] !~ assets_regex) }
180
- end
181
- end
182
-
183
- # Passenger provides the :starting_worker_process event for executing
184
- # code after it has forked, so we use that and reconnect immediately.
185
- if defined?(PhusionPassenger)
186
- PhusionPassenger.on_event(:starting_worker_process) do |forked|
187
- ::SemanticLogger.reopen if forked
188
- end
189
- end
190
-
191
- # Re-open appenders after Resque has forked a worker
192
- if defined?(Resque)
193
- Resque.after_fork { |job| ::SemanticLogger.reopen }
194
- end
177
+ # Before any initializers run, but after the gems have been loaded
178
+ config.before_initialize do
179
+ if config.respond_to?(:assets) && defined?(Rails::Rack::Logger) && config.rails_semantic_logger.semantic
180
+ config.rails_semantic_logger.quiet_assets = true if config.assets.quiet
195
181
 
196
- # Re-open appenders after Spring has forked a process
197
- if defined?(Spring)
198
- Spring.after_fork { |job| ::SemanticLogger.reopen }
182
+ # Otherwise Sprockets can't find the Rails::Rack::Logger middleware
183
+ config.assets.quiet = false
199
184
  end
200
- end
201
185
 
202
- # Before any initializers run, but after the gems have been loaded
203
- config.before_initialize do
204
186
  # Replace the Mongo Loggers
205
187
  Mongoid.logger = SemanticLogger[Mongoid] if defined?(Mongoid)
206
188
  Moped.logger = SemanticLogger[Moped] if defined?(Moped)
@@ -216,15 +198,13 @@ module RailsSemanticLogger
216
198
  Sidetiq.logger = SemanticLogger[Sidetiq] if defined?(Sidetiq)
217
199
 
218
200
  # Replace the DelayedJob logger
219
- Delayed::Worker.logger = SemanticLogger[Delayed::Worker] if defined?(Delayed::Worker)
201
+ if defined?(Delayed::Worker)
202
+ Delayed::Worker.logger = SemanticLogger[Delayed::Worker]
203
+ Delayed::Worker.plugins << RailsSemanticLogger::DelayedJob::Plugin
204
+ end
220
205
 
221
206
  # Replace the Bugsnag logger
222
207
  Bugsnag.configure { |config| config.logger = SemanticLogger[Bugsnag] } if defined?(Bugsnag)
223
-
224
- # Backward compatibility
225
- if config.rails_semantic_logger.named_tags
226
- config.log_tags = config.rails_semantic_logger.named_tags
227
- end
228
208
  end
229
209
 
230
210
  # After any initializers run, but after the gems have been loaded
@@ -241,23 +221,53 @@ module RailsSemanticLogger
241
221
  require('rails_semantic_logger/extensions/active_model_serializers/logging') if defined?(ActiveModelSerializers)
242
222
 
243
223
  if config.rails_semantic_logger.semantic
244
- require('rails_semantic_logger/extensions/rails/rack/logger') if defined?(Rails::Rack::Logger)
245
- require('rails_semantic_logger/extensions/action_controller/log_subscriber') if defined?(ActionController)
246
- require('rails_semantic_logger/extensions/active_record/log_subscriber') if defined?(ActiveRecord::LogSubscriber)
247
- end
224
+ # Active Record
225
+ RailsSemanticLogger.swap_subscriber(
226
+ ::ActiveRecord::LogSubscriber,
227
+ RailsSemanticLogger::ActiveRecord::LogSubscriber,
228
+ :active_record
229
+ )
248
230
 
249
- unless config.rails_semantic_logger.started
250
- require('rails_semantic_logger/extensions/rails/rack/logger_info_as_debug') if defined?(Rails::Rack::Logger)
251
- end
231
+ # Rack
232
+ RailsSemanticLogger::Rack::Logger.started_request_log_level = :info if config.rails_semantic_logger.started
233
+
234
+ # Silence asset logging by applying a filter to the Rails logger itself, not any of the appenders.
235
+ if config.rails_semantic_logger.quiet_assets && config.assets.prefix
236
+ assets_regex = %r(\A/{0,2}#{config.assets.prefix})
237
+ RailsSemanticLogger::Rack::Logger.logger.filter = ->(log) { log.payload[:path] !~ assets_regex if log.payload }
238
+ end
239
+
240
+ # Action View
241
+ RailsSemanticLogger::ActionView::LogSubscriber.rendered_log_level = :info if config.rails_semantic_logger.rendered
242
+ RailsSemanticLogger.swap_subscriber(
243
+ ::ActionView::LogSubscriber,
244
+ RailsSemanticLogger::ActionView::LogSubscriber,
245
+ :action_view
246
+ )
252
247
 
253
- unless config.rails_semantic_logger.rendered
254
- require('rails_semantic_logger/extensions/action_view/log_subscriber') if defined?(ActionView::LogSubscriber)
248
+ # Action Controller
249
+ RailsSemanticLogger.swap_subscriber(
250
+ ::ActionController::LogSubscriber,
251
+ RailsSemanticLogger::ActionController::LogSubscriber,
252
+ :action_controller
253
+ )
255
254
  end
256
255
 
257
- if config.rails_semantic_logger.processing
258
- require('rails_semantic_logger/extensions/action_controller/log_subscriber_processing') if defined?(ActionView::LogSubscriber)
256
+ #
257
+ # Forking Frameworks
258
+ #
259
+
260
+ # Passenger provides the :starting_worker_process event for executing
261
+ # code after it has forked, so we use that and reconnect immediately.
262
+ if defined?(PhusionPassenger)
263
+ PhusionPassenger.on_event(:starting_worker_process) { |forked| ::SemanticLogger.reopen if forked }
259
264
  end
260
- end
261
265
 
266
+ # Re-open appenders after Resque has forked a worker
267
+ Resque.after_fork { |_job| ::SemanticLogger.reopen } if defined?(Resque)
268
+
269
+ # Re-open appenders after Spring has forked a process
270
+ Spring.after_fork { |_job| ::SemanticLogger.reopen } if defined?(Spring)
271
+ end
262
272
  end
263
273
  end
@@ -1,7 +1,9 @@
1
1
  # Log actual exceptions, not a string representation
2
2
  ActionController::Live
3
- module ActionController::Live
4
- def log_error(exception)
5
- logger.fatal(exception)
3
+ module ActionController
4
+ module Live
5
+ def log_error(exception)
6
+ logger.fatal(exception)
7
+ end
6
8
  end
7
9
  end
@@ -1,11 +1,13 @@
1
1
  # Log actual exceptions, not a string representation
2
2
  ActionDispatch::DebugExceptions
3
- class ActionDispatch::DebugExceptions
4
- private
5
- def log_error(request, wrapper)
6
- ActiveSupport::Deprecation.silence do
7
- ActionController::Base.logger.fatal(wrapper.exception)
3
+ module ActionDispatch
4
+ class DebugExceptions
5
+ private
6
+
7
+ def log_error(_request, wrapper)
8
+ ActiveSupport::Deprecation.silence do
9
+ ActionController::Base.logger.fatal(wrapper.exception)
10
+ end
8
11
  end
9
12
  end
10
13
  end
11
-
@@ -1,11 +1,14 @@
1
1
  # Log actual exceptions, not a string representation
2
2
  ActionView::StreamingTemplateRenderer
3
3
 
4
- class ActionView::StreamingTemplateRenderer
5
- class Body
6
- private
7
- def log_error(exception) #:nodoc:
8
- ActionView::Base.logger.fatal(exception)
4
+ module ActionView
5
+ class StreamingTemplateRenderer
6
+ class Body
7
+ private
8
+
9
+ def log_error(exception)
10
+ ActionView::Base.logger.fatal(exception)
11
+ end
9
12
  end
10
13
  end
11
14
  end
@@ -1,11 +1,14 @@
1
1
  # Patch ActiveJob logger
2
2
  require 'active_job/logging'
3
3
 
4
- module ActiveJob::Logging
5
- include SemanticLogger::Loggable
4
+ module ActiveJob
5
+ module Logging
6
+ include SemanticLogger::Loggable
6
7
 
7
- private
8
- def tag_logger(*tags, &block)
9
- logger.tagged(*tags, &block)
8
+ private
9
+
10
+ def tag_logger(*tags, &block)
11
+ logger.tagged(*tags, &block)
12
+ end
10
13
  end
11
14
  end
@@ -1,15 +1,18 @@
1
1
  # Patch ActiveModelSerializers logger
2
2
  require 'active_model_serializers/logging'
3
3
 
4
- module ActiveModelSerializers::Logging
5
- include SemanticLogger::Loggable
4
+ module ActiveModelSerializers
5
+ module Logging
6
+ include SemanticLogger::Loggable
6
7
 
7
- private
8
- def tag_logger(*tags, &block)
9
- logger.tagged(*tags, &block)
8
+ private
9
+
10
+ def tag_logger(*tags, &block)
11
+ logger.tagged(*tags, &block)
12
+ end
10
13
  end
11
- end
12
14
 
13
- class ActiveModelSerializers::SerializableResource
14
- include SemanticLogger::Loggable
15
+ class SerializableResource
16
+ include SemanticLogger::Loggable
17
+ end
15
18
  end
@@ -1,7 +1,7 @@
1
1
  # Patch the Rails::Server log_to_stdout so that it logs via SemanticLogger
2
2
  Rails::Server
3
- module Rails #:nodoc:
4
- class Server #:nodoc:
3
+ module Rails
4
+ class Server
5
5
  private
6
6
 
7
7
  def log_to_stdout
@@ -0,0 +1,103 @@
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 RailsSemanticLogger
8
+ module Rack
9
+ class Logger < ActiveSupport::LogSubscriber
10
+ class << self
11
+ attr_reader :logger
12
+ attr_accessor :started_request_log_level
13
+ end
14
+
15
+ def initialize(app, taggers = nil)
16
+ @app = app
17
+ @taggers = taggers || []
18
+ end
19
+
20
+ def call(env)
21
+ request = ActionDispatch::Request.new(env)
22
+
23
+ # Check for named tags (Hash)
24
+ if @taggers && !@taggers.empty?
25
+ tags = @taggers.is_a?(Hash) ? compute_named_tags(request) : compute_tags(request)
26
+ logger.tagged(tags) { call_app(request, env) }
27
+ else
28
+ call_app(request, env)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ @logger = SemanticLogger['Rack']
35
+ @started_request_log_level = :debug
36
+
37
+ def call_app(request, env)
38
+ instrumenter = ActiveSupport::Notifications.instrumenter
39
+ instrumenter.start 'request.action_dispatch', request: request
40
+
41
+ logger.send(self.class.started_request_log_level) { started_request_message(request) }
42
+
43
+ status, headers, body = @app.call(env)
44
+ body = ::Rack::BodyProxy.new(body) { finish(request) }
45
+ [status, headers, body]
46
+ rescue Exception
47
+ finish(request)
48
+ raise
49
+ end
50
+
51
+ def started_request_message(request)
52
+ {
53
+ message: 'Started',
54
+ payload: {
55
+ method: request.request_method,
56
+ path: request.filtered_path,
57
+ ip: request.ip
58
+ }
59
+ }
60
+ end
61
+
62
+ def compute_tags(request)
63
+ @taggers.collect do |tag|
64
+ case tag
65
+ when Proc
66
+ tag.call(request)
67
+ when Symbol
68
+ request.send(tag)
69
+ else
70
+ tag
71
+ end
72
+ end
73
+ end
74
+
75
+ # Leave out any named tags with a nil value
76
+ def compute_named_tags(request)
77
+ tagged = {}
78
+ @taggers.each_pair do |tag, value|
79
+ resolved =
80
+ case value
81
+ when Proc
82
+ value.call(request)
83
+ when Symbol
84
+ request.send(value)
85
+ else
86
+ value
87
+ end
88
+ tagged[tag] = resolved unless resolved.nil?
89
+ end
90
+ tagged
91
+ end
92
+
93
+ def finish(request)
94
+ instrumenter = ActiveSupport::Notifications.instrumenter
95
+ instrumenter.finish 'request.action_dispatch', request: request
96
+ end
97
+
98
+ def logger
99
+ self.class.logger
100
+ end
101
+ end
102
+ end
103
+ end