use slokit::generate::{generate_rules, generate_rules_with, GenerateOptions};
use slokit::spec::Spec;
const SAMPLE: &str = include_str!("fixtures/sample.yaml");
fn sample_spec() -> Spec {
Spec::from_yaml(SAMPLE).expect("fixture parses")
}
fn redact_version(yaml: String) -> String {
yaml.replace(env!("CARGO_PKG_VERSION"), "[VERSION]")
}
#[test]
fn prometheus_rules_snapshot() {
let rules = generate_rules(&sample_spec()).unwrap();
let yaml = redact_version(rules.to_prometheus_yaml().unwrap());
insta::assert_snapshot!("prometheus_rules", yaml);
}
#[test]
fn operator_rules_snapshot() {
let spec = sample_spec();
let rules = generate_rules(&spec).unwrap();
let yaml = redact_version(rules.to_operator_yaml(&spec.service, &spec.labels).unwrap());
insta::assert_snapshot!("operator_rules", yaml);
}
#[test]
fn page_thresholds_are_factor_times_budget() {
let yaml = generate_rules(&sample_spec())
.unwrap()
.to_prometheus_yaml()
.unwrap();
assert!(yaml.contains("(14.4 * 0.001)"));
assert!(yaml.contains("(6 * 0.001)"));
assert!(yaml.contains("(3 * 0.001)"));
assert!(yaml.contains("(1 * 0.001)"));
}
#[test]
fn emits_expected_group_count() {
let rules = generate_rules(&sample_spec()).unwrap();
assert_eq!(rules.groups.len(), 6);
}
#[test]
fn raw_sli_period_rule_is_present() {
let yaml = generate_rules(&sample_spec())
.unwrap()
.to_prometheus_yaml()
.unwrap();
assert!(yaml.contains("slo:sli_error:ratio_rate30d"));
assert!(yaml.contains("sloth_slo: requests-latency"));
}
#[test]
fn custom_alert_windows_replace_the_default_table() {
let spec = Spec::from_yaml(
r#"
service: s
slos:
- name: a
objective: 99.9
sli:
raw:
error_ratio_query: r[{{.window}}]
alerting:
labels: { severity: page }
windows:
- severity: page
long: 30m
short: 10m
factor: 10
- severity: ticket
long: 12h
short: 1h
factor: 2
"#,
)
.unwrap();
let yaml = generate_rules(&spec).unwrap().to_prometheus_yaml().unwrap();
assert!(yaml.contains("slo:sli_error:ratio_rate30m"));
assert!(yaml.contains("(10 * 0.001)"));
assert!(yaml.contains("(2 * 0.001)"));
assert!(!yaml.contains("(14.4 * 0.001)"));
assert!(!yaml.contains("ratio_rate5m"));
assert!(!yaml.contains("ratio_rate3d"));
assert!(yaml.contains("sum_over_time(slo:sli_error:ratio_rate10m"));
assert!(yaml.contains("slo:sli_error:ratio_rate10m{sloth_id=\"s-a\""));
}
#[test]
fn non_default_period_scales_the_default_windows() {
let spec = Spec::from_yaml(
r#"
service: s
slos:
- name: a
objective: 99.9
period: 90d
sli:
raw:
error_ratio_query: r[{{.window}}]
alerting:
labels: { severity: page }
"#,
)
.unwrap();
let yaml = generate_rules(&spec).unwrap().to_prometheus_yaml().unwrap();
assert!(yaml.contains("slo:sli_error:ratio_rate3h"));
assert!(yaml.contains("slo:sli_error:ratio_rate15m"));
assert!(yaml.contains("slo:sli_error:ratio_rate9d"));
assert!(yaml.contains("slo:sli_error:ratio_rate90d"));
assert!(!yaml.contains("ratio_rate5m"));
assert!(yaml.contains("slo:sli_error:ratio_rate15m{sloth_id=\"s-a\""));
}
#[test]
fn period_scaling_can_be_disabled() {
let spec = Spec::from_yaml(
r#"
service: s
slos:
- name: a
objective: 99.9
period: 90d
sli:
raw:
error_ratio_query: r[{{.window}}]
alerting:
labels: { severity: page }
"#,
)
.unwrap();
let opts = GenerateOptions {
period_aware: false,
..GenerateOptions::default()
};
let yaml = generate_rules_with(&spec, &opts)
.unwrap()
.to_prometheus_yaml()
.unwrap();
assert!(yaml.contains("slo:sli_error:ratio_rate5m"));
assert!(yaml.contains("slo:sli_error:ratio_rate3d"));
assert!(yaml.contains("slo:sli_error:ratio_rate90d"));
assert!(!yaml.contains("ratio_rate15m"));
}
#[test]
fn default_period_output_is_unchanged_by_scaling() {
let aware = generate_rules(&sample_spec())
.unwrap()
.to_prometheus_yaml()
.unwrap();
let opts = GenerateOptions {
period_aware: false,
..GenerateOptions::default()
};
let unaware = generate_rules_with(&sample_spec(), &opts)
.unwrap()
.to_prometheus_yaml()
.unwrap();
assert_eq!(aware, unaware);
}