# This script calculates the minimum, maximum and 95th percentile of methods
# called by more than 10% of all Rails actions taking place in the past 24
# hours. The idea of this script is to find commonly used slow methods.

require_relative 'config'

rows = CLIENT.query(%q{
SELECT percentile("duration", 95)
FROM "rails_method_calls"
WHERE time > now() - 24h
AND "action" =~ /.+/
GROUP BY "action", "method";
})

actions_per_method = Hash.new do |hash, key|
  hash[key] = []
end

methods_per_action = Hash.new do |hash, key|
  hash[key] = {}
end

rows.each do |row|
  action = row['tags']['action']
  method = row['tags']['method']
  time   = row['values'][0]['percentile']

  actions_per_method[method] << action
  methods_per_action[action][method] = time
end

total_actions = methods_per_action.length
rows          = []

actions_per_method.each do |method, actions|
  percent = (actions.length.to_f / total_actions) * 100.0

  if percent >= 10
    timings = actions.map do |action|
      methods_per_action[action][method]
    end

    timings = timings.sort
    average = timings.inject(:+) / timings.length
    min     = timings[0]
    max     = timings[-1]

    next if average < 100

    rows << [method, actions.length, average.round(2), min.round(2), max.round(2)]
  end
end

longest = rows.map { |row| row[0].length }.sort.last

headers = [
  'Method'.ljust(longest, ' '),
  'Actions',
  '95th Percentile',
  'Minimum',
  'Maximum'
]

puts headers.join('  ')

rows.sort { |a, b| b[2] <=> a[2] }.each do |columns|
  cells = columns.map.with_index do |col, index|
    padding = headers[index].length

    col.to_s.ljust(padding, ' ')
  end

  puts cells.join('  ')
end
