Skip to content

Instantly share code, notes, and snippets.

@mthadley
Created April 12, 2022 23:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mthadley/ca40a4ecff417f1dae6715f352c148db to your computer and use it in GitHub Desktop.
Save mthadley/ca40a4ecff417f1dae6715f352c148db to your computer and use it in GitHub Desktop.
Uptime Checker for HTTPS Services
#!/usr/bin/env ruby
require "net/http"
require "openssl"
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "colorize", "~> 0.8"
end
fail "Expected URL as first argument to script." unless ARGV[0]
class Poller
attr_reader :target, :interval
def initialize(target, interval: 1)
@target = target
@interval = interval
@requests = 0
@errors = 0
end
def start!
puts "Tracking uptime for #{target}..."
puts
Signal.trap "INT" do
puts
puts "Stopping..."
puts
print_stats
exit 1
end
loop do
status = get_target_status
update_stats(status)
puts <<~OUT
#{Time.now}
===============
#{status.message}
OUT
sleep interval
end
end
private
def get_target_status
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
cert = OpenSSL::X509::Certificate.new(http.peer_cert)
request = Net::HTTP::Get.new(uri)
response = http.request(request)
Status.new(
error: error_response?(response),
message: <<~MSG
Status: #{response.code.public_send(color_for_response(response))}
Cert: #{cert.issuer}
MSG
)
rescue => err
Status.new(
error: true,
message: <<~MSG
#{"Error".red}: #{err.class}
Message: #{err}
MSG
)
end
end
def uri
@uri ||= URI(target)
end
def color_for_response(response)
case response
when Net::HTTPSuccess then :green
when Net::HTTPRedirection then :blue
else :red
end
end
def error_response?(response)
case response
when Net::HTTPClientError, Net::HTTPServerError
true
else
false
end
end
def update_stats(status)
@requests += 1
@errors += 1 if status.error?
end
def print_stats
puts <<~OUT
Total Requests: #{@requests}
Errors: #{@errors.to_s.public_send(@errors.zero? ? :green : :red)}
OUT
end
Status = Struct.new(:error, :message, keyword_init: true) do
def error?
error
end
end
end
Poller.new(ARGV[0]).start!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment