Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
The pipeline's freshness alert fires whenever a sample crosses the threshold, which means a single slow minute pages somebody at three in the morning and the same alert clears and re-fires a dozen times during a real incident. The team wants to replay a day of samples through a proposed policy before enabling it.
Write evaluate_alerts(samples, threshold, breaches_to_fire, oks_to_clear).
Function to write
evaluate_alerts(samples: list[dict], threshold: float, breaches_to_fire: int, oks_to_clear: int) -> dictA dict with the fire and clear transitions in order, and the series still firing at the end.
How to approach it
Hold three things per series — firing, breach run, ok run — and change them in one place.
Sample cases
+ 2 held back until you submit
one real incident and one spike
A sustained breach that should fire, a single-sample spike that should not, and a flap in the middle.
Input
Argument 1
| series | at | value |
|---|---|---|
| api | 09:00 | 100 |
| api | 09:01 | 900 |
| api | 09:02 | 950 |
| api | 09:03 | 980 |
| api | 09:04 | 100 |
| api | 09:05 | 900 |
| api | 09:06 | 100 |
| api | 09:07 | 100 |
| db | 09:00 | 900 |
| db | 09:01 | 100 |
| db | 09:02 | 100 |
Argument 2
500Argument 3
2Argument 4
2Returns
{
'events': [
{
'series': 'api',
'at': '09:02',
'event': 'fired'
},
{
'series': 'api',
'at': '09:07',
'event': 'cleared'
}
],
'firing': []
}no samples
Nothing measured means no events and nothing firing, rather than an assumed healthy state.
Input
Argument 1
[] (empty list)
Argument 2
500Argument 3
2Argument 4
2Returns
{
'events': [],
'firing': []
}firing on the first breach
With no hysteresis at all, every crossing becomes an event — the behaviour being replaced.
Input
Argument 1
| series | at | value |
|---|---|---|
| api | 09:00 | 100 |
| api | 09:01 | 900 |
| api | 09:02 | 950 |
| api | 09:03 | 980 |
| api | 09:04 | 100 |
| api | 09:05 | 900 |
| api | 09:06 | 100 |
| api | 09:07 | 100 |
| db | 09:00 | 900 |
| db | 09:01 | 100 |
| db | 09:02 | 100 |
Argument 2
500Argument 3
1Argument 4
1Returns
{
'events': [
{
'series': 'api',
'at': '09:01',
'event': 'fired'
},
{
'series': 'api',
'at': '09:04',
'event': 'cleared'
},
{
'series': 'api',
'at': '09:05',
'event': 'fired'
},
{
'series': 'api',
'at': '09:06',
'event': 'cleared'
},
{
'series': 'db',
'at': '09:00',
'event': 'fired'
},
{
'series': 'db',
'at': '09:01',
'event': 'cleared'
}
],
'firing': []
}Constraints
breaches_to_fire consecutive breaches, and only when it is not already firing.oks_to_clear consecutive non-breaching samples, and only when it is firing.at order, compared as text, whatever order the samples arrive in.Worked example
The api series breaches at 09:01, 09:02 and 09:03. With two breaches required it fires at 09:02 — and produces nothing at 09:03, because it is already firing. The current implementation emits an event at all three, which is what turns one incident into a wall of identical pages.
At 09:05 the value crosses again for a single sample, with good samples either side. That is a spike, not an incident: the breach counter reaches one, the next good sample resets it to zero, and nobody is woken. The db series is the same shape at the very start of the window.
The clear is the mirror image and is the part people leave out. Clearing on the first good sample means a service oscillating around the threshold fires and clears repeatedly, and the resulting noise is why teams end up muting the alert that was supposed to protect them.
What this tests
An explicit state machine with two counters, and the understanding that an alert is a statement about a run of observations rather than about one. Reporting transitions rather than states is the same idea applied to the output.
evaluate_alerts(samples: list[dict], threshold: float, breaches_to_fire: int, oks_to_clear: int) -> dictSubmit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.