///|
/// Mutable online counters for a stream of changes.
pub struct OnlineMetrics {
mut changes : Int
mut scalar_changes : Int
mut vector_changes : Int
mut real_changes : Int
mut unknown_changes : Int
mut first_time : Int64?
mut last_time : Int64?
mut checksum : Int64
} derive(Debug, Eq)
///|
/// Create an empty online metrics accumulator.
pub fn new_online_metrics() -> OnlineMetrics {
{
changes: 0,
scalar_changes: 0,
vector_changes: 0,
real_changes: 0,
unknown_changes: 0,
first_time: None,
last_time: None,
checksum: 0L,
}
}
///|
/// Add one change to an online accumulator.
pub fn OnlineMetrics::push(self : OnlineMetrics, change : Change) -> Unit {
self.changes += 1
match self.first_time {
None => self.first_time = Some(change.time)
_ => ()
}
self.last_time = Some(change.time)
self.checksum += change.time
match change.value {
Scalar(value) => {
self.scalar_changes += 1
if !is_known_scalar(value) {
self.unknown_changes += 1
}
}
Vector(bits) => {
self.vector_changes += 1
if bits.contains_char('x') ||
bits.contains_char('X') ||
bits.contains_char('z') ||
bits.contains_char('Z') {
self.unknown_changes += 1
}
}
Real(_) => self.real_changes += 1
}
}
///|
/// Add all trace changes to an accumulator.
pub fn online_metrics(trace : Trace) -> OnlineMetrics {
let result = new_online_metrics()
for change in trace.changes {
result.push(change)
}
result
}
///|
/// Merge two online metric accumulators.
pub fn OnlineMetrics::merge(
self : OnlineMetrics,
other : OnlineMetrics,
) -> OnlineMetrics {
let first_time = match (self.first_time, other.first_time) {
(Some(a), Some(b)) => Some(Int64::min(a, b))
(Some(a), None) => Some(a)
(None, Some(b)) => Some(b)
(None, None) => None
}
let last_time = match (self.last_time, other.last_time) {
(Some(a), Some(b)) => Some(Int64::max(a, b))
(Some(a), None) => Some(a)
(None, Some(b)) => Some(b)
(None, None) => None
}
{
changes: self.changes + other.changes,
scalar_changes: self.scalar_changes + other.scalar_changes,
vector_changes: self.vector_changes + other.vector_changes,
real_changes: self.real_changes + other.real_changes,
unknown_changes: self.unknown_changes + other.unknown_changes,
first_time,
last_time,
checksum: self.checksum + other.checksum,
}
}
///|
/// Render online metrics as JSON.
pub fn OnlineMetrics::to_json_string(self : OnlineMetrics) -> String {
"{\"changes\":" +
self.changes.to_string() +
",\"scalar\":" +
self.scalar_changes.to_string() +
",\"vector\":" +
self.vector_changes.to_string() +
",\"real\":" +
self.real_changes.to_string() +
",\"unknown\":" +
self.unknown_changes.to_string() +
",\"checksum\":" +
self.checksum.to_string() +
"}"
}
///|
/// Return the average time between online changes.
pub fn OnlineMetrics::mean_interval(self : OnlineMetrics) -> Double? {
match (self.first_time, self.last_time) {
(Some(first), Some(last)) if self.changes > 1 =>
Some((last - first).to_double() / (self.changes - 1).to_double())
_ => None
}
}