Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Parse a Rails log file and send metrics to stathat
#!/usr/bin/env ruby
require 'net/http/persistent'
require 'uri'
require 'thread'
USAGE = <<EOS
Parse a Rails log file and send metrics to stathat
export EMAIL=email
export PREFIX=prefix
tail -f logfile | #{$0}
- logfile is the path to the Rails logfile (example: log/production.log)
- email is the email of the stathat account (mandatory)
- prefix is the prefix for the stats name (optional, blank by default)
WARNING: need ruby 1.9 and the net-http-persistent gem
EOS
$verbose = false
$exit = false
$uri = URI "http://api.stathat.com/ez"
$queue = Queue.new
$email = ENV['EMAIL']
$prefix = ENV['PREFIX']
if %w(-h --help).include?(ARGV[0]) || $email.nil?
puts USAGE
exit 0
end
module REGEXP
PROCESSING = /^ Processing by (?<controller>\w+)#(?<action>\w+) as (?<format>\w+)$/
COMPLETED = /^Completed (?<code>\d+) .* in (?<time>\d+)/
MONGODB = /^MONGODB/
RENDERED = /^Rendered (?<template>\w+)/
STARTED = /^Started (?<verb>\w+) "(?<url>.+)" for (?<ip>[0-9.]+)/
end
def count(stat, value)
stat = "#{$prefix} - #{stat}" if $prefix
$queue << [stat, value]
end
def incr(stat)
count stat, 1
end
def processing(line)
data = line.match(REGEXP::PROCESSING)
return unless data
incr data['controller']
incr "#{data['controller']}##{data['action']}"
incr "as #{data['format']}"
end
def completed(line)
data = line.match(REGEXP::COMPLETED)
return unless data
incr "Code #{data['code']}"
count "Completed in", data['time'].to_i
end
def mongodb(line)
incr "MongoDB" if line =~ REGEXP::MONGODB
end
def rendered(line)
data = line.match(REGEXP::RENDERED)
return unless data
incr "Rendering total"
incr "Rendering #{data['template']}"
end
def started(line)
data = line.match(REGEXP::STARTED)
return unless data
incr "Requests"
incr "#{data['verb']} requests"
incr "URL #{data['url']}"
incr "IP #{data['ip']}"
end
$threads = []
8.times do
$threads << Thread.new do
http = Net::HTTP::Persistent.new $0
until $exit
stat, count = *$queue.pop
post = Net::HTTP::Post.new $uri.path
post.set_form_data stat: stat, count: count, email: $email
http.request $uri, post
puts "count #{stat} -> #{count}" if $verbose
end
http.shutdown
end
end
ARGF.each do |line|
case line[0]
when ' ' then processing line
when 'C' then completed line
when 'M' then mongodb line
when 'R' then rendered line
when 'S' then started line
end
end
Thread.pass until $queue.empty?
$exit = true
$threads.each {|t| t.join }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment