From 130e0ea5f02ba6d6238b530fdee90fb0c36462a5 Mon Sep 17 00:00:00 2001 From: Haleygo Date: Fri, 13 Oct 2023 19:54:33 +0800 Subject: [PATCH] vmalert-tool: implement unittest (#4789) 1. split package rule under /app/vmalert, expose needed objects 2. add vmalert-tool with unittest subcmd https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2945 --- Makefile | 1 + app/vmalert-tool/Makefile | 103 ++++ app/vmalert-tool/README.md | 244 ++++++++++ app/vmalert-tool/main.go | 54 +++ app/vmalert-tool/unittest/alerting.go | 19 + app/vmalert-tool/unittest/input.go | 182 +++++++ app/vmalert-tool/unittest/input_test.go | 93 ++++ app/vmalert-tool/unittest/recording.go | 92 ++++ .../testdata/disable-group-label.yaml | 43 ++ .../unittest/testdata/failed-test.yaml | 49 ++ .../unittest/testdata/long-period.yaml | 30 ++ app/vmalert-tool/unittest/testdata/rules.yaml | 39 ++ app/vmalert-tool/unittest/testdata/test1.yaml | 99 ++++ app/vmalert-tool/unittest/testdata/test2.yaml | 46 ++ app/vmalert-tool/unittest/type.go | 83 ++++ app/vmalert-tool/unittest/unittest.go | 443 ++++++++++++++++++ app/vmalert-tool/unittest/unittest_test.go | 47 ++ app/vmalert/README.md | 5 + app/vmalert/datasource/faker.go | 131 ++++++ app/vmalert/main.go | 12 +- app/vmalert/main_test.go | 14 +- app/vmalert/manager.go | 117 +---- app/vmalert/manager_test.go | 101 ++-- app/vmalert/notifier/faker.go | 59 +++ app/vmalert/remotewrite/client.go | 322 +++++++++++++ .../{remotewrite_test.go => client_test.go} | 0 app/vmalert/remotewrite/debug_client.go | 97 ++++ app/vmalert/remotewrite/debug_client_test.go | 50 ++ app/vmalert/remotewrite/remotewrite.go | 321 +------------ app/vmalert/replay.go | 107 +---- app/vmalert/replay_test.go | 80 +--- app/vmalert/rule.go | 118 ----- app/vmalert/{ => rule}/alerting.go | 236 ++++------ app/vmalert/{ => rule}/alerting_test.go | 82 ++-- app/vmalert/{ => rule}/group.go | 215 +++++++-- app/vmalert/{ => rule}/group_test.go | 206 ++++++-- app/vmalert/{ => rule}/recording.go | 91 ++-- app/vmalert/{ => rule}/recording_test.go | 52 +- app/vmalert/rule/rule.go | 174 +++++++ app/vmalert/rule/rule_test.go | 81 ++++ .../{helpers_test.go => rule/test_helpers.go} | 271 ++--------- app/vmalert/{ => rule}/utils.go | 2 +- app/vmalert/{ => rule}/utils_test.go | 2 +- app/vmalert/rule_test.go | 100 ---- app/vmalert/web.go | 67 ++- app/vmalert/web.qtpl | 42 +- app/vmalert/web.qtpl.go | 64 +-- app/vmalert/web_test.go | 54 +-- app/vmalert/web_types.go | 242 +++++++++- app/vmalert/web_types_test.go | 23 + docs/Articles.md | 8 +- docs/BestPractices.md | 8 +- docs/CHANGELOG.md | 10 +- docs/CHANGELOG_2020.md | 8 +- docs/CHANGELOG_2021.md | 8 +- docs/CHANGELOG_2022.md | 8 +- docs/CaseStudies.md | 8 +- docs/FAQ.md | 8 +- docs/MetricsQL.md | 8 +- docs/PerTenantStatistic.md | 8 +- docs/Quick-Start.md | 8 +- docs/Release-Guide.md | 8 +- docs/Troubleshooting.md | 8 +- docs/enterprise.md | 2 +- docs/keyConcepts.md | 8 +- docs/relabeling.md | 8 +- docs/sd_configs.md | 8 +- docs/stream-aggregation.md | 2 +- docs/url-examples.md | 8 +- docs/vmalert-tool.md | 253 ++++++++++ docs/vmalert.md | 5 + docs/vmanomaly.md | 2 +- lib/promutils/duration.go | 8 + 73 files changed, 3952 insertions(+), 1663 deletions(-) create mode 100644 app/vmalert-tool/Makefile create mode 100644 app/vmalert-tool/README.md create mode 100644 app/vmalert-tool/main.go create mode 100644 app/vmalert-tool/unittest/alerting.go create mode 100644 app/vmalert-tool/unittest/input.go create mode 100644 app/vmalert-tool/unittest/input_test.go create mode 100644 app/vmalert-tool/unittest/recording.go create mode 100644 app/vmalert-tool/unittest/testdata/disable-group-label.yaml create mode 100644 app/vmalert-tool/unittest/testdata/failed-test.yaml create mode 100644 app/vmalert-tool/unittest/testdata/long-period.yaml create mode 100644 app/vmalert-tool/unittest/testdata/rules.yaml create mode 100644 app/vmalert-tool/unittest/testdata/test1.yaml create mode 100644 app/vmalert-tool/unittest/testdata/test2.yaml create mode 100644 app/vmalert-tool/unittest/type.go create mode 100644 app/vmalert-tool/unittest/unittest.go create mode 100644 app/vmalert-tool/unittest/unittest_test.go create mode 100644 app/vmalert/datasource/faker.go create mode 100644 app/vmalert/notifier/faker.go create mode 100644 app/vmalert/remotewrite/client.go rename app/vmalert/remotewrite/{remotewrite_test.go => client_test.go} (100%) create mode 100644 app/vmalert/remotewrite/debug_client.go create mode 100644 app/vmalert/remotewrite/debug_client_test.go delete mode 100644 app/vmalert/rule.go rename app/vmalert/{ => rule}/alerting.go (81%) rename app/vmalert/{ => rule}/alerting_test.go (94%) rename app/vmalert/{ => rule}/group.go (73%) rename app/vmalert/{ => rule}/group_test.go (74%) rename app/vmalert/{ => rule}/recording.go (68%) rename app/vmalert/{ => rule}/recording_test.go (86%) create mode 100644 app/vmalert/rule/rule.go create mode 100644 app/vmalert/rule/rule_test.go rename app/vmalert/{helpers_test.go => rule/test_helpers.go} (54%) rename app/vmalert/{ => rule}/utils.go (99%) rename app/vmalert/{ => rule}/utils_test.go (99%) delete mode 100644 app/vmalert/rule_test.go create mode 100644 app/vmalert/web_types_test.go create mode 100644 docs/vmalert-tool.md diff --git a/Makefile b/Makefile index 407525a26..75b338083 100644 --- a/Makefile +++ b/Makefile @@ -276,3 +276,4 @@ docs-sync: SRC=app/vmctl/README.md DST=docs/vmctl.md OLD_URL='/vmctl.html' ORDER=8 TITLE=vmctl $(MAKE) copy-docs SRC=app/vmgateway/README.md DST=docs/vmgateway.md OLD_URL='/vmgateway.html' ORDER=9 TITLE=vmgateway $(MAKE) copy-docs SRC=app/vmbackupmanager/README.md DST=docs/vmbackupmanager.md OLD_URL='/vmbackupmanager.html' ORDER=10 TITLE=vmbackupmanager $(MAKE) copy-docs + SRC=app/vmalert-tool/README.md DST=docs/vmalert-tool.md OLD_URL='' ORDER=12 TITLE=vmalert-tool $(MAKE) copy-docs diff --git a/app/vmalert-tool/Makefile b/app/vmalert-tool/Makefile new file mode 100644 index 000000000..dbb6b373a --- /dev/null +++ b/app/vmalert-tool/Makefile @@ -0,0 +1,103 @@ +# All these commands must run from repository root. + +vmalert-tool: + APP_NAME=vmalert-tool $(MAKE) app-local + +vmalert-tool-race: + APP_NAME=vmalert-tool RACE=-race $(MAKE) app-local + +vmalert-tool-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker + +vmalert-tool-pure-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-pure + +vmalert-tool-linux-amd64-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-linux-amd64 + +vmalert-tool-linux-arm-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-linux-arm + +vmalert-tool-linux-arm64-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-linux-arm64 + +vmalert-tool-linux-ppc64le-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-linux-ppc64le + +vmalert-tool-linux-386-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-linux-386 + +vmalert-tool-darwin-amd64-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-darwin-amd64 + +vmalert-tool-darwin-arm64-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-darwin-arm64 + +vmalert-tool-freebsd-amd64-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-freebsd-amd64 + +vmalert-tool-openbsd-amd64-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-openbsd-amd64 + +vmalert-tool-windows-amd64-prod: + APP_NAME=vmalert-tool $(MAKE) app-via-docker-windows-amd64 + +package-vmalert-tool: + APP_NAME=vmalert-tool $(MAKE) package-via-docker + +package-vmalert-tool-pure: + APP_NAME=vmalert-tool $(MAKE) package-via-docker-pure + +package-vmalert-tool-amd64: + APP_NAME=vmalert-tool $(MAKE) package-via-docker-amd64 + +package-vmalert-tool-arm: + APP_NAME=vmalert-tool $(MAKE) package-via-docker-arm + +package-vmalert-tool-arm64: + APP_NAME=vmalert-tool $(MAKE) package-via-docker-arm64 + +package-vmalert-tool-ppc64le: + APP_NAME=vmalert-tool $(MAKE) package-via-docker-ppc64le + +package-vmalert-tool-386: + APP_NAME=vmalert-tool $(MAKE) package-via-docker-386 + +publish-vmalert-tool: + APP_NAME=vmalert-tool $(MAKE) publish-via-docker + +vmalert-tool-linux-amd64: + APP_NAME=vmalert-tool CGO_ENABLED=1 GOOS=linux GOARCH=amd64 $(MAKE) app-local-goos-goarch + +vmalert-tool-linux-arm: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=linux GOARCH=arm $(MAKE) app-local-goos-goarch + +vmalert-tool-linux-arm64: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $(MAKE) app-local-goos-goarch + +vmalert-tool-linux-ppc64le: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le $(MAKE) app-local-goos-goarch + +vmalert-tool-linux-s390x: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=linux GOARCH=s390x $(MAKE) app-local-goos-goarch + +vmalert-tool-linux-386: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=linux GOARCH=386 $(MAKE) app-local-goos-goarch + +vmalert-tool-darwin-amd64: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 $(MAKE) app-local-goos-goarch + +vmalert-tool-darwin-arm64: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 $(MAKE) app-local-goos-goarch + +vmalert-tool-freebsd-amd64: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 $(MAKE) app-local-goos-goarch + +vmalert-tool-openbsd-amd64: + APP_NAME=vmalert-tool CGO_ENABLED=0 GOOS=openbsd GOARCH=amd64 $(MAKE) app-local-goos-goarch + +vmalert-tool-windows-amd64: + GOARCH=amd64 APP_NAME=vmalert-tool $(MAKE) app-local-windows-goarch + +vmalert-tool-pure: + APP_NAME=vmalert-tool $(MAKE) app-local-pure diff --git a/app/vmalert-tool/README.md b/app/vmalert-tool/README.md new file mode 100644 index 000000000..e25465275 --- /dev/null +++ b/app/vmalert-tool/README.md @@ -0,0 +1,244 @@ + +# vmalert-tool + +VMAlert command-line tool + +## Unit testing for rules + +You can use `vmalert-tool` to run unit tests for alerting and recording rules. +It will perform the following actions: +* sets up an isolated VictoriaMetrics instance; +* simulates the periodic ingestion of time series; +* queries the ingested data for recording and alerting rules evaluation like [vmalert](https://docs.victoriametrics.com/vmalert.html); +* checks whether the firing alerts or resulting recording rules match the expected results. + +See how to run vmalert-tool for unit test below: +``` +# Run vmalert-tool with one or multiple test files via --files cmd-line flag +./vmalert-tool unittest --files test1.yaml --files test2.yaml +``` + +vmalert-tool unittest is compatible with [Prometheus config format for tests](https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/#test-file-format) +except `promql_expr_test` field. Use `metricsql_expr_test` field name instead. The name is different because vmalert-tool +validates and executes [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html) expressions, +which aren't always backward compatible with [PromQL](https://prometheus.io/docs/prometheus/latest/querying/basics/). + +### Test file format + +The configuration format for files specified in `--files` cmd-line flag is the following: +``` +# Path to the files or http url containing [rule groups](https://docs.victoriametrics.com/vmalert.html#groups) configuration. +# Enterprise version of vmalert-tool supports S3 and GCS paths to rules. +rule_files: + [ - ] + +# The evaluation interval for rules specified in `rule_files` +[ evaluation_interval: | default = 1m ] + +# Groups listed below will be evaluated by order. +# Not All the groups need not be mentioned, if not, they will be evaluated by define order in rule_files. +group_eval_order: + [ - ] + +# The list of unit test files to be checked during evaluation. +tests: + [ - ] +``` + +#### `` + +``` +# Interval between samples for input series +interval: +# Time series to persist into the database according to configured before running tests. +input_series: + [ - ] + +# Name of the test group, optional +[ name: ] + +# Unit tests for alerting rules +alert_rule_test: + [ - ] + +# Unit tests for Metricsql expressions. +metricsql_expr_test: + [ - ] + +# External labels accessible for templating. +external_labels: + [ : ... ] + +``` + +#### `` + +``` +# series in the following format '{