Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
require 'gsl'
require 'time'
module Diskalerter
class ThresholdEstimator
attr_reader :timestamps, :signal, :threshold, :now
# timestamps - a list of timestamps in epoch milliseconds
# signal - a list of values for the provided timestamps
# threshold - the "exhaustion" threshold (e.g., 100 for a percentage signal)
def initialize(timestamps, signal, threshold)
@timestamps = timestamps
@signal = signal
@threshold = threshold
@now = Time.now.to_i
end
def alertable?
now < intersect && intersect < warning_threshold
end
def will_intersect?
now < intersect && intersect < never
end
def intersect
x_intersect, slope = linear_fit
(threshold - x_intersect) / slope
end
def linear_fit
return @linear_fit if @linear_fit
timestamps, signal = filtered_data
x = GSL::Vector[*timestamps]
y = GSL::Vector[*signal]
@linear_fit = GSL::Fit.linear(x, y)
end
def warning_threshold
now + one_week
end
def one_week
3600 * 24 * 7
end
def five_years
one_week * 52 * 5
end
def never
now + five_years
end
def intersect_time
Time.at(intersect)
end
def intersect_days
(intersect - now) / 24 / 3600
end
def intersect_milliseconds
(intersect - now) * 1000
end
def intersect_time_string
if will_intersect?
'%s (%0.2f days)' % [intersect_time.iso8601, intersect_days]
else
'Never'
end
end
private
def filtered_data
timestamps.map { |t| t / 1000 }.zip(signal).reject { |pair| pair[1].nil? }.transpose
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment