Functional Weave
Code in Rust

monitor.mttr@1.0.0

vectors.json

5,312 bytes · view raw

[
  {"name": "two resolved incidents in a day", "args": [[{"start": 1000, "end": 1600, "durationSeconds": 600, "worst": "down", "checks": 10}, {"start": 5000, "end": 5300, "durationSeconds": 300, "worst": "degraded", "checks": 5}], 0, 86400], "expect": {"incidents": 2, "resolved": 2, "downtimeSeconds": 900, "mttrSeconds": 450, "mtbfSeconds": 42750, "longestSeconds": 600}},
  {"name": "no incidents: no MTTR and no MTBF", "args": [[], 0, 86400], "expect": {"incidents": 0, "resolved": 0, "downtimeSeconds": 0, "mttrSeconds": null, "mtbfSeconds": null, "longestSeconds": 0}},
  {"name": "an incident that began before the window: downtime clipped, MTTR uses the full duration", "args": [[{"start": -600, "end": 600, "durationSeconds": 1200, "worst": "down", "checks": 1}], 0, 86400], "expect": {"incidents": 1, "resolved": 1, "downtimeSeconds": 600, "mttrSeconds": 1200, "mtbfSeconds": 85800, "longestSeconds": 1200}},
  {"name": "an ongoing incident clipped at the window end counts but has no repair time", "args": [[{"start": 86000, "end": null, "durationSeconds": 1000, "worst": "down", "checks": 3}], 0, 86400], "expect": {"incidents": 1, "resolved": 0, "downtimeSeconds": 400, "mttrSeconds": null, "mtbfSeconds": 86000, "longestSeconds": 1000}},
  {"name": "an incident ending exactly at from and one starting exactly at to are outside the window", "args": [[{"start": -600, "end": 0, "durationSeconds": 600, "worst": "down", "checks": 1}, {"start": 86400, "end": 86500, "durationSeconds": 100, "worst": "down", "checks": 1}], 0, 86400], "expect": {"incidents": 0, "resolved": 0, "downtimeSeconds": 0, "mttrSeconds": null, "mtbfSeconds": null, "longestSeconds": 0}},
  {"name": "mean repair time and MTBF round half up", "args": [[{"start": 0, "end": 100, "durationSeconds": 100, "worst": "down", "checks": 1}, {"start": 200, "end": 301, "durationSeconds": 101, "worst": "down", "checks": 1}], 0, 1000], "expect": {"incidents": 2, "resolved": 2, "downtimeSeconds": 201, "mttrSeconds": 101, "mtbfSeconds": 400, "longestSeconds": 101}},
  {"name": "a mix of resolved and ongoing: MTTR only averages the resolved one", "args": [[{"start": 100, "end": 200, "durationSeconds": 100, "worst": "down", "checks": 1}, {"start": 500, "end": null, "durationSeconds": 300, "worst": "down", "checks": 1}], 0, 1000], "expect": {"incidents": 2, "resolved": 1, "downtimeSeconds": 400, "mttrSeconds": 100, "mtbfSeconds": 300, "longestSeconds": 300}},
  {"name": "a zero-length ongoing incident starting at from counts", "args": [[{"start": 0, "end": null, "durationSeconds": 0, "worst": "down", "checks": 1}], 0, 100], "expect": {"incidents": 1, "resolved": 0, "downtimeSeconds": 0, "mttrSeconds": null, "mtbfSeconds": 100, "longestSeconds": 0}},
  {"name": "an incident covering the whole window leaves no time between failures", "args": [[{"start": -100, "end": 200, "durationSeconds": 300, "worst": "down", "checks": 1}], 0, 100], "expect": {"incidents": 1, "resolved": 1, "downtimeSeconds": 100, "mttrSeconds": 300, "mtbfSeconds": 0, "longestSeconds": 300}},
  {"name": "MTBF of a third rounds down below a half", "args": [[{"start": 10, "end": 10, "durationSeconds": 0, "worst": "down", "checks": 1}, {"start": 20, "end": 20, "durationSeconds": 0, "worst": "down", "checks": 1}, {"start": 30, "end": 30, "durationSeconds": 0, "worst": "down", "checks": 1}], 0, 100], "expect": {"incidents": 3, "resolved": 3, "downtimeSeconds": 0, "mttrSeconds": 0, "mtbfSeconds": 33, "longestSeconds": 0}},
  {"name": "an empty window counts nothing", "args": [[{"start": 0, "end": 10, "durationSeconds": 10, "worst": "down", "checks": 1}], 50, 50], "expect": {"incidents": 0, "resolved": 0, "downtimeSeconds": 0, "mttrSeconds": null, "mtbfSeconds": null, "longestSeconds": 0}},
  {"name": "back-to-back incidents touching are allowed", "args": [[{"start": 0, "end": 10, "durationSeconds": 10, "worst": "down", "checks": 1}, {"start": 10, "end": 30, "durationSeconds": 20, "worst": "down", "checks": 1}], 0, 100], "expect": {"incidents": 2, "resolved": 2, "downtimeSeconds": 30, "mttrSeconds": 15, "mtbfSeconds": 35, "longestSeconds": 20}},
  {"name": "from after to is an error", "args": [[], 100, 0], "expectError": "from must not be after to"},
  {"name": "overlapping incidents are an error", "args": [[{"start": 0, "end": 100, "durationSeconds": 100, "worst": "down", "checks": 1}, {"start": 50, "end": 150, "durationSeconds": 100, "worst": "down", "checks": 1}], 0, 1000], "expectError": "incidents must be in time order and must not overlap"},
  {"name": "an incident ending before it starts is an error", "args": [[{"start": 100, "end": 50, "durationSeconds": 0, "worst": "down", "checks": 1}], 0, 1000], "expectError": "incident end must not be before its start"},
  {"name": "a duration that disagrees with end - start is an error", "args": [[{"start": 0, "end": 100, "durationSeconds": 50, "worst": "down", "checks": 1}], 0, 1000], "expectError": "durationSeconds must equal end - start"},
  {"name": "a negative duration is an error", "args": [[{"start": 0, "end": null, "durationSeconds": -5, "worst": "down", "checks": 1}], 0, 1000], "expectError": "durationSeconds must not be negative"},
  {"name": "a fractional window bound is an error", "args": [[], 0.5, 100], "expectError": "from and to must be whole seconds"}
]