[CI] Add metrics name linter (#2774)

Signed-off-by: Aviv Litman <alitman@redhat.com>
This commit is contained in:
Aviv Litman 2023-07-02 21:54:38 +03:00 committed by GitHub
parent 6ed8f87527
commit 9e37493b93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 247 additions and 2 deletions

View File

@ -21,7 +21,8 @@
goveralls \
release-description \
bazel-generate bazel-build bazel-build-images bazel-push-images \
fossa
fossa \
lint-metrics
DOCKER?=1
ifeq (${DOCKER}, 1)
@ -79,7 +80,7 @@ test-functional: build-functest
./hack/build/run-functional-tests.sh ${WHAT} "${TEST_ARGS}"
# test-lint runs gofmt and golint tests against src files
test-lint:
test-lint: lint-metrics
${DO_BAZ} "./hack/build/run-lint-checks.sh"
"./hack/ci/language.sh"
@ -166,6 +167,9 @@ build-docgen:
fossa:
${DO_BAZ} "FOSSA_TOKEN_FILE=${FOSSA_TOKEN_FILE} PULL_BASE_REF=${PULL_BASE_REF} CI=${CI} ./hack/fossa.sh"
lint-metrics:
./hack/ci/prom_metric_linter.sh --operator-name="kubevirt" --sub-operator-name="cdi"
help:
@echo "Usage: make [Targets ...]"
@echo " all "

1
go.mod
View File

@ -20,6 +20,7 @@ require (
github.com/klauspost/compress v1.14.2
github.com/kubernetes-csi/external-snapshotter/client/v6 v6.0.1
github.com/kubernetes-csi/lib-volume-populator v1.2.0
github.com/kubevirt/monitoring/pkg/metrics/parser v0.0.0-20230627123556-81a891d4462a
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.24.1
github.com/openshift/api v0.0.0-20230406152840-ce21e3fe5da2

2
go.sum
View File

@ -846,6 +846,8 @@ github.com/kubernetes-csi/external-snapshotter/client/v6 v6.0.1 h1:OqBS3UAo3eGWp
github.com/kubernetes-csi/external-snapshotter/client/v6 v6.0.1/go.mod h1:tnHiLn3P10N95fjn7O40QH5ovN0EFGAxqdTpUMrX6bU=
github.com/kubernetes-csi/lib-volume-populator v1.2.0 h1:7ooY7P/5xEMNKQS1NwcqipUF1FMD2uGBjp13UGQmGpY=
github.com/kubernetes-csi/lib-volume-populator v1.2.0/go.mod h1:euAJwBP1NcKCm4ifQLmPgwJvlakPjGLDbbSvchlUr3I=
github.com/kubevirt/monitoring/pkg/metrics/parser v0.0.0-20230627123556-81a891d4462a h1:cdX+oxWw1lJDS3EchP+7Oz1XbErk4r7ffVJu1b1MKgI=
github.com/kubevirt/monitoring/pkg/metrics/parser v0.0.0-20230627123556-81a891d4462a/go.mod h1:qGj2agzgwQ27nYhP3xhLs+IBzE5+ALNUg8bDfMcwPqo=
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/leanovate/gopter v0.2.4/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=

68
hack/ci/prom_metric_linter.sh Executable file
View File

@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# This file is part of the KubeVirt project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright 2023 Red Hat, Inc.
#
#
set -e
linter_image_tag="v0.0.1"
PROJECT_ROOT="$(readlink -e "$(dirname "${BASH_SOURCE[0]}")"/../../)"
export METRICS_COLLECTOR_PATH="${METRICS_COLLECTOR_PATH:-${PROJECT_ROOT}/tools/prom-metrics-collector}"
if [[ ! -d "$METRICS_COLLECTOR_PATH" ]]; then
echo "Invalid METRICS_COLLECTOR_PATH: $METRICS_COLLECTOR_PATH is not a valid directory path"
exit 1
fi
# Parse command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--operator-name=*)
operator_name="${1#*=}"
shift
;;
--sub-operator-name=*)
sub_operator_name="${1#*=}"
shift
;;
*)
echo "Invalid argument: $1"
exit 1
;;
esac
done
# Get the metrics list
go build -o _out/prom-metrics-collector "$METRICS_COLLECTOR_PATH/..."
json_output=$(_out/prom-metrics-collector 2>/dev/null)
# Select container runtime
source "${PROJECT_ROOT}"/hack/build/common.sh
# Run the linter by using the prom-metrics-linter Docker container
errors=$($CDI_CRI run -i "quay.io/kubevirt/prom-metrics-linter:$linter_image_tag" \
--metric-families="$json_output" \
--operator-name="$operator_name" \
--sub-operator-name="$sub_operator_name" 2>/dev/null)
# Check if there were any errors, if yes print and fail
if [[ $errors != "" ]]; then
echo "$errors"
exit 1
fi

View File

@ -0,0 +1,78 @@
/*
* This file is part of the KubeVirt project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2023 Red Hat, Inc.
*
*/
package main
import (
parser "github.com/kubevirt/monitoring/pkg/metrics/parser"
"kubevirt.io/containerized-data-importer/pkg/monitoring"
dto "github.com/prometheus/client_model/go"
)
// excludedMetrics defines the metrics to ignore,
// open issue:https://github.com/kubevirt/containerized-data-importer/issues/2773
// Do not add metrics to this list!
var excludedMetrics = map[string]struct{}{
"clone_progress": {},
"kubevirt_cdi_operator_up_total": {},
"kubevirt_cdi_incomplete_storageprofiles_total": {},
}
func recordRulesDescToMetricList(mdl []monitoring.RecordRulesDesc) []monitoring.MetricOpts {
res := make([]monitoring.MetricOpts, len(mdl))
for i, md := range mdl {
res[i] = metricDescriptionToMetric(md)
}
return res
}
func metricDescriptionToMetric(rrd monitoring.RecordRulesDesc) monitoring.MetricOpts {
return monitoring.MetricOpts{
Name: rrd.Opts.Name,
Help: rrd.Opts.Help,
Type: rrd.Opts.Type,
}
}
// ReadMetrics read and parse the metrics to a MetricFamily
func ReadMetrics() []*dto.MetricFamily {
cdiMetrics := recordRulesDescToMetricList(monitoring.GetRecordRulesDesc(""))
for _, opts := range monitoring.MetricOptsList {
cdiMetrics = append(cdiMetrics, opts)
}
metricsList := make([]parser.Metric, len(cdiMetrics))
var metricFamily []*dto.MetricFamily
for i, cdiMetric := range cdiMetrics {
metricsList[i] = parser.Metric{
Name: cdiMetric.Name,
Help: cdiMetric.Help,
Type: cdiMetric.Type,
}
}
for _, cdiMetric := range metricsList {
// Remove ignored metrics from all rules
if _, isExcludedMetric := excludedMetrics[cdiMetric.Name]; !isExcludedMetric {
mf := parser.CreateMetricFamily(cdiMetric)
metricFamily = append(metricFamily, mf)
}
}
return metricFamily
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of the KubeVirt project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2023 Red Hat, Inc.
*
*/
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
metricFamilies := ReadMetrics()
jsonBytes, err := json.Marshal(metricFamilies)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(string(jsonBytes)) // Write the JSON string to standard output
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of the KubeVirt project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2023 Red Hat, Inc.
*
*/
package parser
import (
dto "github.com/prometheus/client_model/go"
)
// Metric represents a Prometheus metric
type Metric struct {
Name string `json:"name,omitempty"`
Help string `json:"help,omitempty"`
Type string `json:"type,omitempty"`
}
// Set the correct metric type for creating MetricFamily
func CreateMetricFamily(m Metric) *dto.MetricFamily {
metricType := dto.MetricType_UNTYPED
switch m.Type {
case "Counter":
metricType = dto.MetricType_COUNTER
case "Gauge":
metricType = dto.MetricType_GAUGE
case "Histogram":
metricType = dto.MetricType_HISTOGRAM
case "Summary":
metricType = dto.MetricType_SUMMARY
}
return &dto.MetricFamily{
Name: &m.Name,
Help: &m.Help,
Type: &metricType,
}
}

3
vendor/modules.txt vendored
View File

@ -309,6 +309,9 @@ github.com/kubernetes-csi/external-snapshotter/client/v6/clientset/versioned/typ
# github.com/kubernetes-csi/lib-volume-populator v1.2.0
## explicit; go 1.18
github.com/kubernetes-csi/lib-volume-populator/populator-machinery
# github.com/kubevirt/monitoring/pkg/metrics/parser v0.0.0-20230627123556-81a891d4462a
## explicit; go 1.20
github.com/kubevirt/monitoring/pkg/metrics/parser
# github.com/mailru/easyjson v0.7.7
## explicit; go 1.12
github.com/mailru/easyjson/buffer