Thor, Sake, and Rails Log Stats

Of course, converting the Rake task from my previous post to a Sake task was simple.

namespace :log do

  desc 'Show average reqs/sec of provided log file. Usage: sake log:stats FILE=/path/to/file'
  task :stats do |task, args|
    file = ENV["FILE"]
    puts "Parsing #{file}..."

    # Log Analyzing Task
    log = File.open(file)

    reqs_per_sec = []

    log.each_line do |line|
      parts = line.scan(/(\d+)(\sreqs\/sec)/)
      # There should only be one match per line... right?
      reqs_per_sec << parts[0][0].to_i unless parts[0].nil?
    end

    # Find the mode
    nums = {}
    reqs_per_sec.each do |r|
      unless nums.include?(r)
        nums[r] ||= 0
        nums[r] += 1
      end
    end
    mode = nums.sort {|a, b| a[1] <=> b[1] }.last[0]

    sum = reqs_per_sec.inject {|sum, x| sum + x }

    puts sprintf("%-7s %d reqs/sec", 'Mean:', sum/reqs_per_sec.size)
    puts sprintf("%-7s %d reqs/sec", 'Median:', reqs_per_sec[(reqs_per_sec.size/2).to_i])
    puts sprintf("%-7s %d reqs/sec", 'Mode:', mode)
  end
end

So...

> sake -i http://pastie.org/212542.txt
> sake log:reqs_stats FILE=/path/to/file
Parsing production.log...
Mean:   55 reqs/sec
Median: 90 reqs/sec
Mode:   110 reqs/sec

Stand and Face the Might of Thor!

Thor purports to replace Rake and Sake, at least for system scripting. It can do the same things Rake and Sake can do, but it does them while actually looking like (mostly) plain Ruby, and, on top of that, it makes dealing with command line options and argument super freakin' simple. I'll admit, I was on the fence about Thor until actually writing this script:

# module: rlog

class RLog < Thor

  desc 'stats FILE', 'view reqs/sec stats from a Rails log'
  def stats(file)
    puts "Parsing #{file}..."

    reqs_per_sec = parse_log_file(file)

    puts sprintf("%-7s %d reqs/sec", 'Mean:', mean(reqs_per_sec))
    puts sprintf("%-7s %d reqs/sec", 'Median:', median(reqs_per_sec))
    puts sprintf("%-7s %d reqs/sec", 'Mode:', mode(reqs_per_sec))
  end

  private

    def parse_log_file(file)
      # Log Analyzing Task
      log = File.open(file)

      reqs_per_sec = []

      log.each_line do |line|
        parts = line.scan(/(\d+)(\sreqs\/sec)/)
        # There should only be one match per line... right?
        reqs_per_sec << parts[0][0].to_i unless parts[0].nil?
      end

      reqs_per_sec
    end

    def mean(reqs_per_sec)
      sum = reqs_per_sec.inject {|sum, x| sum + x }
      sum/reqs_per_sec.size
    end

    def median(reqs_per_sec)
      sum = reqs_per_sec.inject {|sum, x| sum + x }
      reqs_per_sec[(reqs_per_sec.size/2).to_i]
    end

    def mode(reqs_per_sec)
      # Find the mode
      nums = {}
      reqs_per_sec.each do |r|
        unless nums.include?(r)
          nums[r] ||= 0
          nums[r] += 1
        end
      end
      nums.sort {|a, b| a[1] <=> b[1] }.last[0]
    end

end

I am going to assume you haven't installed Thor. If you have, you know which step to skip:

> sudo gem install thor
> thor install http://pastie.org/212189.txt
> thor list
Tasks
-----
r_log:stats FILE   view reqs/sec stats from a Rails log
> thor r_log:stats /path/to/file
Parsing production.log...
Mean:   55 reqs/sec
Median: 90 reqs/sec
Mode:   110 reqs/sec

And verily, thine hour of judgment is at hand!

Thor is cool. There's no doubt about it. It does indeed make dealing with options in Ruby scripts trivial (although I obviously haven't really used that yet), and it's nice that it is less DSL and more plain Ruby. I don't understand why Thor hasn't gotten the same amount of love that Sake got when it was debuted. It makes me wonder if people love the Rake DSL more than they love Ruby. Sinners! Blasphemers! Hipsters! If I can make Thor do anything I would want to do with Sake, or, even better, anything I would want to do with any old bash script, then I am sure I will be using Thor quite often. You should, too.

Go checkout wycats initial post about Thor. Also, go look at the Thor source on GitHub. Write a couple Thor scripts and tell me what you think. Or, tell wycats what you think.

Art Thou Mad?

Where was I? Oh, right, the Rails log stat scripts. Yup. There they are. What do you think? Seriously, what could be added (that it would make sense to add to a Rake/Sake/Thor script)? What have I done horribly wrong? How poor is my Rubyisms knowledge? Tell me!

I'll leave you with the most common Thor (from Marvel Comics, if you hadn't gotten it by now) phrase:

I Say Thee Nay!

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.

Powered by Drupal - Original Theme by Artinet - Theme Enhancements by Me