Skip to content

Commit 1f8bcf0

Browse files
committed
Merge branch 'master' into metrics
2 parents 4697c01 + 6e1291f commit 1f8bcf0

File tree

15 files changed

+212
-208
lines changed

15 files changed

+212
-208
lines changed

Diff for: .github/FUNDING.yml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# These are supported funding model platforms
2+
3+
github: reidmorrison

Diff for: .github/workflows/ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ jobs:
3131

3232
- rails: "7.1"
3333
ruby: "3.1"
34+
- rails: "7.1b"
35+
ruby: "3.1"
3436
- rails: "7.1.1"
3537
ruby: "3.2"
3638
- rails: "7.1"

Diff for: Appraisals

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ appraise "rails_7.1" do
3434
gem "sqlite3", "~> 1.4"
3535
end
3636

37+
appraise "rails_7.1b" do
38+
gem "rails", "~> 7.1.0"
39+
gem "sidekiq", "~> 7.3.0"
40+
gem "sqlite3", "~> 1.4"
41+
end
42+
3743
appraise "rails_7.2" do
3844
gem "rails", "~> 7.2.0.beta2"
3945
gem "sidekiq", "~> 7.2.4"

Diff for: gemfiles/rails_7.1b.gemfile

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# This file was generated by Appraisal
2+
3+
source "https://rubygems.org"
4+
5+
gem "appraisal"
6+
gem "puma"
7+
gem "active_model_serializers"
8+
gem "amazing_print"
9+
gem "minitest"
10+
gem "minitest-rails"
11+
gem "rake"
12+
gem "sprockets", "< 4.0"
13+
gem "rails", "~> 7.1.0"
14+
gem "sidekiq", "~> 7.3.0"
15+
gem "sqlite3", "~> 1.4"
16+
gem "rubocop"
17+
18+
gemspec path: "../"

Diff for: lib/rails_semantic_logger.rb

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ module DelayedJob
3131
autoload :Plugin, "rails_semantic_logger/delayed_job/plugin"
3232
end
3333

34+
module Sidekiq
35+
autoload :Defaults, "rails_semantic_logger/sidekiq/defaults"
36+
autoload :JobLogger, "rails_semantic_logger/sidekiq/job_logger"
37+
autoload :Loggable, "rails_semantic_logger/sidekiq/loggable"
38+
end
39+
3440
autoload :Options, "rails_semantic_logger/options"
3541

3642
# Swap an existing subscriber with a new one

Diff for: lib/rails_semantic_logger/engine.rb

+27-8
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,31 @@ class Engine < ::Rails::Engine
108108
Resque.logger = SemanticLogger[Resque] if defined?(Resque) && Resque.respond_to?(:logger=)
109109

110110
# Replace the Sidekiq logger
111-
if defined?(Sidekiq)
112-
if Sidekiq.respond_to?(:logger=)
113-
Sidekiq.logger = SemanticLogger[Sidekiq]
114-
elsif Sidekiq::VERSION[0..1] == "7."
115-
method = Sidekiq.server? ? :configure_server : :configure_client
116-
Sidekiq.public_send(method) { |cfg| cfg.logger = SemanticLogger[Sidekiq] }
111+
if defined?(::Sidekiq)
112+
::Sidekiq.configure_client do |config|
113+
config.logger = ::SemanticLogger[::Sidekiq]
114+
end
115+
116+
::Sidekiq.configure_server do |config|
117+
config.logger = ::SemanticLogger[::Sidekiq]
118+
if config.respond_to?(:options)
119+
config.options[:job_logger] = RailsSemanticLogger::Sidekiq::JobLogger
120+
else
121+
config[:job_logger] = RailsSemanticLogger::Sidekiq::JobLogger
122+
end
123+
124+
# Add back the default console logger unless already added
125+
SemanticLogger.add_appender(io: $stdout, formatter: :color) unless SemanticLogger.appenders.console_output?
126+
127+
# Replace default error handler when present
128+
existing = RailsSemanticLogger::Sidekiq::Defaults.delete_default_error_handler(config.error_handlers)
129+
config.error_handlers << RailsSemanticLogger::Sidekiq::Defaults::ERROR_HANDLER if existing
130+
end
131+
132+
if defined?(::Sidekiq::Job) && (::Sidekiq::VERSION.to_i != 5)
133+
::Sidekiq::Job.singleton_class.prepend(RailsSemanticLogger::Sidekiq::Loggable)
134+
else
135+
::Sidekiq::Worker.singleton_class.prepend(RailsSemanticLogger::Sidekiq::Loggable)
117136
end
118137
end
119138

@@ -154,15 +173,15 @@ class Engine < ::Rails::Engine
154173

155174
if config.rails_semantic_logger.semantic
156175
# Active Job
157-
if defined?(::ActiveJob) && defined?(::ActiveJob::Logging::LogSubscriber)
176+
if defined?(::ActiveJob::Logging::LogSubscriber)
158177
RailsSemanticLogger.swap_subscriber(
159178
::ActiveJob::Logging::LogSubscriber,
160179
RailsSemanticLogger::ActiveJob::LogSubscriber,
161180
:active_job
162181
)
163182
end
164183

165-
if defined?(::ActiveJob) && defined?(::ActiveJob::LogSubscriber)
184+
if defined?(::ActiveJob::LogSubscriber)
166185
RailsSemanticLogger.swap_subscriber(
167186
::ActiveJob::LogSubscriber,
168187
RailsSemanticLogger::ActiveJob::LogSubscriber,

Diff for: lib/rails_semantic_logger/extensions/sidekiq/sidekiq.rb

+3-175
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,14 @@
11
# Sidekiq patches
2-
#
3-
# To re-enable stdout logging for sidekiq server processes, add the following snippet to config/initializers/sidekiq.rb:
4-
# Sidekiq.configure_server do |config|
5-
# SemanticLogger.add_appender(io: $stdout, level: :debug, formatter: :color)
6-
# end
72
if Sidekiq::VERSION.to_i == 4
8-
require "sidekiq/exception_handler"
93
require "sidekiq/logging"
104
require "sidekiq/middleware/server/logging"
115
require "sidekiq/processor"
12-
require "sidekiq/worker"
136
elsif Sidekiq::VERSION.to_i == 5
14-
require "sidekiq/exception_handler"
15-
require "sidekiq/job_logger"
167
require "sidekiq/logging"
17-
require "sidekiq/worker"
18-
elsif Sidekiq::VERSION.to_i == 6 && Sidekiq::VERSION.to_f < 6.5
19-
require "sidekiq/exception_handler"
20-
require "sidekiq/job_logger"
21-
require "sidekiq/worker"
22-
elsif Sidekiq::VERSION.to_i == 6
23-
require "sidekiq/job_logger"
24-
require "sidekiq/worker"
25-
else
26-
require "sidekiq/config"
27-
require "sidekiq/job_logger"
28-
require "sidekiq/job"
298
end
309

3110
module Sidekiq
32-
# Sidekiq > v4
33-
if defined?(::Sidekiq::JobLogger)
34-
# Let Semantic Logger handle duration logging
35-
class JobLogger
36-
def call(item, queue, &block)
37-
klass = item["wrapped"] || item["class"]
38-
logger = klass ? SemanticLogger[klass] : Sidekiq.logger
39-
40-
SemanticLogger.tagged(queue: queue) do
41-
# Latency is the time between when the job was enqueued and when it started executing.
42-
logger.info(
43-
"Start #perform",
44-
metric: "sidekiq.queue.latency",
45-
metric_amount: job_latency_ms(item)
46-
)
47-
48-
# Measure the duration of running the job
49-
logger.measure_info(
50-
"Completed #perform",
51-
on_exception_level: :error,
52-
log_exception: :full,
53-
metric: "sidekiq.job.perform",
54-
&block
55-
)
56-
end
57-
end
58-
59-
def prepare(job_hash, &block)
60-
level = job_hash["log_level"]
61-
if level
62-
SemanticLogger.silence(level) do
63-
SemanticLogger.tagged(job_hash_context(job_hash), &block)
64-
end
65-
else
66-
SemanticLogger.tagged(job_hash_context(job_hash), &block)
67-
end
68-
end
69-
70-
def job_hash_context(job_hash)
71-
h = {jid: job_hash["jid"]}
72-
h[:bid] = job_hash["bid"] if job_hash["bid"]
73-
h[:tags] = job_hash["tags"] if job_hash["tags"]
74-
h[:queue] = job_hash["queue"] if job_hash["queue"]
75-
h
76-
end
77-
78-
def job_latency_ms(job)
79-
return unless job && job["enqueued_at"]
80-
81-
(Time.now.to_f - job["enqueued_at"].to_f) * 1000
82-
end
83-
end
84-
end
85-
86-
# Sidekiq <= v6
11+
# Sidekiq v4 & v5
8712
if defined?(::Sidekiq::Logging)
8813
# Replace Sidekiq logging context
8914
module Logging
@@ -100,106 +25,8 @@ def self.job_hash_context(job_hash)
10025
end
10126
end
10227

103-
# Exception is already logged by Semantic Logger during the perform call
104-
if defined?(::Sidekiq::ExceptionHandler)
105-
# Sidekiq <= v6.5
106-
module ExceptionHandler
107-
class Logger
108-
def call(_exception, ctx)
109-
return if ctx.empty?
110-
111-
job_hash = ctx[:job] || {}
112-
klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"]
113-
logger = klass ? SemanticLogger[klass] : Sidekiq.logger
114-
ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx)
115-
end
116-
end
117-
end
118-
elsif defined?(::Sidekiq::Config)
119-
# Sidekiq >= v7
120-
class Config
121-
remove_const :ERROR_HANDLER
122-
123-
ERROR_HANDLER = ->(ex, ctx, cfg = Sidekiq.default_configuration) do
124-
unless ctx.empty?
125-
job_hash = ctx[:job] || {}
126-
klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"]
127-
logger = klass ? SemanticLogger[klass] : Sidekiq.logger
128-
ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx)
129-
end
130-
end
131-
end
132-
elsif Sidekiq.error_handlers.delete(Sidekiq::DEFAULT_ERROR_HANDLER)
133-
# Sidekiq >= 6.5
134-
# Replace default error handler if present
135-
Sidekiq.error_handlers << ->(ex, ctx) do
136-
unless ctx.empty?
137-
job_hash = ctx[:job] || {}
138-
klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"]
139-
logger = klass ? SemanticLogger[klass] : Sidekiq.logger
140-
ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx)
141-
end
142-
end
143-
end
144-
145-
# Logging within each worker should use its own logger
146-
case Sidekiq::VERSION.to_i
147-
when 4
148-
module Worker
149-
def self.included(base)
150-
if base.ancestors.any? { |c| c.name == "ActiveJob::Base" }
151-
raise ArgumentError, "You cannot include Sidekiq::Worker in an ActiveJob: #{base.name}"
152-
end
153-
154-
base.extend(ClassMethods)
155-
base.include(SemanticLogger::Loggable)
156-
base.class_attribute :sidekiq_options_hash
157-
base.class_attribute :sidekiq_retry_in_block
158-
base.class_attribute :sidekiq_retries_exhausted_block
159-
end
160-
end
161-
when 5
162-
module Worker
163-
def self.included(base)
164-
if base.ancestors.any? { |c| c.name == "ActiveJob::Base" }
165-
raise ArgumentError, "You cannot include Sidekiq::Worker in an ActiveJob: #{base.name}"
166-
end
167-
168-
base.extend(ClassMethods)
169-
base.include(SemanticLogger::Loggable)
170-
base.sidekiq_class_attribute :sidekiq_options_hash
171-
base.sidekiq_class_attribute :sidekiq_retry_in_block
172-
base.sidekiq_class_attribute :sidekiq_retries_exhausted_block
173-
end
174-
end
175-
when 6
176-
module Worker
177-
def self.included(base)
178-
if base.ancestors.any? { |c| c.name == "ActiveJob::Base" }
179-
raise ArgumentError, "Sidekiq::Worker cannot be included in an ActiveJob: #{base.name}"
180-
end
181-
182-
base.include(Options)
183-
base.extend(ClassMethods)
184-
base.include(SemanticLogger::Loggable)
185-
end
186-
end
187-
else
188-
module Job
189-
def self.included(base)
190-
if base.ancestors.any? { |c| c.name == "ActiveJob::Base" }
191-
raise ArgumentError, "Sidekiq::Job cannot be included in an ActiveJob: #{base.name}"
192-
end
193-
194-
base.include(Options)
195-
base.extend(ClassMethods)
196-
base.include(SemanticLogger::Loggable)
197-
end
198-
end
199-
end
200-
28+
# Sidekiq v4
20129
if defined?(::Sidekiq::Middleware::Server::Logging)
202-
# Sidekiq v4
20330
# Convert string to machine readable format
20431
class Processor
20532
def log_context(job_hash)
@@ -214,6 +41,7 @@ def log_context(job_hash)
21441
module Middleware
21542
module Server
21643
class Logging
44+
# rubocop:disable Style/ExplicitBlockArgument
21745
def call(worker, item, queue)
21846
SemanticLogger.tagged(queue: queue) do
21947
worker.logger.info(

Diff for: lib/rails_semantic_logger/sidekiq/defaults.rb

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module RailsSemanticLogger
2+
module Sidekiq
3+
module Defaults
4+
# Prevent exception logging during standard error handling since the Job Logger below already logs the exception.
5+
ERROR_HANDLER =
6+
if ::Sidekiq::VERSION.to_f < 7.1 ||
7+
(::Sidekiq::VERSION.to_f == 7.1 && ::Sidekiq::VERSION.split(".").last.to_i < 6)
8+
lambda do |_ex, ctx|
9+
unless ctx.empty?
10+
job_hash = ctx[:job] || {}
11+
klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"]
12+
logger = klass ? SemanticLogger[klass] : Sidekiq.logger
13+
ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx)
14+
end
15+
end
16+
else
17+
lambda do |_ex, ctx, _default_configuration|
18+
unless ctx.empty?
19+
job_hash = ctx[:job] || {}
20+
klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"]
21+
logger = klass ? SemanticLogger[klass] : Sidekiq.logger
22+
ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx)
23+
end
24+
end
25+
end
26+
27+
# Returns the default logger after removing from the supplied list.
28+
# Returns [nil] when the default logger was not present.
29+
def self.delete_default_error_handler(error_handlers)
30+
return error_handlers.delete(::Sidekiq::Config::ERROR_HANDLER) if defined?(::Sidekiq::Config::ERROR_HANDLER)
31+
return error_handlers.delete(::Sidekiq::DEFAULT_ERROR_HANDLER) if defined?(::Sidekiq::DEFAULT_ERROR_HANDLER)
32+
33+
return unless defined?(::Sidekiq::ExceptionHandler)
34+
35+
existing = error_handlers.find { |handler| handler.is_a?(::Sidekiq::ExceptionHandler::Logger) }
36+
error_handlers.delete(existing) if existing
37+
end
38+
end
39+
end
40+
end

0 commit comments

Comments
 (0)