class SidekiqUniqueJobs::Profiler


@author Mikael Henriksson <mikael@zoolutions.se>
Class MethodProfiler provides method level profiling

def self.current_timestamp

def self.current_timestamp
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
end

def self.patch(klass, methods, name) # rubocop:disable Metrics/MethodLength

rubocop:disable Metrics/MethodLength
def self.patch(klass, methods, name) # rubocop:disable Metrics/MethodLength
  patches = methods.map do |method_name|
    <<~RUBY
      unless defined?(#{method_name}__mp_unpatched)
        alias_method :#{method_name}__mp_unpatched, :#{method_name}
        def #{method_name}(*args, &blk)
          unless prof = Thread.current[:_method_profiler]
            return #{method_name}__mp_unpatched(*args, &blk)
          end
          begin
            start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
            #{method_name}__mp_unpatched(*args, &blk)
          ensure
            data = (prof[:#{name}] ||= {duration: 0.0, calls: 0})
            data[:duration] += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
            data[:calls] += 1
          end
        end
      end
    RUBY
  end.join("\n")
  klass.class_eval patches
end

def self.start

def self.start
  Thread.current[:_method_profiler] = {
    __start: current_timestamp,
  }
end

def self.stop

def self.stop
  finish = current_timestamp
  return unless (data = Thread.current[:_method_profiler])
  Thread.current[:_method_profiler] = nil
  start = data.delete(:__start)
  data[:total_duration] = finish - start
  data
end