module GoodJob class LogSubscriber < ActiveSupport::LogSubscriber def create(event) good_job = event.payload[:good_job] debug do "GoodJob created job resource with id #{good_job.id}" end end def timer_task_finished(event) exception = event.payload[:error] return unless exception error do "GoodJob error: #{exception}\n #{exception.backtrace}" end end def job_finished(event) exception = event.payload[:error] return unless exception error do "GoodJob error: #{exception}\n #{exception.backtrace}" end end def scheduler_create_pools(event) max_threads = event.payload[:max_threads] poll_interval = event.payload[:poll_interval] performer_name = event.payload[:performer_name] process_id = event.payload[:process_id] info(tags: [process_id]) do "GoodJob started scheduler with queues=#{performer_name} max_threads=#{max_threads} poll_interval=#{poll_interval}." end end def scheduler_shutdown_start(event) process_id = event.payload[:process_id] info(tags: [process_id]) do "GoodJob shutting down scheduler..." end end def scheduler_shutdown(event) process_id = event.payload[:process_id] info(tags: [process_id]) do "GoodJob scheduler is shut down." end end def scheduler_restart_pools(event) process_id = event.payload[:process_id] info(tags: [process_id]) do "GoodJob scheduler has restarted." end end def perform_job(event) good_job = event.payload[:good_job] process_id = event.payload[:process_id] thread_name = event.payload[:thread_name] info(tags: [process_id, thread_name]) do "Executed GoodJob #{good_job.id}" end end def notifier_listen(_event) info do "Notifier subscribed with LISTEN" end end def notifier_notified(event) payload = event.payload[:payload] debug do "Notifier received payload: #{payload}" end end def notifier_notify_error(event) error = event.payload[:error] error do "Notifier errored: #{error}" end end def notifier_unlisten(_event) info do "Notifier unsubscribed with UNLISTEN" end end def cleanup_preserved_jobs(event) timestamp = event.payload[:timestamp] deleted_records_count = event.payload[:deleted_records_count] info do "GoodJob deleted #{deleted_records_count} preserved #{'job'.pluralize(deleted_records_count)} finished before #{timestamp}." end end class << self def loggers @_loggers ||= [GoodJob.logger] end def logger @_logger ||= begin logger = Logger.new(StringIO.new) loggers.each do |each_logger| logger.extend(ActiveSupport::Logger.broadcast(each_logger)) end logger end end def reset_logger @_logger = nil end end def logger GoodJob::LogSubscriber.logger end private def tag_logger(*tags, &block) tags = tags.dup.unshift("GoodJob").compact self.class.loggers.inject(block) do |inner, each_logger| if each_logger.respond_to?(:tagged) tags_for_logger = if each_logger.formatter.current_tags.include?("ActiveJob") ["ActiveJob"] + tags else tags end proc { each_logger.tagged(*tags_for_logger, &inner) } else inner end end.call end %w(info debug warn error fatal unknown).each do |level| class_eval <<-METHOD, __FILE__, __LINE__ + 1 def #{level}(progname = nil, tags: [], &block) return unless logger tag_logger(*tags) do logger.#{level}(progname, &block) end end METHOD end end end