module RequestLogAnalyzer::Tracker # Catagorize requests. # 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 Category < RequestLogAnalyzer::Tracker::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 = STDOUT, report_width = 80, color = false) if options[:title] output << "\n#{options[:title]}\n" output << green(('━' * report_width), color) + "\n" end 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] adjuster = color ? 33 : 24 # justifcation calcultaion is slight different when color codes are inserterted max_cat_length = [sorted_categories.map { |c| c[0].to_s.length }.max, report_width - adjuster].min sorted_categories.each do |(cat, count)| text = "%-#{max_cat_length+1}s┃%7d hits %s" % [cat.to_s[0..max_cat_length], count, (green("(%0.01f%%)", color) % [(count.to_f / total_hits) * 100])] space_left = report_width - (max_cat_length + adjuster + 3) if space_left > 3 bar_chars = (space_left * (count.to_f / total_hits)).round output << "%-#{max_cat_length + adjuster}s %s%s" % [text, '┃', '░' * bar_chars] + "\n" else output << text + "\n" end end end end end end