JSON formatter fails with stack overflow on Rails 7.1 + Sidekiq 7.2
ixti opened this issue · 2 comments
ixti commented
Environment
- Ruby Version: 3.3.0
- Rails Version: 7.1.3
- Semantic Logger Version: 4.15.0
- Rails Semantic Logger Version: 4.14.0
# file: config/application.rb
config.rails_semantic_logger.format = SemanticLogger::Formatters::Json.new
Expected Behavior
- Should work just fine
Actual Behavior
- It does, but...
- Upon boot, appender catches stack-overflow exception
Root Cause
Sidekiq 7.2 logs debug info about the process with payload:
average_scheduled_poll_interval: 5,
backtrace_cleaner: #<Proc:0x00007f6994840a08 /home/ixti/.gem/ruby/3.3.0/gems/sidekiq-7.2.1/lib/sidekiq/rails.rb:44 (lambda)>,
concurrency: 5,
dead_max_jobs: 10000
... more stuff ...
reloader: #<Sidekiq::Rails::Reloader @app=Demo::Application>,
require: ".",
tag: "demo",
timeout: 25
The problematic here is :reloader
. Attempt to call as_json
on it causes stack overflow.
Workaround
We've monkey-patched Sidekiq::Rails::Reloader
in our codebase to overcome this:
# file: config/initializers/sidekiq.rb
module Sidekiq
class Rails < ::Rails::Engine
class Reloader
def as_json(...)
{ app: @app.class.name }.as_json(...)
end
end
end
end
ixti commented
Correction. Sidekiq::Rails::Reloader
is not the direct problem here. It simply holds instance variable: @app = Rails.application
. Calling Rails.application.as_json
fails with stack level to deep.
Rails extends Object
with as_json
:
class Object
def as_json(options = nil) # :nodoc:
if respond_to?(:to_hash)
to_hash.as_json(options)
else
instance_values.as_json(options)
end
end
end
Thus, if class does not implement to_hash
or as_json
, it will:
class Example
def initialize
@answer = 42
end
end
Example.new.as_json # => { "answer" => 42 }
TLDR; Sorry for the noise. This has nothing to do with SemanticLogger - will open a PR to Sidekiq.
ixti commented
See: sidekiq/sidekiq#6198