lib/sidekiq/logging/shared.rb in sidekiq-logstash-1.1.0 vs lib/sidekiq/logging/shared.rb in sidekiq-logstash-1.2.0

- old
+ new

@@ -1,72 +1,124 @@ +# frozen_string_literal: true + module Sidekiq module Logging + # Shared module with all the logics used by job loggers. module Shared - ENCRYPTED = '[ENCRYPTED]'.freeze + ENCRYPTED = '[ENCRYPTED]' - def log_job(payload, started_at, exc = nil) + def log_job(job) + started_at = Time.now.utc + log_start = log_job_start(job) + Sidekiq.logger.info log_start if log_start + yield if block_given? + Sidekiq.logger.info log_job_exec(job, started_at) + rescue StandardError => e + begin + Sidekiq.logger.warn log_job_exception(job, started_at, e) + rescue StandardError => ex + log_standard_error(job, e, ex) + end + raise + end + + def log_job_start(job) + return unless Sidekiq::Logstash.configuration.job_start_log + # Skips start logs for retrying jobs + return if job['failed_at'] + + payload = setup_payload(job) + payload['job_status'] = 'started' + payload['message'] += ': started' + process_payload(payload) + end + + def log_job_exec(job, started_at) + payload = setup_payload(job) + payload['duration'] = elapsed(started_at) + + payload['message'] += ": done: #{payload['duration']} sec" + payload['job_status'] = 'done' + payload['completed_at'] = Time.now.utc + + process_payload(payload) + end + + def log_job_exception(job, started_at, exc) + payload = setup_payload(job) + payload['duration'] = elapsed(started_at) + + payload['message'] += ": fail: #{payload['duration']} sec" + payload['job_status'] = 'fail' + payload['error_message'] = exc.message + payload['error'] = exc.class + payload['error_backtrace'] = %('#{exc.backtrace.join("\n")}') + + process_payload(payload) + end + + private + + def setup_payload(job) # Create a copy of the payload using JSON # This should always be possible since Sidekiq store it in Redis - payload = JSON.parse(JSON.unparse(payload)) + payload = JSON.parse(JSON.unparse(job)) # Convert timestamps into Time instances - %w( created_at enqueued_at retried_at failed_at completed_at ).each do |key| + %w[created_at enqueued_at retried_at failed_at completed_at].each do |key| payload[key] = parse_time(payload[key]) if payload[key] end + # Sets the initial message + payload['message'] = "#{payload['class']} JID-#{payload['jid']}" + # Add process id params - payload['pid'] = ::Process.pid - payload['duration'] = elapsed(started_at) + payload['pid'] = ::Process.pid - message = "#{payload['class']} JID-#{payload['jid']}" + payload + end - if exc - payload['message'] = "#{message}: fail: #{payload['duration']} sec" - payload['job_status'] = 'fail' - payload['error_message'] = exc.message - payload['error'] = exc.class - payload['error_backtrace'] = %('#{exc.backtrace.join("\n")}') - else - payload['message'] = "#{message}: done: #{payload['duration']} sec" - payload['job_status'] = 'done' - payload['completed_at'] = Time.now.utc - end - + def process_payload(payload) # Filter sensitive parameters unless filter_args.empty? - args_filter = Sidekiq::Logging::ArgumentFilter.new(filter_args) - payload['args'] = args_filter.filter({ args: payload['args'] })[:args] + args_filter = Sidekiq::Logging::ArgumentFilter.new(filter_args) + payload['args'] = args_filter.filter(args: payload['args'])[:args] end # If encrypt is true, the last arg is encrypted so hide it - if payload['encrypt'] - payload['args'][-1] = ENCRYPTED - end + payload['args'][-1] = ENCRYPTED if payload['encrypt'] # Needs to map all args to strings for ElasticSearch compatibility payload['args'].map!(&:to_s) - # Needs to map all unique_args to strings for ElasticSearch compatibility in case sidekiq-unique-jobs is used - payload['unique_args'].map!(&:to_s) if payload['unique_args'] + # Needs to map all unique_args to strings for ElasticSearch + # compatibility in case sidekiq-unique-jobs is used + payload['unique_args']&.map!(&:to_s) if payload['retry'].is_a?(Integer) payload['max_retries'] = payload['retry'] payload['retry'] = true end payload end + def log_standard_error(job, job_exc, log_exc) + Sidekiq.logger.error 'Error logging the job execution!' + Sidekiq.logger.error "Job: #{job}" + Sidekiq.logger.error "Job Exception: #{job_exc}" + Sidekiq.logger.error "Log Exception: #{log_exc}" + end + def elapsed(start) (Time.now.utc - start).round(3) end def parse_time(timestamp) return timestamp if timestamp.is_a? Time - timestamp.is_a?(Float) ? - Time.at(timestamp).utc : - Time.parse(timestamp) - rescue + + timestamp.is_a?(Float) ? Time.at(timestamp).utc : Time.parse(timestamp) + rescue StandardError timestamp end def filter_args Sidekiq::Logstash.configuration.filter_args