Skip to content

Instantly share code, notes, and snippets.

@mfn
Forked from anonymous/http_responsetime_detailed.rb
Last active December 12, 2015 08:49
Show Gist options
  • Save mfn/4747157 to your computer and use it in GitHub Desktop.
Save mfn/4747157 to your computer and use it in GitHub Desktop.
Munin script written in Ruby to get more details about a single HTTP connection, namely: DNS lookup time, connect time, send request time, wait for first byte of response and response time.
#!/usr/bin/env ruby
require 'uri'
require 'socket'
if ARGV[0] and ( ARGV[0] == "-h" or ARGV[0] == "--help" )
puts "#{$0} [-h|--help] [config]"
puts "Munin plugin to measure individual HTTP timings"
puts " --help,-h Show this help"
puts " config Prints the configuration for munin"
puts ""
puts "Environment variables:"
puts " URL - URL to connect to"
puts " HTTP_HEADER - Custom HTTP Header(s) to append"
puts " graph_title - Title for the munin graph"
puts ""
puts "All values are reported in ms"
puts ""
puts "Written by Markus Fischer <markus@fischer.name>"
exit 0
end
graph_title = ENV['graph_title'] || "HTTP timings"
if ARGV[0] and ARGV[0] == "config"
puts <<EOT
graph_title #{graph_title}
graph_vlabel Time [ms]
graph_args --base 1000
graph_scale no
graph_category HTTPng
dns.label DNS
dns.draw AREA
connect.label Connect
connect.draw STACK
header_sent.label Header sent
header_sent.draw STACK
waiting.label Waiting
waiting.draw STACK
received.label Received
received.draw STACK
EOT
exit 0
end
def diff_time_ms(a,b)
((a - b) * 1000).to_i
end
HTTP_LE = "\r\n"
uri = URI.parse ENV['URL']
request_a = [
"GET / HTTP/1.1",
"Host: #{uri.host}",
"Connection: Close"
]
if ENV['HTTP_HEADER']
request_a << ENV['HTTP_HEADER']
end
request = request_a.join(HTTP_LE) + HTTP_LE + HTTP_LE
timings = {}
timings[:start] = Time.now
hosts = TCPSocket.gethostbyname uri.host
timings[:dns] = Time.now
socket = TCPSocket.new hosts[3], uri.port
timings[:connected] = Time.now
socket.print request
timings[:sent_request] = Time.now
response = socket.recv 1
# So we know how long it took to receive the first byte
timings[:response_started] = Time.now
while rec = socket.recv(4096)
response += rec
break if rec.length == 0
end
timings[:response_finished] = Time.now
data = {}
data[:dns] = diff_time_ms(timings[:dns], timings[:start])
data[:connect] = diff_time_ms(timings[:connected], timings[:dns])
data[:header_sent] = diff_time_ms(timings[:sent_request], timings[:connected])
data[:waiting] = diff_time_ms(timings[:response_started], timings[:sent_request])
data[:received] = diff_time_ms(timings[:response_finished], timings[:response_started])
data.each do |k,v|
puts "#{k}.value #{v}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment