///|
/// Runtime observability primitives for services and production equipment.
/// The module turns timestamped measurements and incidents into reliability
/// indicators that can be used by dashboards, alerting, and planning code.
pub struct TelemetryPoint {
timestamp : Double
value : Double
healthy : Bool
weight : Double
}
///|
pub fn telemetry_point(
timestamp~ : Double,
value~ : Double,
healthy~ : Bool,
weight~ : Double,
) -> TelemetryPoint {
if timestamp < 0.0 || weight <= 0.0 {
abort("timestamp must be non-negative and weight must be positive")
}
{ timestamp, value, healthy, weight }
}
///|
pub struct TelemetryWindow {
points : Array[TelemetryPoint]
start : Double
end : Double
interval : Double
}
///|
pub fn telemetry_window(
points : Array[TelemetryPoint],
start~ : Double,
end~ : Double,
interval~ : Double,
) -> TelemetryWindow {
if start < 0.0 || end <= start || interval <= 0.0 {
abort("invalid telemetry window")
}
let selected = points.filter(point => {
point.timestamp >= start && point.timestamp <= end
})
{ points: selected, start, end, interval }
}
///|
pub fn telemetry_window_duration(window : TelemetryWindow) -> Double {
window.end - window.start
}
///|
pub fn telemetry_window_count(window : TelemetryWindow) -> Int {
window.points.length()
}
///|
pub fn telemetry_window_values(window : TelemetryWindow) -> Array[Double] {
window.points.map(point => point.value)
}
///|
pub fn telemetry_window_healthy_count(window : TelemetryWindow) -> Int {
window.points.fold(init=0, (count, point) => {
if point.healthy {
count + 1
} else {
count
}
})
}
///|
pub fn telemetry_window_unhealthy_count(window : TelemetryWindow) -> Int {
window.points.length() - telemetry_window_healthy_count(window)
}
///|
pub fn telemetry_window_weight(window : TelemetryWindow) -> Double {
window.points.fold(init=0.0, (total, point) => total + point.weight)
}
///|
pub fn telemetry_window_mean(window : TelemetryWindow) -> Double {
let weight = telemetry_window_weight(window)
if weight <= 0.0 {
0.0
} else {
window.points.fold(init=0.0, (total, point) => {
total + point.value * point.weight
}) /
weight
}
}
///|
pub fn telemetry_window_minimum(window : TelemetryWindow) -> Double {
if window.points.is_empty() {
0.0
} else {
let mut result = window.points[0].value
for point in window.points {
if point.value < result {
result = point.value
}
}
result
}
}
///|
pub fn telemetry_window_maximum(window : TelemetryWindow) -> Double {
if window.points.is_empty() {
0.0
} else {
let mut result = window.points[0].value
for point in window.points {
if point.value > result {
result = point.value
}
}
result
}
}
///|
pub fn telemetry_window_range(window : TelemetryWindow) -> Double {
telemetry_window_maximum(window) - telemetry_window_minimum(window)
}
///|
pub fn telemetry_window_variance(window : TelemetryWindow) -> Double {
let weight = telemetry_window_weight(window)
if weight <= 0.0 {
0.0
} else {
let center = telemetry_window_mean(window)
window.points.fold(init=0.0, (total, point) => {
total + point.weight * (point.value - center) * (point.value - center)
}) /
weight
}
}
///|
pub fn telemetry_window_standard_deviation(window : TelemetryWindow) -> Double {
telemetry_window_variance(window).sqrt()
}
///|
pub fn telemetry_window_availability(window : TelemetryWindow) -> Double {
let total = telemetry_window_weight(window)
if total <= 0.0 {
0.0
} else {
window.points.fold(init=0.0, (value, point) => {
if point.healthy {
value + point.weight
} else {
value
}
}) /
total
}
}
///|
pub fn telemetry_window_failure_rate(window : TelemetryWindow) -> Double {
1.0 - telemetry_window_availability(window)
}
///|
pub fn telemetry_window_coefficient_of_variation(
window : TelemetryWindow,
) -> Double {
let mean_value = telemetry_window_mean(window)
if mean_value == 0.0 {
0.0
} else {
telemetry_window_standard_deviation(window) / mean_value.abs()
}
}
///|
pub fn telemetry_window_normalized(window : TelemetryWindow) -> Array[Double] {
let mean_value = telemetry_window_mean(window)
let deviation = telemetry_window_standard_deviation(window)
if deviation <= 1.0e-12 {
Array::make(window.points.length(), 0.0)
} else {
window.points.map(point => (point.value - mean_value) / deviation)
}
}
///|
pub fn telemetry_window_threshold_count(
window : TelemetryWindow,
lower : Double,
upper : Double,
) -> Int {
if lower > upper {
abort("lower threshold must not exceed upper threshold")
}
window.points.fold(init=0, (count, point) => {
if point.value < lower || point.value > upper {
count + 1
} else {
count
}
})
}
///|
pub fn telemetry_window_above(
window : TelemetryWindow,
threshold : Double,
) -> Int {
window.points.fold(init=0, (count, point) => {
if point.value > threshold {
count + 1
} else {
count
}
})
}
///|
pub fn telemetry_window_below(
window : TelemetryWindow,
threshold : Double,
) -> Int {
window.points.fold(init=0, (count, point) => {
if point.value < threshold {
count + 1
} else {
count
}
})
}
///|
pub fn telemetry_window_first(window : TelemetryWindow) -> Double {
if window.points.is_empty() {
window.start
} else {
window.points[0].timestamp
}
}
///|
pub fn telemetry_window_last(window : TelemetryWindow) -> Double {
if window.points.is_empty() {
window.end
} else {
window.points[window.points.length() - 1].timestamp
}
}
///|
pub fn telemetry_window_coverage(window : TelemetryWindow) -> Double {
if window.points.is_empty() {
0.0
} else {
((telemetry_window_last(window) - telemetry_window_first(window)) /
telemetry_window_duration(window))
.max(0.0)
.min(1.0)
}
}
///|
pub fn telemetry_window_gap(window : TelemetryWindow) -> Double {
if window.points.length() < 2 {
telemetry_window_duration(window)
} else {
let mut gap = 0.0
for i in 0..<(window.points.length() - 1) {
gap = gap.max(window.points[i + 1].timestamp - window.points[i].timestamp)
}
gap
}
}
///|
pub fn telemetry_window_event_count(window : TelemetryWindow) -> Int {
if window.points.length() < 2 {
0
} else {
let mut events = 0
for i in 1.. Double {
telemetry_window_duration(window) * telemetry_window_failure_rate(window)
}
///|
pub fn telemetry_window_error_budget(
window : TelemetryWindow,
target : Double,
) -> Double {
if target < 0.0 || target > 1.0 {
abort("target must be between zero and one")
}
(telemetry_window_availability(window) - target).max(0.0) *
telemetry_window_duration(window)
}
///|
pub fn telemetry_window_burn_rate(
window : TelemetryWindow,
target : Double,
) -> Double {
if target >= 1.0 || target < 0.0 {
abort("target must be between zero and one")
}
telemetry_window_failure_rate(window) / (1.0 - target)
}
///|
pub struct IncidentRecord {
start : Double
end : Double
severity : Int
cause : Int
}
///|
pub fn incident_record(
start~ : Double,
end~ : Double,
severity~ : Int,
cause~ : Int,
) -> IncidentRecord {
if start < 0.0 || end < start || severity < 0 || cause < 0 {
abort("invalid incident record")
}
{ start, end, severity, cause }
}
///|
pub fn incident_duration(incident : IncidentRecord) -> Double {
incident.end - incident.start
}
///|
pub fn incident_is_open_at(
incident : IncidentRecord,
timestamp : Double,
) -> Bool {
timestamp >= incident.start && timestamp <= incident.end
}
///|
pub fn incident_overlaps(left : IncidentRecord, right : IncidentRecord) -> Bool {
left.start <= right.end && right.start <= left.end
}
///|
pub fn incident_union_duration(incidents : Array[IncidentRecord]) -> Double {
if incidents.is_empty() {
0.0
} else {
let ordered = incidents.copy()
ordered.sort_by((left, right) => {
if left.start < right.start {
-1
} else if left.start > right.start {
1
} else {
0
}
})
let mut total = 0.0
let mut start = ordered[0].start
let mut end = ordered[0].end
for incident in ordered[1:] {
if incident.start <= end {
end = end.max(incident.end)
} else {
total += end - start
start = incident.start
end = incident.end
}
}
total + end - start
}
}
///|
pub fn incident_total_duration(incidents : Array[IncidentRecord]) -> Double {
incidents.fold(init=0.0, (total, incident) => {
total + incident_duration(incident)
})
}
///|
pub fn incident_mean_duration(incidents : Array[IncidentRecord]) -> Double {
if incidents.is_empty() {
0.0
} else {
incident_total_duration(incidents) / incidents.length().to_double()
}
}
///|
pub fn incident_max_duration(incidents : Array[IncidentRecord]) -> Double {
incidents.fold(init=0.0, (maximum, incident) => {
maximum.max(incident_duration(incident))
})
}
///|
pub fn incident_count_by_severity(
incidents : Array[IncidentRecord],
severity : Int,
) -> Int {
incidents.fold(init=0, (count, incident) => {
if incident.severity == severity {
count + 1
} else {
count
}
})
}
///|
pub fn incident_count_by_cause(
incidents : Array[IncidentRecord],
cause : Int,
) -> Int {
incidents.fold(init=0, (count, incident) => {
if incident.cause == cause {
count + 1
} else {
count
}
})
}
///|
pub fn incident_severity_weight(incidents : Array[IncidentRecord]) -> Double {
incidents.fold(init=0.0, (total, incident) => {
total + incident_duration(incident) * (incident.severity + 1).to_double()
})
}
///|
pub fn incident_rate(
incidents : Array[IncidentRecord],
window : Double,
) -> Double {
if window <= 0.0 {
abort("window must be positive")
}
incidents.length().to_double() / window
}
///|
pub struct IncidentSummary {
count : Int
total_duration : Double
union_duration : Double
mean_duration : Double
maximum_duration : Double
severity_weight : Double
rate : Double
}
///|
pub fn summarize_incidents(
incidents : Array[IncidentRecord],
window : Double,
) -> IncidentSummary {
if window <= 0.0 {
abort("window must be positive")
}
{
count: incidents.length(),
total_duration: incident_total_duration(incidents),
union_duration: incident_union_duration(incidents),
mean_duration: incident_mean_duration(incidents),
maximum_duration: incident_max_duration(incidents),
severity_weight: incident_severity_weight(incidents),
rate: incident_rate(incidents, window),
}
}
///|
pub fn incident_availability(
incidents : Array[IncidentRecord],
window : Double,
) -> Double {
if window <= 0.0 {
abort("window must be positive")
}
(1.0 - incident_union_duration(incidents) / window).max(0.0).min(1.0)
}
///|
pub fn incident_mttr(incidents : Array[IncidentRecord]) -> Double {
incident_mean_duration(incidents)
}
///|
pub fn incident_mtbf(
incidents : Array[IncidentRecord],
window : Double,
) -> Double {
if incidents.is_empty() {
window
} else {
(window - incident_union_duration(incidents)).max(0.0) /
incidents.length().to_double()
}
}
///|
pub struct AlertRule {
name : String
threshold : Double
direction : Int
minimum_samples : Int
consecutive_windows : Int
}
///|
pub fn alert_rule(
name~ : String,
threshold~ : Double,
direction~ : Int,
minimum_samples~ : Int,
consecutive_windows~ : Int,
) -> AlertRule {
if (direction != 1 && direction != -1) ||
minimum_samples < 1 ||
consecutive_windows < 1 {
abort("invalid alert rule")
}
{ name, threshold, direction, minimum_samples, consecutive_windows }
}
///|
pub fn alert_rule_breached(
rule : AlertRule,
value : Double,
samples : Int,
) -> Bool {
if samples < rule.minimum_samples {
false
} else if rule.direction > 0 {
value >= rule.threshold
} else {
value <= rule.threshold
}
}
///|
pub struct AlertDecision {
rule_name : String
triggered : Bool
value : Double
threshold : Double
consecutive : Int
severity : Int
}
///|
pub fn evaluate_alert(
rule : AlertRule,
values : Array[Double],
) -> AlertDecision {
let mut consecutive = 0
let mut maximum = 0.0
for value in values {
if alert_rule_breached(rule, value, values.length()) {
consecutive += 1
maximum = if rule.direction > 0 { maximum.max(value) } else { value }
} else {
consecutive = 0
}
}
let triggered = consecutive >= rule.consecutive_windows
{
rule_name: rule.name,
triggered,
value: maximum,
threshold: rule.threshold,
consecutive,
severity: if triggered {
2
} else if consecutive > 0 {
1
} else {
0
},
}
}
///|
pub fn evaluate_availability_alert(
window : TelemetryWindow,
target : Double,
minimum_samples : Int,
) -> AlertDecision {
let rule = alert_rule(
name="availability",
threshold=target,
direction=-1,
minimum_samples~,
consecutive_windows=1,
)
evaluate_alert(rule, [telemetry_window_availability(window)])
}
///|
pub fn evaluate_burn_rate_alert(
window : TelemetryWindow,
target : Double,
threshold : Double,
) -> AlertDecision {
let rule = alert_rule(
name="error-budget-burn",
threshold~,
direction=1,
minimum_samples=1,
consecutive_windows=1,
)
evaluate_alert(rule, [telemetry_window_burn_rate(window, target)])
}
///|
pub fn alert_severity_score(decision : AlertDecision) -> Double {
if decision.triggered {
decision.severity.to_double() * decision.value.abs()
} else {
0.0
}
}
///|
pub struct ForecastPoint {
horizon : Int
value : Double
lower : Double
upper : Double
}
///|
pub struct ForecastSeries {
points : Array[ForecastPoint]
slope : Double
intercept : Double
residual_scale : Double
}
///|
fn linear_intercept(values : Array[Double], slope : Double) -> Double {
if values.is_empty() {
0.0
} else {
values.fold(init=0.0, (total, value) => total + value) /
values.length().to_double() -
slope * (values.length() - 1).to_double() / 2.0
}
}
///|
fn linear_slope(values : Array[Double]) -> Double {
let n = values.length()
if n < 2 {
0.0
} else {
let mean_x = (n - 1).to_double() / 2.0
let mean_y = values.fold(init=0.0, (total, value) => total + value) /
n.to_double()
let mut numerator = 0.0
let mut denominator = 0.0
for i in 0.. ForecastSeries {
if horizon < 1 {
abort("forecast horizon must be positive")
}
let slope = linear_slope(values)
let intercept = linear_intercept(values, slope)
let residuals = Array::makei(values.length(), i => {
values[i] - (intercept + slope * i.to_double())
})
let residual_scale = if residuals.is_empty() {
0.0
} else {
(residuals.fold(init=0.0, (total, value) => total + value * value) /
residuals.length().to_double()).sqrt()
}
let last_index = values.length().max(1)
let points = Array::makei(horizon, i => {
let value = intercept + slope * (last_index + i).to_double()
let spread = residual_scale *
(1.0 + i.to_double() / horizon.to_double()).sqrt()
{ horizon: i + 1, value, lower: value - spread, upper: value + spread }
})
{ points, slope, intercept, residual_scale }
}
///|
pub fn forecast_values(forecast : ForecastSeries) -> Array[Double] {
forecast.points.map(point => point.value)
}
///|
pub fn forecast_lower(forecast : ForecastSeries) -> Array[Double] {
forecast.points.map(point => point.lower)
}
///|
pub fn forecast_upper(forecast : ForecastSeries) -> Array[Double] {
forecast.points.map(point => point.upper)
}
///|
pub fn forecast_trend(forecast : ForecastSeries) -> String {
if forecast.slope > 1.0e-12 {
"increasing"
} else if forecast.slope < -1.0e-12 {
"decreasing"
} else {
"stable"
}
}
///|
pub fn forecast_endpoint(forecast : ForecastSeries) -> Double {
if forecast.points.is_empty() {
forecast.intercept
} else {
forecast.points[forecast.points.length() - 1].value
}
}
///|
pub fn forecast_risk_score(
forecast : ForecastSeries,
target : Double,
) -> Double {
let endpoint = forecast_endpoint(forecast)
if target == 0.0 {
endpoint.abs()
} else {
(endpoint - target).abs() / target.abs()
}
}
///|
pub struct HealthSnapshot {
availability : Double
stability : Double
coverage : Double
freshness : Double
health_score : Double
status : String
}
///|
pub fn health_snapshot(
window : TelemetryWindow,
target : Double,
) -> HealthSnapshot {
if target < 0.0 || target > 1.0 {
abort("target must be between zero and one")
}
let availability = telemetry_window_availability(window)
let stability = 1.0 -
telemetry_window_coefficient_of_variation(window).min(1.0)
let coverage = telemetry_window_coverage(window)
let freshness = if window.points.is_empty() { 0.0 } else { 1.0 }
let target_factor = if target == 0.0 {
availability
} else {
(availability / target).min(1.0)
}
let score = (0.45 * target_factor +
0.25 * stability +
0.20 * coverage +
0.10 * freshness).min(1.0)
let status = if score >= 0.90 {
"healthy"
} else if score >= 0.70 {
"degraded"
} else {
"critical"
}
{ availability, stability, coverage, freshness, health_score: score, status }
}
///|
pub fn health_score(snapshot : HealthSnapshot) -> Double {
snapshot.health_score
}
///|
pub fn health_status(snapshot : HealthSnapshot) -> String {
snapshot.status
}
///|
pub fn health_is_actionable(snapshot : HealthSnapshot) -> Bool {
snapshot.status != "healthy"
}
///|
pub fn health_gap(snapshot : HealthSnapshot, target : Double) -> Double {
(target - snapshot.availability).max(0.0)
}
///|
pub fn health_risk_index(snapshot : HealthSnapshot) -> Double {
1.0 - snapshot.health_score
}
///|
pub struct ReliabilitySnapshot {
time : Double
reliability : Double
hazard : Double
cumulative_hazard : Double
mission_success : Double
}
///|
pub fn reliability_snapshot(
model : ReliabilityModel,
time : Double,
mission_count : Int,
) -> ReliabilitySnapshot {
if time < 0.0 || mission_count < 1 {
abort("invalid reliability snapshot")
}
let reliability = model.survival(time)
let mission_success = @math.pow(reliability, mission_count.to_double())
let hazard = model_hazard(model, time)
{
time,
reliability,
hazard,
cumulative_hazard: -safe_log_probability(reliability),
mission_success,
}
}
///|
pub fn snapshot_margin(
snapshot : ReliabilitySnapshot,
target : Double,
) -> Double {
snapshot.reliability - target
}
///|
pub fn snapshot_failure_probability(snapshot : ReliabilitySnapshot) -> Double {
1.0 - snapshot.reliability
}
///|
pub fn snapshot_expected_failures(
snapshot : ReliabilitySnapshot,
population : Int,
) -> Double {
if population < 0 {
abort("population must be non-negative")
}
population.to_double() * snapshot_failure_probability(snapshot)
}
///|
pub fn snapshot_target_time(
model : ReliabilityModel,
target : Double,
) -> Double {
if target <= 0.0 || target >= 1.0 {
abort("target reliability must be between zero and one")
}
model_quantile(model, 1.0 - target)
}
///|
pub fn snapshot_series(
model : ReliabilityModel,
times : Array[Double],
mission_count : Int,
) -> Array[ReliabilitySnapshot] {
times.map(time => reliability_snapshot(model, time, mission_count))
}
///|
pub fn snapshot_checksum(snapshots : Array[ReliabilitySnapshot]) -> Double {
snapshots.fold(init=0.0, (total, snapshot) => {
total + snapshot.reliability + snapshot.hazard + snapshot.mission_success
})
}
///|
pub fn rolling_windows(
points : Array[TelemetryPoint],
window_size : Int,
step : Int,
) -> Array[TelemetryWindow] {
if window_size < 1 || step < 1 {
abort("window size and step must be positive")
}
if points.is_empty() {
[]
} else {
let count = if points.length() < window_size {
1
} else {
(points.length() - window_size) / step + 1
}
Array::makei(count, i => {
let offset = i * step
let last = (offset + window_size - 1).min(points.length() - 1)
let selected = Array::makei(last - offset + 1, j => points[offset + j])
telemetry_window(
selected,
start=selected[0].timestamp,
end=selected[selected.length() - 1].timestamp.max(
selected[0].timestamp + 1.0,
),
interval=1.0,
)
})
}
}
///|
pub fn rolling_availability(
points : Array[TelemetryPoint],
window_size : Int,
step : Int,
) -> Array[Double] {
rolling_windows(points, window_size, step).map(window => {
telemetry_window_availability(window)
})
}
///|
pub fn rolling_failure_rates(
points : Array[TelemetryPoint],
window_size : Int,
step : Int,
) -> Array[Double] {
rolling_windows(points, window_size, step).map(window => {
telemetry_window_failure_rate(window)
})
}
///|
pub fn rolling_means(
points : Array[TelemetryPoint],
window_size : Int,
step : Int,
) -> Array[Double] {
rolling_windows(points, window_size, step).map(window => {
telemetry_window_mean(window)
})
}
///|
pub fn rolling_standard_deviations(
points : Array[TelemetryPoint],
window_size : Int,
step : Int,
) -> Array[Double] {
rolling_windows(points, window_size, step).map(window => {
telemetry_window_standard_deviation(window)
})
}
///|
pub fn rolling_burn_rates(
points : Array[TelemetryPoint],
window_size : Int,
step : Int,
target : Double,
) -> Array[Double] {
rolling_windows(points, window_size, step).map(window => {
telemetry_window_burn_rate(window, target)
})
}
///|
pub fn rolling_health(
points : Array[TelemetryPoint],
window_size : Int,
step : Int,
target : Double,
) -> Array[Double] {
rolling_windows(points, window_size, step).map(window => {
health_score(health_snapshot(window, target))
})
}
///|
pub fn change_points(values : Array[Double], threshold : Double) -> Array[Int] {
if threshold < 0.0 {
abort("threshold must be non-negative")
}
if values.length() < 2 {
[]
} else {
let result = []
for i in 1..= threshold {
result.push(i)
}
}
result
}
}
///|
pub fn change_magnitudes(values : Array[Double]) -> Array[Double] {
if values.length() < 2 {
[]
} else {
Array::makei(values.length() - 1, i => values[i + 1] - values[i])
}
}
///|
pub fn change_direction(value : Double) -> Int {
if value > 0.0 {
1
} else if value < 0.0 {
-1
} else {
0
}
}
///|
pub fn change_directions(values : Array[Double]) -> Array[Int] {
change_magnitudes(values).map(value => change_direction(value))
}
///|
pub fn positive_change_fraction(values : Array[Double]) -> Double {
let changes = change_magnitudes(values)
if changes.is_empty() {
0.0
} else {
changes
.fold(init=0, (count, value) => if value > 0.0 { count + 1 } else { count })
.to_double() /
changes.length().to_double()
}
}
///|
pub fn negative_change_fraction(values : Array[Double]) -> Double {
let changes = change_magnitudes(values)
if changes.is_empty() {
0.0
} else {
changes
.fold(init=0, (count, value) => if value < 0.0 { count + 1 } else { count })
.to_double() /
changes.length().to_double()
}
}
///|
pub fn total_absolute_change(values : Array[Double]) -> Double {
change_magnitudes(values).fold(init=0.0, (total, value) => total + value.abs())
}
///|
pub fn autocorrelation_lag(values : Array[Double], lag : Int) -> Double {
if lag < 0 || lag >= values.length() {
abort("invalid autocorrelation lag")
}
let count = values.length() - lag
if count < 2 {
0.0
} else {
let left = Array::makei(count, i => values[i])
let right = Array::makei(count, i => values[i + lag])
let left_mean = left.fold(init=0.0, (total, value) => total + value) /
count.to_double()
let right_mean = right.fold(init=0.0, (total, value) => total + value) /
count.to_double()
let mut numerator = 0.0
let mut left_scale = 0.0
let mut right_scale = 0.0
for i in 0.. Array[Double] {
if window < lag + 2 {
abort("window must exceed lag by at least two")
}
if values.length() < window {
[]
} else {
Array::makei(values.length() - window + 1, i => {
let sample = Array::makei(window, j => values[i + j])
autocorrelation_lag(sample, lag)
})
}
}
///|
pub fn observability_exponential_smoothing(
values : Array[Double],
alpha : Double,
) -> Array[Double] {
if alpha <= 0.0 || alpha > 1.0 {
abort("alpha must be in (0, 1]")
}
if values.is_empty() {
[]
} else {
let result = Array::make(values.length(), 0.0)
result[0] = values[0]
for i in 1.. Array[Double] {
if alpha <= 0.0 || alpha > 1.0 || beta <= 0.0 || beta > 1.0 {
abort("smoothing parameters must be in (0, 1]")
}
if values.is_empty() {
[]
} else if values.length() == 1 {
[values[0]]
} else {
let result = Array::make(values.length(), 0.0)
let mut level = values[0]
let mut trend = values[1] - values[0]
result[0] = level
for i in 1.. Array[Double] {
if values.length() != smoothed.length() {
abort("series lengths must match")
}
Array::makei(values.length(), i => values[i] - smoothed[i])
}
///|
pub fn smoothing_rmse(
values : Array[Double],
smoothed : Array[Double],
) -> Double {
let residuals = smoothing_residuals(values, smoothed)
if residuals.is_empty() {
0.0
} else {
(residuals.fold(init=0.0, (total, value) => total + value * value) /
residuals.length().to_double()).sqrt()
}
}
///|
pub fn smoothing_mae(
values : Array[Double],
smoothed : Array[Double],
) -> Double {
let residuals = smoothing_residuals(values, smoothed)
if residuals.is_empty() {
0.0
} else {
residuals.fold(init=0.0, (total, value) => total + value.abs()) /
residuals.length().to_double()
}
}
///|
pub fn quantile_rank(values : Array[Double], value : Double) -> Double {
if values.is_empty() {
0.0
} else {
values
.fold(init=0, (count, item) => if item <= value { count + 1 } else { count })
.to_double() /
values.length().to_double()
}
}
///|
pub fn exceedance_probability(
values : Array[Double],
threshold : Double,
) -> Double {
if values.is_empty() {
0.0
} else {
values
.fold(init=0, (count, value) => {
if value > threshold {
count + 1
} else {
count
}
})
.to_double() /
values.length().to_double()
}
}
///|
pub fn empirical_tail_mean(
values : Array[Double],
threshold : Double,
) -> Double {
let tail = values.filter(value => value > threshold)
if tail.is_empty() {
threshold
} else {
tail.fold(init=0.0, (total, value) => total + value) /
tail.length().to_double()
}
}
///|
pub fn conditional_exceedance_mean(
values : Array[Double],
threshold : Double,
) -> Double {
empirical_tail_mean(values, threshold) - threshold
}
///|
pub fn percentile_exceedance(
values : Array[Double],
threshold : Double,
percentile : Double,
) -> Double {
if percentile < 0.0 || percentile > 1.0 {
abort("percentile must be between zero and one")
}
let tail = values.filter(value => value > threshold)
if tail.is_empty() {
threshold
} else {
let average = tail.fold(init=0.0, (total, value) => total + value) /
tail.length().to_double()
threshold + (average - threshold) * percentile
}
}
///|
pub struct CapacityPlan {
baseline : Double
peak : Double
headroom : Double
target : Double
required_capacity : Double
utilization : Double
breach : Bool
}
///|
pub fn capacity_plan(
observations : Array[Double],
target_utilization : Double,
safety_factor : Double,
) -> CapacityPlan {
if target_utilization <= 0.0 ||
target_utilization > 1.0 ||
safety_factor < 0.0 {
abort("invalid capacity planning parameters")
}
let baseline = if observations.is_empty() {
0.0
} else {
observations.fold(init=0.0, (total, value) => total + value) /
observations.length().to_double()
}
let peak = if observations.is_empty() {
0.0
} else {
observations.fold(init=0.0, (maximum, value) => maximum.max(value))
}
let target = peak * (1.0 + safety_factor)
let required_capacity = if target_utilization == 0.0 {
target
} else {
target / target_utilization
}
let utilization = if required_capacity == 0.0 {
0.0
} else {
peak / required_capacity
}
{
baseline,
peak,
headroom: required_capacity - peak,
target,
required_capacity,
utilization,
breach: utilization > target_utilization,
}
}
///|
pub fn capacity_headroom(plan : CapacityPlan) -> Double {
plan.headroom
}
///|
pub fn capacity_risk(plan : CapacityPlan) -> Double {
if plan.required_capacity == 0.0 {
0.0
} else {
(plan.peak / plan.required_capacity).min(1.0)
}
}
///|
pub fn capacity_scale_factor(plan : CapacityPlan) -> Double {
if plan.baseline <= 0.0 {
1.0
} else {
plan.required_capacity / plan.baseline
}
}
///|
pub fn capacity_breach(plan : CapacityPlan) -> Bool {
plan.breach
}
///|
pub fn capacity_forecast(
observations : Array[Double],
horizon : Int,
target_utilization : Double,
safety_factor : Double,
) -> Array[Double] {
let forecast = forecast_linear(observations, horizon)
let plan = capacity_plan(observations, target_utilization, safety_factor)
forecast_values(forecast).map(value => value.max(plan.required_capacity))
}
///|
pub struct ReliabilityBudget {
target : Double
observed : Double
remaining : Double
burn_rate : Double
consumed_fraction : Double
status : String
}
///|
pub fn reliability_budget(
window : TelemetryWindow,
target : Double,
) -> ReliabilityBudget {
if target < 0.0 || target >= 1.0 {
abort("target must be in [0, 1)")
}
let observed = telemetry_window_availability(window)
let remaining = telemetry_window_error_budget(window, target)
let budget = (1.0 - target) * telemetry_window_duration(window)
let consumed = if budget == 0.0 {
0.0
} else {
(1.0 - observed) * telemetry_window_duration(window) / budget
}
let burn = telemetry_window_burn_rate(window, target)
let status = if burn > 2.0 {
"exhausted"
} else if burn > 1.0 {
"burning"
} else {
"safe"
}
{
target,
observed,
remaining,
burn_rate: burn,
consumed_fraction: consumed,
status,
}
}
///|
pub fn budget_is_exhausted(budget : ReliabilityBudget) -> Bool {
budget.status == "exhausted"
}
///|
pub fn budget_remaining(budget : ReliabilityBudget) -> Double {
budget.remaining
}
///|
pub fn budget_consumed(budget : ReliabilityBudget) -> Double {
budget.consumed_fraction
}
///|
pub fn budget_burn_rate(budget : ReliabilityBudget) -> Double {
budget.burn_rate
}
///|
pub fn budget_status(budget : ReliabilityBudget) -> String {
budget.status
}
///|
pub fn budget_projection(
budget : ReliabilityBudget,
future_windows : Int,
) -> Double {
if future_windows < 0 {
abort("future window count must be non-negative")
}
budget.remaining - budget.burn_rate * future_windows.to_double()
}
///|
pub fn budget_recovery_needed(budget : ReliabilityBudget) -> Double {
(budget.observed - budget.target).max(0.0)
}
///|
pub fn incident_burden(
incidents : Array[IncidentRecord],
window : Double,
) -> Double {
if window <= 0.0 {
abort("window must be positive")
}
incident_severity_weight(incidents) / window
}
///|
pub fn weighted_reliability_score(
availability : Double,
stability : Double,
incident_burden_value : Double,
target : Double,
) -> Double {
if availability < 0.0 ||
availability > 1.0 ||
stability < 0.0 ||
stability > 1.0 ||
target <= 0.0 ||
target > 1.0 {
abort("invalid reliability score inputs")
}
let target_score = (availability / target).min(1.0)
let burden_score = (1.0 - incident_burden_value).max(0.0).min(1.0)
(0.55 * target_score + 0.30 * stability + 0.15 * burden_score).min(1.0)
}
///|
pub fn score_label(score : Double) -> String {
if score >= 0.90 {
"excellent"
} else if score >= 0.75 {
"good"
} else if score >= 0.50 {
"watch"
} else {
"poor"
}
}
///|
pub fn score_gap(score : Double, target : Double) -> Double {
(target - score).max(0.0)
}
///|
pub fn score_to_percent(score : Double) -> Double {
score.max(0.0).min(1.0) * 100.0
}
///|
pub fn score_is_passing(score : Double, target : Double) -> Bool {
score >= target
}
///|
pub fn score_checksum(scores : Array[Double]) -> Double {
scores.fold(init=0.0, (total, score) => total + score)
}