Created
June 7, 2018 22:21
-
-
Save jhawthorn/6d631e9c1641451a4f7f711258d938ef to your computer and use it in GitHub Desktop.
Generate a text report of internet outages from https://gist.github.com/jhawthorn/7bd68dd027a1b8e1ae2bdc56efed2414
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ruby report.rb | |
Outage from 2018-06-07 02:50:49 -0700 to 2018-06-07 02:58:32 -0700 | |
duration: 8 minutes | |
pings lost: 77% (34 / 44) | |
average ping: 22ms | |
Outage from 2018-06-07 05:07:10 -0700 to 2018-06-07 05:21:04 -0700 | |
duration: 14 minutes | |
pings lost: 83% (65 / 78) | |
average ping: 16ms | |
Outage from 2018-06-07 12:11:27 -0700 to 2018-06-07 12:15:18 -0700 | |
duration: 4 minutes | |
pings lost: 8% (2 / 24) | |
average ping: 18ms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ping = Struct.new(:time, :ms) do | |
def dropped? | |
ms.nil? | |
end | |
end | |
Outage = Struct.new(:pings) do | |
def start_time | |
pings.first.time | |
end | |
def end_time | |
pings.last.time | |
end | |
def duration | |
end_time - start_time | |
end | |
def dropped_ratio | |
pings.count(&:dropped?) / pings.count.to_f | |
end | |
def dropped_pings | |
pings.select(&:dropped?) | |
end | |
def returned_pings | |
pings.reject(&:dropped?) | |
end | |
def average_ping | |
if returned_pings.empty? | |
nil | |
else | |
returned_pings.sum(&:ms) / returned_pings.count | |
end | |
end | |
def description | |
<<~STR | |
Outage from #{start_time} to #{end_time} | |
duration: #{(duration/60.0).ceil} minutes | |
pings lost: #{(dropped_ratio * 100).round}% (#{pings.count(&:dropped?)} / #{pings.count}) | |
average ping: #{average_ping}ms | |
STR | |
end | |
end | |
def partition_outages(pings) | |
window = 5 * 60 # 5 minutes | |
dropped = pings.select(&:dropped?) | |
partitions = [] | |
until dropped.empty? do | |
partition = [dropped.shift] | |
partitions << partition | |
while !dropped.empty? && (dropped.first.time - partition.last.time) < window | |
partition << dropped.shift | |
end | |
end | |
partitions.map do |dropped| | |
partition_pings = pings.select do |ping| | |
(dropped.first.time..dropped.last.time).cover?(ping.time) | |
end | |
Outage.new(partition_pings) | |
end | |
end | |
file = Dir['logs/*.guff'].sort.last | |
data = File.read(file).lines.map do |line| | |
time, ping = line.strip.split(",") | |
time = Time.at(time.to_i) | |
ping = ping && ping.to_i | |
Ping.new(time, ping) | |
end | |
outages = partition_outages(data) | |
outages.select do |outage| | |
outage.duration > 60 | |
end.each do |outage| | |
puts outage.description | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment