Uptime computation
parent
f1a61cd19b
commit
212bf0a36f
|
@ -34,6 +34,34 @@ class Service < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
UPTIME_DURATIONS = [1.year, 1.month, 1.week, 1.day].freeze
|
||||
|
||||
def uptime
|
||||
first_check = self.checks.order(created_at: :asc).limit(1).first
|
||||
return nil unless first_check
|
||||
|
||||
now = Time.now.utc
|
||||
uptime = UPTIME_DURATIONS.map { |d| [d, 0.second] }.to_h
|
||||
ago = UPTIME_DURATIONS.map { |d| [d, d.ago(now).utc] }.to_h
|
||||
start = ago.fetch UPTIME_DURATIONS.first
|
||||
|
||||
self.downs.where('"to" >= ?', start).each do |down|
|
||||
UPTIME_DURATIONS.each do |duration|
|
||||
start = ago[duration]
|
||||
uptime[duration] += down.to.utc - [start, down.from.utc].max if start <= down.to
|
||||
end
|
||||
end
|
||||
|
||||
check_start = first_check.created_at.utc
|
||||
uptime.map do |duration, downtime|
|
||||
start = ago[duration]
|
||||
max = [check_start, start].max
|
||||
diff = (now - max).seconds
|
||||
percentage = 1 - downtime / diff
|
||||
[duration, percentage]
|
||||
end.to_h
|
||||
end
|
||||
|
||||
def last_check
|
||||
self.checks.order(created_at: :desc).limit(1).first
|
||||
end
|
||||
|
|
|
@ -13,7 +13,6 @@ describe Service do
|
|||
.and_return(check)
|
||||
|
||||
now = Time.utc 2020, 01, 01, 00, 00, 00
|
||||
from = nil
|
||||
Timecop.freeze now do
|
||||
allow(check).to receive(:ok?).and_return(true).at_least(:once)
|
||||
expect { service.check! }.to not_change { ActionMailer::Base.deliveries.count } \
|
||||
|
@ -54,4 +53,37 @@ describe Service do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :uptime do
|
||||
let!(:service) { Service.create! name: :test, type: :ping, config: { host: 'example.org' } }
|
||||
let!(:check) { service.checks.create! created_at: '2020-01-01', result: true }
|
||||
|
||||
it 'must exclude downtime prior to uptime period' do
|
||||
service.downs.create! from: '2019-01-01', to: '2020-01-01'
|
||||
Timecop.freeze 2021, 01, 01 do
|
||||
expect(service.uptime[1.year]).to eq 1
|
||||
end
|
||||
end
|
||||
|
||||
it 'must only include the last downtime part of overlapping uptime period' do
|
||||
service.downs.create! from: '2019-07-01', to: '2020-07-01'
|
||||
Timecop.freeze 2021, 01, 01 do
|
||||
expect(service.uptime[1.year]).to eq 1-(182.0/366)
|
||||
end
|
||||
end
|
||||
|
||||
it 'must include all the downtime later to uptime period' do
|
||||
service.downs.create! from: '2020-03-01', to: '2020-07-01'
|
||||
Timecop.freeze 2021, 01, 01 do
|
||||
expect(service.uptime[1.year]).to eq 1-(122.0/366)
|
||||
end
|
||||
end
|
||||
|
||||
it 'must restrict uptime period if check created before' do
|
||||
service.downs.create! from: '2020-03-01', to: '2020-07-01'
|
||||
Timecop.freeze 2020, 06, 01 do
|
||||
expect(service.uptime[1.year]).to eq 1-(122.0/152)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue