diff --git a/lib/rails_semantic_logger.rb b/lib/rails_semantic_logger.rb index 2bd3b46..3a91ec6 100644 --- a/lib/rails_semantic_logger.rb +++ b/lib/rails_semantic_logger.rb @@ -32,6 +32,7 @@ module DelayedJob end module Sidekiq + autoload :Defaults, "rails_semantic_logger/sidekiq/defaults" autoload :JobLogger, "rails_semantic_logger/sidekiq/job_logger" autoload :Loggable, "rails_semantic_logger/sidekiq/loggable" end diff --git a/lib/rails_semantic_logger/engine.rb b/lib/rails_semantic_logger/engine.rb index 05d98f3..416486d 100644 --- a/lib/rails_semantic_logger/engine.rb +++ b/lib/rails_semantic_logger/engine.rb @@ -123,40 +123,9 @@ class Engine < ::Rails::Engine SemanticLogger.add_appender(io: $stdout, formatter: :color) unless SemanticLogger.appenders.console_output? - # Replace default error handler if present - # Prevent exception logging since the Job Logger already logged the exception. - # Only log the context that was not available during the job_logger call. - if defined?(::Sidekiq::ExceptionHandler) - existing = ::Sidekiq.error_handlers.find { |handler| handler.is_a?(::Sidekiq::ExceptionHandler::Logger) } - if existing && config.error_handlers.delete(existing) - config.error_handlers << ->(ex, ctx) do - unless ctx.empty? - job_hash = ctx[:job] || {} - klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"] - logger = klass ? SemanticLogger[klass] : Sidekiq.logger - ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx) - end - end - end - elsif defined?(::Sidekiq::DEFAULT_ERROR_HANDLER) && config.error_handlers.delete(::Sidekiq::DEFAULT_ERROR_HANDLER) - config.error_handlers << ->(ex, ctx) do - unless ctx.empty? - job_hash = ctx[:job] || {} - klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"] - logger = klass ? SemanticLogger[klass] : Sidekiq.logger - ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx) - end - end - elsif defined?(::Sidekiq::Config::ERROR_HANDLER) && config.error_handlers.delete(::Sidekiq::Config::ERROR_HANDLER) - config.error_handlers << ->(ex, ctx, _default_configuration) do - unless ctx.empty? - job_hash = ctx[:job] || {} - klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"] - logger = klass ? SemanticLogger[klass] : Sidekiq.logger - ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx) - end - end - end + # Replace default error handler when present + existing = RailsSemanticLogger::Sidekiq::Defaults.delete_default_error_handler(config.error_handlers) + config.error_handlers << RailsSemanticLogger::Sidekiq::Defaults::ERROR_HANDLER if existing end if defined?(::Sidekiq::Job) diff --git a/lib/rails_semantic_logger/sidekiq/defaults.rb b/lib/rails_semantic_logger/sidekiq/defaults.rb new file mode 100644 index 0000000..d636f30 --- /dev/null +++ b/lib/rails_semantic_logger/sidekiq/defaults.rb @@ -0,0 +1,37 @@ +module RailsSemanticLogger + module Sidekiq + module Defaults + # Prevent exception logging during standard error handling since the Job Logger below already logs the exception. + if ::Sidekiq::VERSION.to_f < 7.2 + ERROR_HANDLER = ->(ex, ctx) do + unless ctx.empty? + job_hash = ctx[:job] || {} + klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"] + logger = klass ? SemanticLogger[klass] : Sidekiq.logger + ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx) + end + end + else + ERROR_HANDLER = ->(ex, ctx, _default_configuration) do + unless ctx.empty? + job_hash = ctx[:job] || {} + klass = job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"] + logger = klass ? SemanticLogger[klass] : Sidekiq.logger + ctx[:context] ? logger.warn(ctx[:context], ctx) : logger.warn(ctx) + end + end + end + + # Returns the default logger after removing from the supplied list. + # Returns [nil] when the default logger was not present. + def self.delete_default_error_handler(error_handlers) + return error_handlers.delete(::Sidekiq::Config::ERROR_HANDLER) if defined?(::Sidekiq::Config::ERROR_HANDLER) + return error_handlers.delete(::Sidekiq::DEFAULT_ERROR_HANDLER) if defined?(::Sidekiq::DEFAULT_ERROR_HANDLER) + + return unless defined?(::Sidekiq::ExceptionHandler) + existing = error_handlers.find { |handler| handler.is_a?(::Sidekiq::ExceptionHandler::Logger) } + return config.error_handlers.delete(existing) if existing + end + end + end +end diff --git a/test/dummy/config/initializers/sidekiq.rb b/test/dummy/config/initializers/sidekiq.rb new file mode 100644 index 0000000..9a6e79a --- /dev/null +++ b/test/dummy/config/initializers/sidekiq.rb @@ -0,0 +1,7 @@ +# In tests we force Sidekiq into thinking it is running as a server, +# so it creates a stdout logger. Remove it here: +Rails.application.config.after_initialize do + if Rails.env.test? + SemanticLogger.appenders.delete_if { |appender| appender.is_a?(SemanticLogger::Appender::IO) } + end +end