///|
pub(all) struct Histogram {
name : String
mut count : Int
mut sum : Double
mut min_val : Double
mut max_val : Double
priv bins : Array[Int]
bin_width : Double
min_bin : Double
}
///|
pub fn Histogram::new(
name : String,
num_bins : Int,
min_bin : Double,
max_bin : Double,
) -> Histogram {
if num_bins <= 0 || max_bin <= min_bin {
abort("Invalid Histogram bin parameters")
}
let bins = []
for i = 0; i < num_bins + 2; i = i + 1 {
bins.push(0)
}
let bin_width = (max_bin - min_bin) / Double::from_int(num_bins)
{
name,
count: 0,
sum: 0.0,
min_val: 1.0e300,
max_val: -1.0e300,
bins,
bin_width,
min_bin,
}
}
///|
pub fn Histogram::add(self : Histogram, value : Double) -> Unit {
self.count = self.count + 1
self.sum = self.sum + value
if value < self.min_val {
self.min_val = value
}
if value > self.max_val {
self.max_val = value
}
if value < self.min_bin {
self.bins[0] = self.bins[0] + 1
} else {
let num_bins = self.bins.length() - 2
let idx = ((value - self.min_bin) / self.bin_width).to_int()
if idx >= num_bins {
self.bins[num_bins + 1] = self.bins[num_bins + 1] + 1
} else {
self.bins[idx + 1] = self.bins[idx + 1] + 1
}
}
}
///|
pub fn Histogram::mean(self : Histogram) -> Double {
if self.count == 0 {
0.0
} else {
self.sum / Double::from_int(self.count)
}
}
///|
pub fn Histogram::count(self : Histogram) -> Int {
self.count
}
///|
pub(all) struct ThroughputTracker {
name : String
mut count : Int
mut start_time : Double
mut last_time : Double
}
///|
pub fn ThroughputTracker::new(
name : String,
start_time : Double,
) -> ThroughputTracker {
{ name, count: 0, start_time, last_time: start_time }
}
///|
pub fn ThroughputTracker::record(
self : ThroughputTracker,
time : Double,
count_delta : Int,
) -> Unit {
if time < self.last_time {
abort("ThroughputTracker time cannot move backward")
}
self.count = self.count + count_delta
self.last_time = time
}
///|
pub fn ThroughputTracker::rate(self : ThroughputTracker) -> Double {
let elapsed = self.last_time - self.start_time
if elapsed <= 0.0 {
0.0
} else {
Double::from_int(self.count) / elapsed
}
}
///|
pub(all) struct SlaMonitor {
name : String
threshold : Double
mut total : Int
mut violations : Int
}
///|
pub fn SlaMonitor::new(name : String, threshold : Double) -> SlaMonitor {
{ name, threshold, total: 0, violations: 0 }
}
///|
pub fn SlaMonitor::record(self : SlaMonitor, wait_time : Double) -> Bool {
self.total = self.total + 1
let violated = wait_time > self.threshold
if violated {
self.violations = self.violations + 1
}
violated
}
///|
pub fn SlaMonitor::violation_rate(self : SlaMonitor) -> Double {
if self.total == 0 {
0.0
} else {
Double::from_int(self.violations) / Double::from_int(self.total)
}
}
///|
pub fn SlaMonitor::violations(self : SlaMonitor) -> Int {
self.violations
}
///|
pub fn SlaMonitor::total(self : SlaMonitor) -> Int {
self.total
}