Skip to content

Instantly share code, notes, and snippets.

@eThikas
Created March 22, 2012 15:46
Show Gist options
  • Save eThikas/2159122 to your computer and use it in GitHub Desktop.
Save eThikas/2159122 to your computer and use it in GitHub Desktop.
Continuously measure 'Time To First Byte'. Easily plot Connection and TTFB
#!/usr/bin/env ruby
#
# @Name TTFB Measurer
# @Author Rasmus Christiansen
# @Description
#
# Measures the "true" loading time of a website.
# Saves data output to an .out-file
# Saves additional .conn and .ttfb files for easy plotting
# Generates and saves A report with average data.
#
#
# TODO: Very messy, but gets the job done. Could use a proper rewriting
#
class APP
def initialize
if ARGV.length < 1
puts "Usage: #{__FILE__} domain.com [delay] [subsystem] [timeout in minutes]"
exit
end
@delay = 10
@domain = ARGV[0]
@domain_formatted = @domain.gsub("/", "_")
@domain_formatted = @domain_formatted.gsub(".", "_")
@logdir = "ttfb_logs"
@timeout = 0
@iter =0
@sum_conn =0.0
@sum_ttfb =0.0
@sum_total=0.0
unless File.directory?(@logdir)
Dir.mkdir(@logdir)
end
if ARGV.length >= 2
@delay = ARGV[1]
end
if ARGV.length >= 3
@subsystem = ARGV[2]
@logdir = @logdir + "/" + @subsystem
unless File.directory?(@logdir)
Dir.mkdir(@logdir)
end
end
if ARGV.length >= 4
@timeout = (ARGV[3]).to_i*60
end
@init_time = Time.now
@filename = @logdir + "/" + @domain_formatted + "-" + @init_time.to_i.to_s + ".out"
@filename_conn = @logdir + "/" + @domain_formatted + "-" + @init_time.to_i.to_s + ".conn"
@filename_ttfb = @logdir + "/" + @domain_formatted + "-" + @init_time.to_i.to_s + ".ttfb"
@filename_avg = @logdir + "/" + @domain_formatted + "-" + @init_time.to_i.to_s + ".avg"
end
def logtime
t = Time.now
return t.strftime("[%m/%d/%Y %H:%M:%S]")
end
def logit str
open(@filename, 'a') do |f|
f.puts str
end
end
def plotlog str
tmp = str.split(" ")
timediff = Time.now.to_i - @init_time.to_i
open(@filename_conn, 'a') do |f|
f.puts "#{timediff} #{tmp[1]}"
end
open(@filename_ttfb, 'a') do |f|
f.puts "#{timediff} #{tmp[3]}"
end
end
def ttfb
measure = `curl -o /dev/null -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} \n" -s http://#{@domain}`
return measure
end
def genAvg
#end_time = Time.now
#@running_time = end_time.to_i - @init_time.to_i
puts "Generating report.."
puts
report = {}
report["started"] = "Started:\t" + @init_time.to_i.to_s + @init_time.strftime("\t[%m/%d/%Y %H:%M:%S]")
report["ended"] = "Ended:\t\t" + @end_time.to_i.to_s + @end_time.strftime("\t[%m/%d/%Y %H:%M:%S]")
report["running"] = "Running:\t" + @running_time.to_s + " seconds"
report["connavg"] = "Conn Avg:\t#{@sum_conn/@iter} \t\t[#{@sum_conn}/#{@iter}]"
report["ttfbavg"] = "TTFB Avg:\t#{@sum_ttfb/@iter} \t\t[#{@sum_ttfb}/#{@iter}]"
report["totalavg"] = "Total Avg:\t#{@sum_total/@iter} \t\t[#{@sum_total}/#{@iter}]"
open(@filename_avg, 'a') do |f|
f.puts report["started"]
puts report["started"]
f.puts report["ended"]
puts report["ended"]
f.puts report["running"]
puts report["running"]
f.puts report["connavg"]
puts report["connavg"]
f.puts report["ttfbavg"]
puts report["ttfbavg"]
f.puts report["totalavg"]
puts report["totalavg"]
puts
end
puts "Report saved to: #{@filename_avg}"
end
def reportAvg str
tmp = str.split(" ")
#puts "#{@iter} - Summing: #{tmp[1]}, #{tmp[3]}, #{tmp[6]}"
@sum_conn +=tmp[1].to_f
@sum_ttfb +=tmp[3].to_f
@sum_total+=tmp[6].to_f
end
def run
trap("INT") do
puts " signal caught!"
genAvg
exit
end
puts "Measuring Time To First Byte on #{@domain} with a #{@delay} seconds delay."
unless @timeout.nil? || @timeout==0
puts "Running for #{@timeout/60} minutes (#{@timeout} seconds) or until manual quit.."
end
while TRUE
@iter += 1
@end_time = Time.now
@running_time = @end_time.to_i - @init_time.to_i
#puts "Running for : #{@running_time}"
unless @timeout.nil? || @timeout==0
if @running_time >= @timeout
#if (@iter >= (@runningtime))
puts "Timeout reached! Quitting.."
genAvg
exit
end
end
ttfb_res = ttfb
ttfb_pretty = logtime + " " + ttfb_res
puts ttfb_pretty
logit ttfb_pretty
plotlog ttfb_res
reportAvg ttfb_res
sleep(@delay.to_i)
end
end
end
app = APP.new
app.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment