rails_semantic_logger 5.0.0 → 5.2.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.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/Rakefile +2 -0
- data/lib/rails_semantic_logger/action_controller/log_subscriber.rb +2 -1
- data/lib/rails_semantic_logger/action_view/log_subscriber.rb +3 -3
- data/lib/rails_semantic_logger/appenders.rb +6 -5
- data/lib/rails_semantic_logger/engine.rb +44 -23
- data/lib/rails_semantic_logger/extensions/action_cable/tagged_logger_proxy.rb +71 -43
- data/lib/rails_semantic_logger/options.rb +45 -3
- data/lib/rails_semantic_logger/sidekiq/defaults.rb +10 -27
- data/lib/rails_semantic_logger/sidekiq/job_logger.rb +17 -5
- data/lib/rails_semantic_logger/solid_queue/log_subscriber.rb +5 -1
- data/lib/rails_semantic_logger/version.rb +1 -1
- data/lib/rails_semantic_logger.rb +1 -1
- metadata +7 -7
- data/lib/rails_semantic_logger/extensions/sidekiq/sidekiq.rb +0 -87
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '08056406dee88f7c5eb0d29107d9d82b95487cf913ace9a6dd292c49641f58c4'
|
|
4
|
+
data.tar.gz: 5dfdb7970f4baf88676218aa9a0778245957c094dc1ee7103e7940c456a54e06
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e138fdae60edf8a40b1e0b57d4b351bc0069b48550f0ecd0ee443ef8bbb154984c8923a07632d441cf154b39f7777e266073254f6cd57bd6bf83c26dd59c5b63
|
|
7
|
+
data.tar.gz: 5e7e1e27aded0d3a1731cab0f756dfada2d11dcf1f2a756bd41ecfa912c44f9931649df0a2e56f32d21328a64f22db1a9f97c02c6ac939f17974342f4805c7d8
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Rails Semantic Logger
|
|
2
2
|
[](https://rubygems.org/gems/rails_semantic_logger) [](https://github.com/reidmorrison/rails_semantic_logger/actions?query=workflow%3Abuild) [](https://rubygems.org/gems/rails_semantic_logger) [](http://opensource.org/licenses/Apache-2.0) 
|
|
3
3
|
|
|
4
|
-
Rails Semantic Logger replaces the Rails default logger with [Semantic Logger](https://logger.
|
|
4
|
+
Rails Semantic Logger replaces the Rails default logger with [Semantic Logger](https://logger.reidmorrison.com/), so that Rails, your application code, and many common gems all log through structured logging instead of plain text.
|
|
5
5
|
|
|
6
6
|
When any large Rails application is deployed to production one of the first steps is to move to centralized logging, so that logs can be viewed and searched from a central location. That quickly falls apart when consuming human readable text logs:
|
|
7
7
|
|
|
@@ -67,17 +67,17 @@ end
|
|
|
67
67
|
|
|
68
68
|
Because declaring an appender replaces the default file appender, JSON to stdout becomes the only destination, exactly what a container platform wants. Once logs are emitted as structured JSON, a centralized logging system can parse each field, including the nested `payload` and any `metric` data, into a searchable hierarchy, so you can build searches, alerts, and dashboards against well-defined fields instead of brittle text matching.
|
|
69
69
|
|
|
70
|
-
See [Configuring appenders](https://logger.
|
|
70
|
+
See [Configuring appenders](https://logger.reidmorrison.com/rails#configuring-where-logs-go-the-appenders-block) for the full guide, including formatters, third-party destinations, the [container platform recipe](https://logger.reidmorrison.com/rails#production-on-a-container-platform-docker-kubernetes-heroku), tuning what Rails logs, and worked examples of querying the JSON.
|
|
71
71
|
|
|
72
72
|
## Documentation
|
|
73
73
|
|
|
74
|
-
For complete documentation see: https://logger.
|
|
74
|
+
For complete documentation see: https://logger.reidmorrison.com/rails
|
|
75
75
|
|
|
76
76
|
## Upgrading
|
|
77
77
|
|
|
78
78
|
The way appenders (log destinations) are configured changed in v5. See the
|
|
79
|
-
[v4 to v5 migration guide](https://logger.
|
|
80
|
-
before/after mapping, and [Migrating from earlier versions](https://logger.
|
|
79
|
+
[v4 to v5 migration guide](https://logger.reidmorrison.com/rails#migrating-from-v4-to-v5) for the
|
|
80
|
+
before/after mapping, and [Migrating from earlier versions](https://logger.reidmorrison.com/rails#migrating-from-earlier-versions)
|
|
81
81
|
for older releases.
|
|
82
82
|
|
|
83
83
|
## New Versions of Rails, etc.
|
data/Rakefile
CHANGED
|
@@ -5,10 +5,12 @@ require "bundler/setup"
|
|
|
5
5
|
require "rake/testtask"
|
|
6
6
|
require_relative "lib/rails_semantic_logger/version"
|
|
7
7
|
|
|
8
|
+
desc "Build the gem"
|
|
8
9
|
task :gem do
|
|
9
10
|
system "gem build rails_semantic_logger.gemspec"
|
|
10
11
|
end
|
|
11
12
|
|
|
13
|
+
desc "Build and publish the gem, and tag the release"
|
|
12
14
|
task publish: :gem do
|
|
13
15
|
system "git tag -a v#{RailsSemanticLogger::VERSION} -m 'Tagging #{RailsSemanticLogger::VERSION}'"
|
|
14
16
|
system "git push --tags"
|
|
@@ -137,7 +137,8 @@ module RailsSemanticLogger
|
|
|
137
137
|
payload[:source] = source if source
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
-
controller_logger(event).info(message: "Redirected to", payload: payload,
|
|
140
|
+
controller_logger(event).info(message: "Redirected to", payload: payload,
|
|
141
|
+
metric: "rails.controller.redirect_to")
|
|
141
142
|
end
|
|
142
143
|
|
|
143
144
|
def send_data(event)
|
|
@@ -142,7 +142,7 @@ module RailsSemanticLogger
|
|
|
142
142
|
end
|
|
143
143
|
|
|
144
144
|
def rails_root
|
|
145
|
-
@
|
|
145
|
+
@rails_root ||= "#{Rails.root}/"
|
|
146
146
|
end
|
|
147
147
|
|
|
148
148
|
def logger
|
|
@@ -161,12 +161,12 @@ module RailsSemanticLogger
|
|
|
161
161
|
super
|
|
162
162
|
end
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
EMPTY = "".freeze
|
|
165
165
|
|
|
166
166
|
@logger = ::ActionView::Base.logger
|
|
167
167
|
@rendered_log_level = :debug
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
private
|
|
170
170
|
|
|
171
171
|
def should_log?
|
|
172
172
|
logger.send("#{self.class.rendered_log_level}?")
|
|
@@ -16,8 +16,8 @@ module RailsSemanticLogger
|
|
|
16
16
|
# destination and formatting are ordinary `SemanticLogger.add_appender` arguments:
|
|
17
17
|
#
|
|
18
18
|
# #add - always created, during Rails initialization.
|
|
19
|
-
# #add_server - created only when serving requests (`rails server`,
|
|
20
|
-
#
|
|
19
|
+
# #add_server - created only when serving requests (`rails server`, Sidekiq
|
|
20
|
+
# in server mode). Defaults to `$stdout`.
|
|
21
21
|
# #add_console - created only inside a `rails console` session. Defaults to
|
|
22
22
|
# `$stderr` so log output does not tangle with command results.
|
|
23
23
|
#
|
|
@@ -44,9 +44,10 @@ module RailsSemanticLogger
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
# Declare an appender that is only created when the application is serving
|
|
47
|
-
# requests: `rails server`,
|
|
48
|
-
#
|
|
49
|
-
#
|
|
47
|
+
# requests: `rails server`, Sidekiq in server mode, or when the app calls
|
|
48
|
+
# RailsSemanticLogger.add_server_appenders from its own server's boot hook.
|
|
49
|
+
# It is never created during a non-serving boot (rake tasks, runners,
|
|
50
|
+
# generators), so it only appears where it is useful.
|
|
50
51
|
#
|
|
51
52
|
# Accepts the same arguments (and optional block) as SemanticLogger.add_appender.
|
|
52
53
|
# When no destination is given it defaults to `$stdout`; the formatter defaults
|
|
@@ -25,6 +25,27 @@ module RailsSemanticLogger
|
|
|
25
25
|
# insert itself above the configured rails logger to add support for its
|
|
26
26
|
# additional features
|
|
27
27
|
|
|
28
|
+
# Register this gem's deprecator with the application so that the standard Rails
|
|
29
|
+
# deprecation settings govern it: `config.active_support.report_deprecations`,
|
|
30
|
+
# `config.active_support.deprecation`, and
|
|
31
|
+
# `Rails.application.deprecators[:rails_semantic_logger]`. Rails' own
|
|
32
|
+
# `active_support.deprecation_behavior` initializer only reaches deprecators in
|
|
33
|
+
# that collection.
|
|
34
|
+
#
|
|
35
|
+
# Runs before the environment file is read so that an application can also reach
|
|
36
|
+
# the deprecator by name from `config/environments/*.rb`.
|
|
37
|
+
initializer "rails_semantic_logger.deprecator", before: :load_environment_config do |app|
|
|
38
|
+
app.deprecators[:rails_semantic_logger] = RailsSemanticLogger.deprecator
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# The deprecated appender options are set from `config/application.rb` and
|
|
42
|
+
# `config/environments/*.rb`, which Rails reads before it applies the deprecation
|
|
43
|
+
# settings above, so their warnings are recorded rather than emitted. Now that
|
|
44
|
+
# the settings are in place, emit them.
|
|
45
|
+
initializer "rails_semantic_logger.flush_deprecations", after: "active_support.deprecation_behavior" do |app|
|
|
46
|
+
app.config.rails_semantic_logger.flush_deprecations!
|
|
47
|
+
end
|
|
48
|
+
|
|
28
49
|
# Replace Rails logger initializer
|
|
29
50
|
Rails::Application::Bootstrap.initializers.delete_if { |i| i.name == :initialize_logger }
|
|
30
51
|
|
|
@@ -48,7 +69,7 @@ module RailsSemanticLogger
|
|
|
48
69
|
elsif config.rails_semantic_logger.add_file_appender
|
|
49
70
|
# DEPRECATED: This option is deprecated and will be removed in a future version.
|
|
50
71
|
path = config.paths["log"].first
|
|
51
|
-
FileUtils.mkdir_p(File.dirname(path))
|
|
72
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
52
73
|
|
|
53
74
|
# Add the log file to the list of appenders
|
|
54
75
|
# Use the colorized formatter if Rails colorized logs are enabled
|
|
@@ -67,21 +88,28 @@ module RailsSemanticLogger
|
|
|
67
88
|
|
|
68
89
|
app.formatter = formatter
|
|
69
90
|
end
|
|
70
|
-
SemanticLogger.add_appender(file_name: path, formatter: formatter,
|
|
91
|
+
SemanticLogger.add_appender(file_name: path, formatter: formatter,
|
|
92
|
+
filter: config.rails_semantic_logger.filter)
|
|
71
93
|
end
|
|
72
94
|
|
|
73
95
|
SemanticLogger[Rails]
|
|
74
96
|
rescue StandardError => e
|
|
75
|
-
# If
|
|
97
|
+
# If unable to create the appenders, log to standard error with warning level only
|
|
76
98
|
SemanticLogger.default_level = :warn
|
|
77
99
|
|
|
78
100
|
SemanticLogger::Processor.logger = SemanticLogger::Appender::IO.new($stderr)
|
|
79
101
|
SemanticLogger.add_appender(io: $stderr)
|
|
80
102
|
|
|
103
|
+
message =
|
|
104
|
+
if path
|
|
105
|
+
"Rails Error: Unable to access log file. Please ensure that #{path} exists and is chmod 0666."
|
|
106
|
+
else
|
|
107
|
+
"Rails Error: Unable to create the configured appenders."
|
|
108
|
+
end
|
|
81
109
|
logger = SemanticLogger[Rails]
|
|
82
110
|
logger.warn(
|
|
83
|
-
"
|
|
84
|
-
"
|
|
111
|
+
"#{message} The log level has been raised to WARN and the output directed to STDERR " \
|
|
112
|
+
"until the problem is fixed.",
|
|
85
113
|
e
|
|
86
114
|
)
|
|
87
115
|
logger
|
|
@@ -122,12 +150,8 @@ module RailsSemanticLogger
|
|
|
122
150
|
end
|
|
123
151
|
|
|
124
152
|
::Sidekiq.configure_server do |config|
|
|
125
|
-
config.logger
|
|
126
|
-
|
|
127
|
-
config.options[:job_logger] = RailsSemanticLogger::Sidekiq::JobLogger
|
|
128
|
-
else
|
|
129
|
-
config[:job_logger] = RailsSemanticLogger::Sidekiq::JobLogger
|
|
130
|
-
end
|
|
153
|
+
config.logger = ::SemanticLogger[::Sidekiq]
|
|
154
|
+
config[:job_logger] = RailsSemanticLogger::Sidekiq::JobLogger
|
|
131
155
|
|
|
132
156
|
# Add back the default console logger (unless the app declared its own appenders, or one exists)
|
|
133
157
|
RailsSemanticLogger.add_server_appenders
|
|
@@ -137,15 +161,12 @@ module RailsSemanticLogger
|
|
|
137
161
|
config.error_handlers << RailsSemanticLogger::Sidekiq::Defaults::ERROR_HANDLER if existing
|
|
138
162
|
end
|
|
139
163
|
|
|
140
|
-
|
|
141
|
-
::Sidekiq::Job.singleton_class.prepend(RailsSemanticLogger::Sidekiq::Loggable)
|
|
142
|
-
else
|
|
143
|
-
::Sidekiq::Worker.singleton_class.prepend(RailsSemanticLogger::Sidekiq::Loggable)
|
|
144
|
-
end
|
|
164
|
+
::Sidekiq::Job.singleton_class.prepend(RailsSemanticLogger::Sidekiq::Loggable)
|
|
145
165
|
end
|
|
146
166
|
|
|
147
167
|
# Replace the SolidQueue logger
|
|
148
|
-
if config.rails_semantic_logger.replace_solid_queue_logger &&
|
|
168
|
+
if config.rails_semantic_logger.replace_solid_queue_logger &&
|
|
169
|
+
defined?(::SolidQueue) && ::SolidQueue.respond_to?(:logger=)
|
|
149
170
|
::SolidQueue.logger = SemanticLogger[::SolidQueue]
|
|
150
171
|
end
|
|
151
172
|
|
|
@@ -224,14 +245,18 @@ module RailsSemanticLogger
|
|
|
224
245
|
if config.rails_semantic_logger.quiet_assets && config.respond_to?(:assets) && config.assets.prefix
|
|
225
246
|
assets_root = config.relative_url_root.to_s + config.assets.prefix
|
|
226
247
|
assets_regex = %r(\A/{0,2}#{assets_root})
|
|
227
|
-
RailsSemanticLogger::Rack::Logger.logger.filter =
|
|
248
|
+
RailsSemanticLogger::Rack::Logger.logger.filter = lambda do |log|
|
|
249
|
+
log.payload[:path] !~ assets_regex if log.payload
|
|
250
|
+
end
|
|
228
251
|
end
|
|
229
252
|
|
|
230
253
|
# Action View
|
|
231
254
|
if defined?(::ActionView)
|
|
232
255
|
require "action_view/log_subscriber"
|
|
233
256
|
|
|
234
|
-
|
|
257
|
+
if config.rails_semantic_logger.rendered
|
|
258
|
+
RailsSemanticLogger::ActionView::LogSubscriber.rendered_log_level = :info
|
|
259
|
+
end
|
|
235
260
|
RailsSemanticLogger.swap_subscriber(
|
|
236
261
|
::ActionView::LogSubscriber,
|
|
237
262
|
RailsSemanticLogger::ActionView::LogSubscriber,
|
|
@@ -264,10 +289,6 @@ module RailsSemanticLogger
|
|
|
264
289
|
)
|
|
265
290
|
end
|
|
266
291
|
|
|
267
|
-
if config.rails_semantic_logger.replace_sidekiq_logger && defined?(::Sidekiq)
|
|
268
|
-
require("rails_semantic_logger/extensions/sidekiq/sidekiq")
|
|
269
|
-
end
|
|
270
|
-
|
|
271
292
|
# SolidQueue
|
|
272
293
|
if config.rails_semantic_logger.replace_solid_queue_logger && defined?(::SolidQueue::LogSubscriber)
|
|
273
294
|
RailsSemanticLogger.swap_subscriber(
|
|
@@ -1,53 +1,81 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
# Upstream source (identical across supported versions):
|
|
1
|
+
# Upstream source (identical across supported versions, only the namespace differs):
|
|
4
2
|
# https://github.com/rails/rails/blob/v7.2.2/actioncable/lib/action_cable/connection/tagged_logger_proxy.rb
|
|
5
3
|
# https://github.com/rails/rails/blob/v8.0.2/actioncable/lib/action_cable/connection/tagged_logger_proxy.rb
|
|
6
4
|
# https://github.com/rails/rails/blob/v8.1.3/actioncable/lib/action_cable/connection/tagged_logger_proxy.rb
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
logger.tagged(*current_tags, &)
|
|
21
|
-
else
|
|
22
|
-
yield
|
|
23
|
-
end
|
|
5
|
+
# https://github.com/rails/rails/blob/main/actioncable/lib/action_cable/server/tagged_logger_proxy.rb
|
|
6
|
+
module RailsSemanticLogger
|
|
7
|
+
module ActionCable
|
|
8
|
+
# Rails 8.2 moved the proxy from ActionCable::Connection to ActionCable::Server, as part of
|
|
9
|
+
# the ActionCable::Server::Socket refactor, without leaving a back-compat alias behind.
|
|
10
|
+
# Resolve whichever constant this version of ActionCable ships rather than hard-coding a
|
|
11
|
+
# namespace, so that a `require` of the old path cannot fail the app's boot. See #326.
|
|
12
|
+
TaggedLoggerProxy =
|
|
13
|
+
if defined?(::ActionCable::Server::TaggedLoggerProxy)
|
|
14
|
+
::ActionCable::Server::TaggedLoggerProxy
|
|
15
|
+
else
|
|
16
|
+
require "action_cable/connection/tagged_logger_proxy"
|
|
17
|
+
::ActionCable::Connection::TaggedLoggerProxy
|
|
24
18
|
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
RailsSemanticLogger::ActionCable::TaggedLoggerProxy.class_eval do
|
|
23
|
+
# Mirrors upstream #tag, including the `respond_to?(:tagged)` guard so a
|
|
24
|
+
# target logger without tagging support (e.g. when handed a non-tagged
|
|
25
|
+
# ActiveRecord::Base.logger by the worker pool) simply yields. Diverges in
|
|
26
|
+
# one place: upstream reads the already-applied tags via
|
|
27
|
+
# `logger.formatter.current_tags` (ActiveSupport::TaggedLogging), but
|
|
28
|
+
# Semantic Logger exposes them via `#tags`, so resolve from whichever the
|
|
29
|
+
# target logger supports. See #220.
|
|
30
|
+
def tag(logger, &)
|
|
31
|
+
if logger.respond_to?(:tagged)
|
|
32
|
+
current_tags = tags - applied_tags_for(logger)
|
|
33
|
+
logger.tagged(*current_tags, &)
|
|
34
|
+
else
|
|
35
|
+
yield
|
|
36
|
+
end
|
|
37
|
+
end
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
# Upstream defines the severity methods with a single-arg signature
|
|
40
|
+
# (`message = nil`), which discards Semantic Logger's richer payload and
|
|
41
|
+
# exception arguments and raises ArgumentError when they are supplied.
|
|
42
|
+
# Redefine them to forward the full Semantic Logger signature down to the
|
|
43
|
+
# wrapped logger, while still applying the connection's tags. See #220.
|
|
44
|
+
%i[debug info warn error fatal unknown].each do |severity|
|
|
45
|
+
define_method(severity) do |message = nil, payload = nil, exception = nil, &block|
|
|
46
|
+
tag(@logger) { forward(severity, message, payload, exception, &block) }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# Only forward the extra payload/exception arguments when the wrapped logger's
|
|
53
|
+
# method can accept them. A standard Ruby Logger (e.g. the one wrapped by
|
|
54
|
+
# ActionCable::Connection::TestCase) only accepts a single `progname` argument
|
|
55
|
+
# and raises ArgumentError given more, so fall back to the single-arg call. See #317.
|
|
56
|
+
def forward(severity, message, payload, exception, &)
|
|
57
|
+
if extended_signature?(@logger, severity)
|
|
58
|
+
@logger.public_send(severity, message, payload, exception, &)
|
|
59
|
+
else
|
|
60
|
+
@logger.public_send(severity, message, &)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def extended_signature?(logger, severity)
|
|
65
|
+
params = logger.method(severity).parameters
|
|
66
|
+
params.any? { |type, _| type == :rest } || params.count { |type, _| %i[req opt].include?(type) } >= 3
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Tags already applied to the target logger, so they are not duplicated.
|
|
70
|
+
# Semantic Logger exposes them via `#tags`; ActiveSupport::TaggedLogging
|
|
71
|
+
# via `formatter.current_tags`. Fall back to none when neither is present.
|
|
72
|
+
def applied_tags_for(logger)
|
|
73
|
+
if logger.respond_to?(:tags)
|
|
74
|
+
Array(logger.tags)
|
|
75
|
+
elsif logger.respond_to?(:formatter) && logger.formatter.respond_to?(:current_tags)
|
|
76
|
+
logger.formatter.current_tags
|
|
77
|
+
else
|
|
78
|
+
[]
|
|
51
79
|
end
|
|
52
80
|
end
|
|
53
81
|
end
|
|
@@ -181,7 +181,7 @@ module RailsSemanticLogger
|
|
|
181
181
|
# The method names the context in which the appender is created; the destination
|
|
182
182
|
# is an ordinary `SemanticLogger.add_appender` argument. Use `add` for an
|
|
183
183
|
# appender that is always created, `add_server` for one created only when serving
|
|
184
|
-
# requests (`rails server`,
|
|
184
|
+
# requests (`rails server`, Sidekiq in server mode; defaults to
|
|
185
185
|
# `$stdout`), and `add_console` for one created only inside a `rails console`
|
|
186
186
|
# session (defaults to `$stderr`). Any appender works in any context, so a
|
|
187
187
|
# context may declare several (e.g. a server-only stdout and file appender).
|
|
@@ -256,14 +256,56 @@ module RailsSemanticLogger
|
|
|
256
256
|
@add_file_appender = value
|
|
257
257
|
end
|
|
258
258
|
|
|
259
|
+
# Emit the deprecation warnings recorded by the deprecated appender option
|
|
260
|
+
# setters, and warn immediately from any later call. Called by the engine once
|
|
261
|
+
# Rails has applied the application's deprecation configuration.
|
|
262
|
+
#
|
|
263
|
+
# The deprecated options are documented to be set in `config/application.rb` or
|
|
264
|
+
# `config/environments/*.rb`, which Rails reads in `load_environment_config`,
|
|
265
|
+
# long before `active_support.deprecation_behavior` applies
|
|
266
|
+
# `config.active_support.report_deprecations`, `config.active_support.deprecation`,
|
|
267
|
+
# and any per-deprecator settings. Warning from the setter itself would therefore
|
|
268
|
+
# land in a window where nothing the application configures can reach it. The
|
|
269
|
+
# setters record instead, and this flushes once the settings are in place.
|
|
270
|
+
#
|
|
271
|
+
# Each option is reported once, attributed to the first place it was set, so an
|
|
272
|
+
# application setting several deprecated options gets one warning per option
|
|
273
|
+
# rather than one per assignment.
|
|
274
|
+
def flush_deprecations!
|
|
275
|
+
@deprecations_flushed = true
|
|
276
|
+
pending = pending_deprecations
|
|
277
|
+
@pending_deprecations = {}
|
|
278
|
+
pending.each_value { |message, callstack| RailsSemanticLogger.deprecator.warn(message, callstack) }
|
|
279
|
+
nil
|
|
280
|
+
end
|
|
281
|
+
|
|
259
282
|
private
|
|
260
283
|
|
|
261
284
|
def deprecate_appender_option(option, via: "appenders.add(...)")
|
|
262
|
-
|
|
285
|
+
message =
|
|
263
286
|
"`config.rails_semantic_logger.#{option}=` is deprecated and will be removed in a future release. " \
|
|
264
287
|
"Declare the destination and formatting directly instead, via " \
|
|
265
288
|
"`config.rails_semantic_logger.appenders { |appenders| #{via} }`."
|
|
266
|
-
|
|
289
|
+
|
|
290
|
+
# Skip this method and the setter that called it, so the warning is attributed
|
|
291
|
+
# to the application code that set the option, whether it is emitted now or
|
|
292
|
+
# flushed later by #flush_deprecations!.
|
|
293
|
+
callstack = caller_locations(2)
|
|
294
|
+
|
|
295
|
+
return RailsSemanticLogger.deprecator.warn(message, callstack) if deprecations_flushed?
|
|
296
|
+
|
|
297
|
+
pending_deprecations[option] ||= [message, callstack]
|
|
298
|
+
nil
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Deprecations recorded before Rails applied its deprecation configuration,
|
|
302
|
+
# keyed by option so that each is reported only once. See #flush_deprecations!.
|
|
303
|
+
def pending_deprecations
|
|
304
|
+
@pending_deprecations ||= {}
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def deprecations_flushed?
|
|
308
|
+
defined?(@deprecations_flushed) && @deprecations_flushed
|
|
267
309
|
end
|
|
268
310
|
|
|
269
311
|
# Warn when an init-time setting is changed after the logger and its
|
|
@@ -4,38 +4,21 @@ module RailsSemanticLogger
|
|
|
4
4
|
# Prevent exception logging during standard error handling since the Job Logger below already logs the exception.
|
|
5
5
|
# Logs the remaining Sidekiq context at :info (matching upstream Sidekiq's default handler) rather than :warn,
|
|
6
6
|
# since the exception itself is already logged at :error by the Job Logger.
|
|
7
|
+
# Sidekiq 7.1.6+ calls error handlers with a third config argument; earlier 7.x versions pass only two.
|
|
7
8
|
ERROR_HANDLER =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
logger = klass ? SemanticLogger[klass] : ::Sidekiq.logger
|
|
15
|
-
ctx[:context] ? logger.info(ctx[:context], ctx) : logger.info(ctx)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
else
|
|
19
|
-
lambda do |_ex, ctx, _default_configuration|
|
|
20
|
-
unless ctx.empty?
|
|
21
|
-
job_hash = ctx[:job] || {}
|
|
22
|
-
klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"]
|
|
23
|
-
logger = klass ? SemanticLogger[klass] : ::Sidekiq.logger
|
|
24
|
-
ctx[:context] ? logger.info(ctx[:context], ctx) : logger.info(ctx)
|
|
25
|
-
end
|
|
9
|
+
lambda do |_ex, ctx, _config = nil|
|
|
10
|
+
unless ctx.empty?
|
|
11
|
+
job_hash = ctx[:job] || {}
|
|
12
|
+
klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"]
|
|
13
|
+
logger = klass ? SemanticLogger[klass] : ::Sidekiq.logger
|
|
14
|
+
ctx[:context] ? logger.info(ctx[:context], ctx) : logger.info(ctx)
|
|
26
15
|
end
|
|
27
16
|
end
|
|
28
17
|
|
|
29
|
-
# Returns the default
|
|
30
|
-
# Returns [nil] when the default
|
|
18
|
+
# Returns the default error handler after removing it from the supplied list.
|
|
19
|
+
# Returns [nil] when the default handler was not present.
|
|
31
20
|
def self.delete_default_error_handler(error_handlers)
|
|
32
|
-
|
|
33
|
-
return error_handlers.delete(::Sidekiq::DEFAULT_ERROR_HANDLER) if defined?(::Sidekiq::DEFAULT_ERROR_HANDLER)
|
|
34
|
-
|
|
35
|
-
return unless defined?(::Sidekiq::ExceptionHandler)
|
|
36
|
-
|
|
37
|
-
existing = error_handlers.find { |handler| handler.is_a?(::Sidekiq::ExceptionHandler::Logger) }
|
|
38
|
-
error_handlers.delete(existing) if existing
|
|
21
|
+
error_handlers.delete(::Sidekiq::Config::ERROR_HANDLER)
|
|
39
22
|
end
|
|
40
23
|
end
|
|
41
24
|
end
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
module RailsSemanticLogger
|
|
2
2
|
module Sidekiq
|
|
3
3
|
class JobLogger
|
|
4
|
+
# Job attributes copied into the logging context, matching Sidekiq's own defaults.
|
|
5
|
+
# Sidekiq 8 makes this configurable via `config[:logged_job_attributes]`.
|
|
6
|
+
DEFAULT_LOGGED_JOB_ATTRIBUTES = %w[bid tags].freeze
|
|
7
|
+
|
|
4
8
|
class << self
|
|
5
9
|
attr_writer :perform_messages
|
|
6
10
|
|
|
@@ -9,8 +13,9 @@ module RailsSemanticLogger
|
|
|
9
13
|
end
|
|
10
14
|
end
|
|
11
15
|
|
|
12
|
-
# Sidekiq
|
|
13
|
-
def initialize(
|
|
16
|
+
# Sidekiq 7 passes its logger, whereas Sidekiq 8 passes its config.
|
|
17
|
+
def initialize(arg = nil)
|
|
18
|
+
@config = arg if arg.respond_to?(:[])
|
|
14
19
|
end
|
|
15
20
|
|
|
16
21
|
def call(item, queue, &block)
|
|
@@ -56,17 +61,24 @@ module RailsSemanticLogger
|
|
|
56
61
|
private
|
|
57
62
|
|
|
58
63
|
def perform_messages_enabled?
|
|
64
|
+
return false if @config && @config[:skip_default_job_logging]
|
|
65
|
+
|
|
59
66
|
self.class.perform_messages != false
|
|
60
67
|
end
|
|
61
68
|
|
|
62
69
|
def job_hash_context(job_hash)
|
|
63
|
-
h
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
h = {jid: job_hash["jid"], class: job_hash["wrapped"] || job_hash["class"]}
|
|
71
|
+
logged_job_attributes.each do |attr|
|
|
72
|
+
h[attr.to_sym] = job_hash[attr] if job_hash.key?(attr)
|
|
73
|
+
end
|
|
66
74
|
h[:queue] = job_hash["queue"] if job_hash["queue"]
|
|
67
75
|
h
|
|
68
76
|
end
|
|
69
77
|
|
|
78
|
+
def logged_job_attributes
|
|
79
|
+
(@config && @config[:logged_job_attributes]) || DEFAULT_LOGGED_JOB_ATTRIBUTES
|
|
80
|
+
end
|
|
81
|
+
|
|
70
82
|
def job_latency_ms(job)
|
|
71
83
|
return unless job && job["enqueued_at"]
|
|
72
84
|
|
|
@@ -54,7 +54,11 @@ module RailsSemanticLogger
|
|
|
54
54
|
elsif event.payload[:other_adapter]
|
|
55
55
|
log_event(event, :debug, "Enqueued recurring task outside Solid Queue", **attributes)
|
|
56
56
|
else
|
|
57
|
-
action = event.payload[:skipped].present?
|
|
57
|
+
action = if event.payload[:skipped].present?
|
|
58
|
+
"Skipped recurring task – already dispatched"
|
|
59
|
+
else
|
|
60
|
+
"Enqueued recurring task"
|
|
61
|
+
end
|
|
58
62
|
log_event(event, :debug, action, **attributes)
|
|
59
63
|
end
|
|
60
64
|
end
|
|
@@ -116,7 +116,7 @@ module RailsSemanticLogger
|
|
|
116
116
|
|
|
117
117
|
# Swap an existing subscriber with a new one
|
|
118
118
|
def self.swap_subscriber(old_class, new_class, notifier)
|
|
119
|
-
subscribers = ActiveSupport::LogSubscriber.subscribers.
|
|
119
|
+
subscribers = ActiveSupport::LogSubscriber.subscribers.grep(old_class)
|
|
120
120
|
subscribers.each { |subscriber| unattach(subscriber) }
|
|
121
121
|
|
|
122
122
|
new_class.attach_to(notifier)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_semantic_logger
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Reid Morrison
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - ">="
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '5.
|
|
46
|
+
version: '5.1'
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '5.
|
|
53
|
+
version: '5.1'
|
|
54
54
|
executables: []
|
|
55
55
|
extensions: []
|
|
56
56
|
extra_rdoc_files: []
|
|
@@ -76,7 +76,6 @@ files:
|
|
|
76
76
|
- lib/rails_semantic_logger/extensions/active_support/tagged_logging.rb
|
|
77
77
|
- lib/rails_semantic_logger/extensions/mongoid/config.rb
|
|
78
78
|
- lib/rails_semantic_logger/extensions/rails/server.rb
|
|
79
|
-
- lib/rails_semantic_logger/extensions/sidekiq/sidekiq.rb
|
|
80
79
|
- lib/rails_semantic_logger/options.rb
|
|
81
80
|
- lib/rails_semantic_logger/rack/logger.rb
|
|
82
81
|
- lib/rails_semantic_logger/sidekiq/defaults.rb
|
|
@@ -84,13 +83,14 @@ files:
|
|
|
84
83
|
- lib/rails_semantic_logger/sidekiq/loggable.rb
|
|
85
84
|
- lib/rails_semantic_logger/solid_queue/log_subscriber.rb
|
|
86
85
|
- lib/rails_semantic_logger/version.rb
|
|
87
|
-
homepage: https://logger.
|
|
86
|
+
homepage: https://logger.reidmorrison.com
|
|
88
87
|
licenses:
|
|
89
88
|
- Apache-2.0
|
|
90
89
|
metadata:
|
|
91
90
|
bug_tracker_uri: https://github.com/reidmorrison/rails_semantic_logger/issues
|
|
92
|
-
documentation_uri: https://logger.
|
|
93
|
-
source_code_uri: https://github.com/reidmorrison/rails_semantic_logger/tree/v5.
|
|
91
|
+
documentation_uri: https://logger.reidmorrison.com
|
|
92
|
+
source_code_uri: https://github.com/reidmorrison/rails_semantic_logger/tree/v5.2.0
|
|
93
|
+
changelog_uri: https://github.com/reidmorrison/rails_semantic_logger/blob/main/CHANGELOG.md
|
|
94
94
|
rubygems_mfa_required: 'true'
|
|
95
95
|
rdoc_options: []
|
|
96
96
|
require_paths:
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# Sidekiq patches
|
|
2
|
-
if Sidekiq::VERSION.to_i == 4
|
|
3
|
-
require "sidekiq/logging"
|
|
4
|
-
require "sidekiq/middleware/server/logging"
|
|
5
|
-
require "sidekiq/processor"
|
|
6
|
-
elsif Sidekiq::VERSION.to_i == 5
|
|
7
|
-
require "sidekiq/logging"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
module Sidekiq
|
|
11
|
-
# Sidekiq v4 & v5
|
|
12
|
-
if defined?(::Sidekiq::Logging)
|
|
13
|
-
# Replace Sidekiq logging context
|
|
14
|
-
module Logging
|
|
15
|
-
def self.with_context(msg, &)
|
|
16
|
-
SemanticLogger.tagged(msg, &)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def self.job_hash_context(job_hash)
|
|
20
|
-
h = {jid: job_hash["jid"], class: job_hash["wrapped"] || job_hash["class"]}
|
|
21
|
-
h[:bid] = job_hash["bid"] if job_hash["bid"]
|
|
22
|
-
h[:queue] = job_hash["queue"] if job_hash["queue"]
|
|
23
|
-
h
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Sidekiq v4
|
|
29
|
-
if defined?(::Sidekiq::Middleware::Server::Logging)
|
|
30
|
-
# Convert string to machine readable format
|
|
31
|
-
class Processor
|
|
32
|
-
def log_context(job_hash)
|
|
33
|
-
h = {jid: job_hash["jid"], class: job_hash["wrapped"] || job_hash["class"]}
|
|
34
|
-
h[:bid] = job_hash["bid"] if job_hash["bid"]
|
|
35
|
-
h[:queue] = job_hash["queue"] if job_hash["queue"]
|
|
36
|
-
h
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Let Semantic Logger handle duration logging
|
|
41
|
-
module Middleware
|
|
42
|
-
module Server
|
|
43
|
-
class Logging
|
|
44
|
-
# rubocop:disable Style/ExplicitBlockArgument
|
|
45
|
-
def call(worker, item, queue)
|
|
46
|
-
SemanticLogger.tagged(queue: queue) do
|
|
47
|
-
if perform_messages_enabled?
|
|
48
|
-
worker.logger.info(
|
|
49
|
-
"Start #perform",
|
|
50
|
-
metric: "sidekiq.queue.latency",
|
|
51
|
-
metric_amount: job_latency_ms(item)
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
worker.logger.measure_info(
|
|
55
|
-
"Completed #perform",
|
|
56
|
-
on_exception_level: :error,
|
|
57
|
-
log_exception: :full,
|
|
58
|
-
metric: "sidekiq.job.perform"
|
|
59
|
-
) { yield }
|
|
60
|
-
else
|
|
61
|
-
yield
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def perform_messages_enabled?
|
|
67
|
-
RailsSemanticLogger::Sidekiq::JobLogger.perform_messages != false
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def job_latency_ms(job)
|
|
71
|
-
return unless job && job["enqueued_at"]
|
|
72
|
-
|
|
73
|
-
enqueued_at = job["enqueued_at"]
|
|
74
|
-
if enqueued_at.is_a?(Float)
|
|
75
|
-
# Sidekiq <= 7: seconds since epoch
|
|
76
|
-
(Time.now.to_f - enqueued_at) * 1000
|
|
77
|
-
else
|
|
78
|
-
# Sidekiq 8+: milliseconds since epoch
|
|
79
|
-
now = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
|
|
80
|
-
now - enqueued_at
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|