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.
- checksums.yaml +4 -4
- data/README.md +3 -6
- data/Rakefile +2 -2
- data/lib/rails_semantic_logger.rb +35 -0
- data/lib/rails_semantic_logger/action_controller/log_subscriber.rb +108 -0
- data/lib/rails_semantic_logger/action_view/log_subscriber.rb +108 -0
- data/lib/rails_semantic_logger/active_record/log_subscriber.rb +186 -0
- data/lib/rails_semantic_logger/delayed_job/plugin.rb +11 -0
- data/lib/rails_semantic_logger/engine.rb +80 -70
- data/lib/rails_semantic_logger/extensions/action_controller/live.rb +5 -3
- data/lib/rails_semantic_logger/extensions/action_dispatch/debug_exceptions.rb +8 -6
- data/lib/rails_semantic_logger/extensions/action_view/streaming_template_renderer.rb +8 -5
- data/lib/rails_semantic_logger/extensions/active_job/logging.rb +8 -5
- data/lib/rails_semantic_logger/extensions/active_model_serializers/logging.rb +11 -8
- data/lib/rails_semantic_logger/extensions/rails/server.rb +2 -2
- data/lib/rails_semantic_logger/rack/logger.rb +103 -0
- data/lib/rails_semantic_logger/version.rb +2 -2
- metadata +13 -14
- data/lib/rails_semantic_logger/extensions/action_controller/log_subscriber.rb +0 -111
- data/lib/rails_semantic_logger/extensions/action_controller/log_subscriber_processing.rb +0 -28
- data/lib/rails_semantic_logger/extensions/action_view/log_subscriber.rb +0 -12
- data/lib/rails_semantic_logger/extensions/active_record/log_subscriber.rb +0 -102
- data/lib/rails_semantic_logger/extensions/rails/rack/logger.rb +0 -63
- data/lib/rails_semantic_logger/extensions/rails/rack/logger_info_as_debug.rb +0 -30
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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::
|
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
|
-
|
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
|
-
[
|
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
|
-
#
|
171
|
-
config.
|
172
|
-
|
173
|
-
|
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
|
-
|
197
|
-
|
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
|
-
|
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
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
224
|
+
# Active Record
|
225
|
+
RailsSemanticLogger.swap_subscriber(
|
226
|
+
::ActiveRecord::LogSubscriber,
|
227
|
+
RailsSemanticLogger::ActiveRecord::LogSubscriber,
|
228
|
+
:active_record
|
229
|
+
)
|
248
230
|
|
249
|
-
|
250
|
-
|
251
|
-
|
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
|
-
|
254
|
-
|
248
|
+
# Action Controller
|
249
|
+
RailsSemanticLogger.swap_subscriber(
|
250
|
+
::ActionController::LogSubscriber,
|
251
|
+
RailsSemanticLogger::ActionController::LogSubscriber,
|
252
|
+
:action_controller
|
253
|
+
)
|
255
254
|
end
|
256
255
|
|
257
|
-
|
258
|
-
|
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
|
4
|
-
|
5
|
-
|
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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
5
|
-
|
4
|
+
module ActiveJob
|
5
|
+
module Logging
|
6
|
+
include SemanticLogger::Loggable
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
5
|
-
|
4
|
+
module ActiveModelSerializers
|
5
|
+
module Logging
|
6
|
+
include SemanticLogger::Loggable
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
14
|
-
|
15
|
+
class SerializableResource
|
16
|
+
include SemanticLogger::Loggable
|
17
|
+
end
|
15
18
|
end
|
@@ -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
|