///|
pub(all) struct WindowStatistics {
window_count : Int
total_requests : Int
total_good : Int
total_bad : Int
min_availability_bp : Int
max_availability_bp : Int
average_availability_bp : Int
} derive(Eq, Debug)
///|
pub fn WindowStatistics::from_windows(
windows : Array[RequestWindow],
) -> WindowStatistics {
if windows.length() == 0 {
{
window_count: 0,
total_requests: 0,
total_good: 0,
total_bad: 0,
min_availability_bp: 10000,
max_availability_bp: 0,
average_availability_bp: 10000,
}
} else {
let mut total_requests = 0
let mut total_good = 0
let mut total_bad = 0
let mut min_availability_bp = 10000
let mut max_availability_bp = 0
let mut availability_sum = 0
for window in windows {
let availability = window.availability_bp()
total_requests = total_requests + window.total
total_good = total_good + window.good
total_bad = total_bad + window.bad()
availability_sum = availability_sum + availability
if availability < min_availability_bp {
min_availability_bp = availability
}
if availability > max_availability_bp {
max_availability_bp = availability
}
}
{
window_count: windows.length(),
total_requests,
total_good,
total_bad,
min_availability_bp,
max_availability_bp,
average_availability_bp: availability_sum / windows.length(),
}
}
}
///|
pub fn WindowStatistics::error_rate_bp(self : WindowStatistics) -> Int {
if self.total_requests == 0 {
0
} else {
self.total_bad * 10000 / self.total_requests
}
}
///|
pub fn WindowStatistics::healthy(
self : WindowStatistics,
target : SloTarget,
) -> Bool {
self.error_rate_bp() <= target.allowed_error_bp()
}
///|
pub fn WindowStatistics::to_json(self : WindowStatistics) -> String {
"{\"window_count\":\{self.window_count},\"total_requests\":\{self.total_requests},\"total_good\":\{self.total_good},\"total_bad\":\{self.total_bad},\"min_availability_bp\":\{self.min_availability_bp},\"max_availability_bp\":\{self.max_availability_bp},\"average_availability_bp\":\{self.average_availability_bp}}"
}
///|
pub fn WindowStatistics::merge(
self : WindowStatistics,
other : WindowStatistics,
) -> WindowStatistics {
let count = self.window_count + other.window_count
let min_value = if self.min_availability_bp < other.min_availability_bp {
self.min_availability_bp
} else {
other.min_availability_bp
}
let max_value = if self.max_availability_bp > other.max_availability_bp {
self.max_availability_bp
} else {
other.max_availability_bp
}
{
window_count: count,
total_requests: self.total_requests + other.total_requests,
total_good: self.total_good + other.total_good,
total_bad: self.total_bad + other.total_bad,
min_availability_bp: min_value,
max_availability_bp: max_value,
average_availability_bp: if count == 0 {
10000
} else {
(
self.average_availability_bp * self.window_count +
other.average_availability_bp * other.window_count
) /
count
},
}
}
///|
pub fn windows_in_range(
windows : Array[RequestWindow],
start : Int,
end : Int,
) -> Array[RequestWindow] {
let result = []
for window in windows {
if window.minutes >= start && window.minutes <= end {
result.push(window)
}
}
result
}
///|
pub fn availability_band(availability_bp : Int) -> String {
if availability_bp >= 9990 {
"excellent"
} else if availability_bp >= 9900 {
"healthy"
} else if availability_bp >= 9500 {
"degraded"
} else {
"critical"
}
}
///|
pub fn error_rate_percent(error_bp : Int) -> String {
let value = if error_bp < 0 { 0 } else { error_bp }
"\{value / 100}.\{two_digits(value % 100)}%"
}