module RequestLogAnalyzer::Tracker
# Catagorize requests by frequency.
# Count and analyze requests for a specific attribute
#
# Accepts the following options:
# * :line_type The line type that contains the duration field (determined by the category proc).
# * :if Proc that has to return !nil for a request to be passed to the tracker.
# * :title Title do be displayed above the report.
# * :category Proc that handles the request categorization.
# * :amount The amount of lines in the report
#
# The items in the update request hash are set during the creation of the Duration tracker.
#
# Example output:
# HTTP methods
# ----------------------------------------------------------------------
# GET | 22248 hits (46.2%) |░░░░░░░░░░░░░░░░░
# PUT | 13685 hits (28.4%) |░░░░░░░░░░░
# POST | 11662 hits (24.2%) |░░░░░░░░░
# DELETE | 512 hits (1.1%) |
class Frequency < Base
attr_reader :categories
def prepare
raise "No categorizer set up for category tracker #{self.inspect}" unless options[:category]
@categories = {}
if options[:all_categories].kind_of?(Enumerable)
options[:all_categories].each { |cat| @categories[cat] = 0 }
end
end
def update(request)
cat = options[:category].respond_to?(:call) ? options[:category].call(request) : request[options[:category]]
if !cat.nil? || options[:nils]
@categories[cat] ||= 0
@categories[cat] += 1
end
end
def report(output)
output.title(options[:title]) if options[:title]
if @categories.empty?
output << "None found.\n"
else
sorted_categories = @categories.sort { |a, b| b[1] <=> a[1] }
total_hits = sorted_categories.inject(0) { |carry, item| carry + item[1] }
sorted_categories = sorted_categories.slice(0...options[:amount]) if options[:amount]
output.table({:align => :left}, {:align => :right }, {:align => :right}, {:type => :ratio, :width => :rest}) do |rows|
sorted_categories.each do |(cat, count)|
rows << [cat, "#{count} hits", '%0.1f%%' % ((count.to_f / total_hits.to_f) * 100.0), (count.to_f / total_hits.to_f)]
end
end
end
end
end
end