feno¶
Anomaly detector specifications, written as OpenSLO-shaped YAML in git, compiled into the alert rules your stack already evaluates, and replayed over history before they ship.
Status: three commands run against Prometheus
feno suggest --from-sli slis/ --url <endpoint> -o detectors/ drafts a
detector from an SLI already in the repository, feno backtest -f
detectors/ --url <endpoint> --from -30d replays it over history and
prints the report, and feno generate -f detectors/ -o rules/anomaly/
compiles the rule files, with --check as the drift gate. The ClickHouse
target is next. See the
README for what is being built
and in what order, and
spec.md for why.
The idea in one page¶
Anomaly detection on metrics is well understood and barely adopted, because the algorithms were never the hard part. Tuning them is. A band that pages forty times a month gets muted in a quarter, and nothing in the open source tool chain tells you that will happen before you merge it.
So feno is three commands over one specification.
suggest writes the first draft of that specification from an SLI the
repository already holds. It profiles the series over three weeks and decides
the fields nobody can fill in from the document alone, seasonality from the
autocorrelation at a day and at a week, the strategy from how spiky the series
is, and it puts the measurement behind every one of them in the draft as a
comment. The fields it cannot measure are left out so the defaults apply, and
a series too sparse or too spiky to band is refused with the number that says
so rather than drafted anyway. Nothing in it calls out to a model.
generate compiles a detector into recording and alerting rules for the
engine you already run, which means Prometheus and its compatible stores
first, and ClickHouse through
clickhouse-ruler after that.
There is no new service to operate and no anomaly score to learn to trust:
the output is rules a person can read at three in the morning.
backtest replays a detector over the last month of real history and reports
what it would have done. How many separate times it would have paged, for how
long, which series were responsible, and how much of it coincided with an
error budget actually burning. That report is the whole point. A detector that
never lined up with a real incident is a detector to delete, and the report
says that in those terms: how many of the paging episodes coincided with the
linked SLO's budget being spent, and how much of the paged wall clock did. A
detector that names no SLO says so rather than printing a zero, because an
overlap of zero over a budget that was read is the finding and the two must
not read alike.
A detector over its noise budget fails the build, and a detector that has to
stay over it for now carries a waiver in feno.yaml: a reason, and a date
it runs out on. Until that date the finding is still reported, named as
waived, and the build passes. After it the waiver is itself a finding and the
build fails, so the decision comes back to a reviewer instead of living on as
a raised number nobody remembers writing.
Why it is shaped this way¶
The specification is OpenSLO's, extended rather than replaced. A team that
already declared a DataSource and an SLI has already written down where
the metrics live and which query matters, so feno asks for neither again.
The long version, including the landscape it is answering and the decisions already settled, is in spec.md.