Finish implementation of stable metrics static analysis

Handle "DeprecatedVersion" field
Fix kube metrics framework path
Implement handling prometheus util functions for generating buckets
This commit is contained in:
Marek Siarkowicz 2019-08-16 14:12:08 +02:00
parent d6035f3e0d
commit 53fc6f9b58
6 changed files with 287 additions and 92 deletions

View File

@ -171,7 +171,6 @@ test/images/agnhost/pause
test/images/agnhost/serve-hostname
test/images/agnhost/webhook
test/images/pets/peer-finder
test/instrumentation
test/integration/apiserver
test/integration/apiserver/admissionwebhook
test/integration/auth

View File

@ -63,4 +63,5 @@ go_test(
srcs = ["main_test.go"],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = ["//vendor/github.com/prometheus/client_golang/prometheus:go_default_library"],
)

View File

@ -24,12 +24,14 @@ import (
"strconv"
"strings"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/component-base/metrics"
)
func decodeMetricCalls(fs []*ast.CallExpr, metricsImportName string) ([]metric, []error) {
func decodeMetricCalls(fs []*ast.CallExpr, metricsImportName, prometheusImportName string) ([]metric, []error) {
finder := metricDecoder{
metricsImportName: metricsImportName,
kubeMetricsImportName: metricsImportName,
prometheusImportName: prometheusImportName,
}
ms := make([]metric, 0, len(fs))
errors := []error{}
@ -45,7 +47,8 @@ func decodeMetricCalls(fs []*ast.CallExpr, metricsImportName string) ([]metric,
}
type metricDecoder struct {
metricsImportName string
kubeMetricsImportName string
prometheusImportName string
}
func (c *metricDecoder) decodeNewMetricCall(fc *ast.CallExpr) (metric, error) {
@ -60,7 +63,7 @@ func (c *metricDecoder) decodeNewMetricCall(fc *ast.CallExpr) (metric, error) {
if !ok {
return m, newDecodeErrorf(fc, errNotDirectCall)
}
if functionImport.String() != c.metricsImportName {
if functionImport.String() != c.kubeMetricsImportName {
return m, newDecodeErrorf(fc, errNotDirectCall)
}
switch functionName {
@ -157,7 +160,7 @@ func (c *metricDecoder) decodeOpts(expr ast.Expr) (metric, error) {
key := fmt.Sprintf("%v", kv.Key)
switch key {
case "Namespace", "Subsystem", "Name", "Help":
case "Namespace", "Subsystem", "Name", "Help", "DeprecatedVersion":
k, ok := kv.Value.(*ast.BasicLit)
if !ok {
return m, newDecodeErrorf(expr, errNonStringAttribute)
@ -173,18 +176,20 @@ func (c *metricDecoder) decodeOpts(expr ast.Expr) (metric, error) {
m.Subsystem = value
case "Name":
m.Name = value
case "DeprecatedVersion":
m.DeprecatedVersion = value
case "Help":
m.Help = value
}
case "Buckets":
buckets, err := decodeBuckets(kv)
buckets, err := c.decodeBuckets(kv.Value)
if err != nil {
return m, err
}
sort.Float64s(buckets)
m.Buckets = buckets
case "StabilityLevel":
level, err := decodeStabilityLevel(kv.Value, c.metricsImportName)
level, err := decodeStabilityLevel(kv.Value, c.kubeMetricsImportName)
if err != nil {
return m, err
}
@ -196,13 +201,46 @@ func (c *metricDecoder) decodeOpts(expr ast.Expr) (metric, error) {
return m, nil
}
func decodeBuckets(kv *ast.KeyValueExpr) ([]float64, error) {
cl, ok := kv.Value.(*ast.CompositeLit)
if !ok {
return nil, newDecodeErrorf(kv, errBuckets)
func (c *metricDecoder) decodeBuckets(expr ast.Expr) ([]float64, error) {
switch v := expr.(type) {
case *ast.CompositeLit:
return decodeListOfFloats(v.Elts)
case *ast.SelectorExpr:
variableName := v.Sel.String()
importName, ok := v.X.(*ast.Ident)
if ok && importName.String() == c.prometheusImportName && variableName == "DefBuckets" {
return prometheus.DefBuckets, nil
}
case *ast.CallExpr:
se, ok := v.Fun.(*ast.SelectorExpr)
if !ok {
return nil, newDecodeErrorf(v, errBuckets)
}
functionName := se.Sel.String()
functionImport, ok := se.X.(*ast.Ident)
if !ok {
return nil, newDecodeErrorf(v, errBuckets)
}
if functionImport.String() != c.prometheusImportName {
return nil, newDecodeErrorf(v, errBuckets)
}
firstArg, secondArg, thirdArg, err := decodeBucketArguments(v)
if err != nil {
return nil, err
}
switch functionName {
case "LinearBuckets":
return prometheus.LinearBuckets(firstArg, secondArg, thirdArg), nil
case "ExponentialBuckets":
return prometheus.ExponentialBuckets(firstArg, secondArg, thirdArg), nil
}
}
buckets := make([]float64, len(cl.Elts))
for i, elt := range cl.Elts {
return nil, newDecodeErrorf(expr, errBuckets)
}
func decodeListOfFloats(exprs []ast.Expr) ([]float64, error) {
buckets := make([]float64, len(exprs))
for i, elt := range exprs {
bl, ok := elt.(*ast.BasicLit)
if !ok {
return nil, newDecodeErrorf(bl, errBuckets)
@ -219,6 +257,37 @@ func decodeBuckets(kv *ast.KeyValueExpr) ([]float64, error) {
return buckets, nil
}
func decodeBucketArguments(fc *ast.CallExpr) (float64, float64, int, error) {
if len(fc.Args) != 3 {
return 0, 0, 0, newDecodeErrorf(fc, errBuckets)
}
strArgs := make([]string, len(fc.Args))
for i, elt := range fc.Args {
bl, ok := elt.(*ast.BasicLit)
if !ok {
return 0, 0, 0, newDecodeErrorf(bl, errBuckets)
}
if bl.Kind != token.FLOAT && bl.Kind != token.INT {
return 0, 0, 0, newDecodeErrorf(bl, errBuckets)
}
strArgs[i] = bl.Value
}
firstArg, err := strconv.ParseFloat(strArgs[0], 64)
if err != nil {
return 0, 0, 0, newDecodeErrorf(fc.Args[0], errBuckets)
}
secondArg, err := strconv.ParseFloat(strArgs[1], 64)
if err != nil {
return 0, 0, 0, newDecodeErrorf(fc.Args[1], errBuckets)
}
thirdArg, err := strconv.ParseInt(strArgs[2], 10, 64)
if err != nil {
return 0, 0, 0, newDecodeErrorf(fc.Args[2], errBuckets)
}
return firstArg, secondArg, int(thirdArg), nil
}
func decodeStabilityLevel(expr ast.Expr, metricsFrameworkImportName string) (*metrics.StabilityLevel, error) {
se, ok := expr.(*ast.SelectorExpr)
if !ok {

View File

@ -30,9 +30,9 @@ const (
errInvalidNewMetricCall = "Invalid new metric call, please ensure code compiles"
errNonStringAttribute = "Non string attribute it not supported"
errFieldNotSupported = "Field %s is not supported"
errBuckets = "Buckets were not set to list of floats"
errBuckets = "Buckets should be set to list of floats, result from function call of prometheus.LinearBuckets or prometheus.ExponentialBuckets"
errLabels = "Labels were not set to list of strings"
errImport = `Importing through "." metrics framework is not supported`
errImport = `Importing using "." is not supported`
)
type decodeError struct {

View File

@ -31,9 +31,12 @@ import (
)
const (
metricFrameworkPath = `"k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"`
// Should equal to final directory name of metricFrameworkPath
defaultFrameworkImportName = "metrics"
kubeMetricImportPath = `"k8s.io/component-base/metrics"`
// Should equal to final directory name of kubeMetricImportPath
kubeMetricsDefaultImportName = "metrics"
prometheusImportPath = `"github.com/prometheus/client_golang/prometheus"`
// Should equal to final directory name of kubeMetricImportPath
prometheusDefaultImportName = "prometheus"
)
func main() {
@ -67,7 +70,7 @@ func main() {
}
func searchPathForStableMetrics(path string) ([]metric, []error) {
ms := []metric{}
metrics := []metric{}
errors := []error{}
err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if strings.HasPrefix(path, "vendor") {
@ -78,13 +81,13 @@ func searchPathForStableMetrics(path string) ([]metric, []error) {
}
ms, es := searchFileForStableMetrics(path, nil)
errors = append(errors, es...)
ms = append(ms, ms...)
metrics = append(metrics, ms...)
return nil
})
if err != nil {
errors = append(errors, err)
}
return ms, errors
return metrics, errors
}
// Pass either only filename of existing file or src including source code in any format and a filename that it comes from
@ -94,26 +97,30 @@ func searchFileForStableMetrics(filename string, src interface{}) ([]metric, []e
if err != nil {
return []metric{}, []error{err}
}
metricsImportName, err := getMetricsFrameworkImportName(tree)
metricsImportName, err := getLocalNameOfImportedPackage(tree, kubeMetricImportPath, kubeMetricsDefaultImportName)
if err != nil {
return []metric{}, addFileInformationToErrors([]error{err}, fileset)
}
if metricsImportName == "" {
return []metric{}, []error{}
}
prometheusImportName, err := getLocalNameOfImportedPackage(tree, prometheusImportPath, prometheusDefaultImportName)
if err != nil {
return []metric{}, addFileInformationToErrors([]error{err}, fileset)
}
stableMetricsFunctionCalls, errors := findStableMetricDeclaration(tree, metricsImportName)
metrics, es := decodeMetricCalls(stableMetricsFunctionCalls, metricsImportName)
metrics, es := decodeMetricCalls(stableMetricsFunctionCalls, metricsImportName, prometheusImportName)
errors = append(errors, es...)
return metrics, addFileInformationToErrors(errors, fileset)
}
func getMetricsFrameworkImportName(tree *ast.File) (string, error) {
func getLocalNameOfImportedPackage(tree *ast.File, importPath, defaultImportName string) (string, error) {
var importName string
for _, im := range tree.Imports {
if im.Path.Value == metricFrameworkPath {
if im.Path.Value == importPath {
if im.Name == nil {
importName = defaultFrameworkImportName
importName = defaultImportName
} else {
if im.Name.Name == "." {
return "", newDecodeErrorf(im, errImport)

View File

@ -20,6 +20,8 @@ import (
"fmt"
"reflect"
"testing"
"github.com/prometheus/client_golang/prometheus"
)
const fakeFilename = "testdata/metric.go"
@ -33,7 +35,7 @@ func TestSkipMetrics(t *testing.T) {
testName: "Skip alpha metric with local variable",
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var name = "metric"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
@ -46,7 +48,7 @@ var _ = metrics.NewCounter(
testName: "Skip alpha metric created via function call",
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
func getName() string {
return "metric"
}
@ -61,7 +63,7 @@ var _ = metrics.NewCounter(
testName: "Skip metric without stability set",
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
Name: "metric",
@ -123,22 +125,24 @@ func TestStableMetric(t *testing.T) {
{
testName: "Counter",
metric: metric{
Name: "metric",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
Help: "help",
Type: counterMetricType,
Name: "metric",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
DeprecatedVersion: "1.16",
Help: "help",
Type: counterMetricType,
},
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
Name: "metric",
Subsystem: "subsystem",
Namespace: "namespace",
Help: "help",
DeprecatedVersion: "1.16",
StabilityLevel: metrics.STABLE,
},
)
@ -146,23 +150,25 @@ var _ = metrics.NewCounter(
{
testName: "CounterVec",
metric: metric{
Name: "metric",
Namespace: "namespace",
Subsystem: "subsystem",
Labels: []string{"label-1"},
StabilityLevel: "STABLE",
Help: "help",
Type: counterMetricType,
Name: "metric",
Namespace: "namespace",
Subsystem: "subsystem",
Labels: []string{"label-1"},
StabilityLevel: "STABLE",
DeprecatedVersion: "1.16",
Help: "help",
Type: counterMetricType,
},
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewCounterVec(
&metrics.CounterOpts{
Name: "metric",
Namespace: "namespace",
Subsystem: "subsystem",
Help: "help",
DeprecatedVersion: "1.16",
StabilityLevel: metrics.STABLE,
},
[]string{"label-1"},
@ -171,22 +177,24 @@ var _ = metrics.NewCounterVec(
{
testName: "Gauge",
metric: metric{
Name: "gauge",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
Help: "help",
Type: gaugeMetricType,
Name: "gauge",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
DeprecatedVersion: "1.16",
Help: "help",
Type: gaugeMetricType,
},
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewGauge(
&metrics.GaugeOpts{
Name: "gauge",
Namespace: "namespace",
Subsystem: "subsystem",
Help: "help",
DeprecatedVersion: "1.16",
StabilityLevel: metrics.STABLE,
},
)
@ -194,23 +202,25 @@ var _ = metrics.NewGauge(
{
testName: "GaugeVec",
metric: metric{
Name: "gauge",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
Help: "help",
Type: gaugeMetricType,
Labels: []string{"label-1", "label-2"},
Name: "gauge",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
DeprecatedVersion: "1.16",
Help: "help",
Type: gaugeMetricType,
Labels: []string{"label-1", "label-2"},
},
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewGaugeVec(
&metrics.GaugeOpts{
Name: "gauge",
Namespace: "namespace",
Subsystem: "subsystem",
Help: "help",
DeprecatedVersion: "1.16",
StabilityLevel: metrics.STABLE,
},
[]string{"label-2", "label-1"},
@ -219,17 +229,18 @@ var _ = metrics.NewGaugeVec(
{
testName: "Histogram",
metric: metric{
Name: "histogram",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
Buckets: []float64{0.001, 0.01, 0.1, 1, 10, 100},
Help: "help",
Type: histogramMetricType,
Name: "histogram",
Namespace: "namespace",
Subsystem: "subsystem",
DeprecatedVersion: "1.16",
StabilityLevel: "STABLE",
Buckets: []float64{0.001, 0.01, 0.1, 1, 10, 100},
Help: "help",
Type: histogramMetricType,
},
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewHistogram(
&metrics.HistogramOpts{
Name: "histogram",
@ -237,6 +248,7 @@ var _ = metrics.NewHistogram(
Subsystem: "subsystem",
StabilityLevel: metrics.STABLE,
Help: "help",
DeprecatedVersion: "1.16",
Buckets: []float64{0.001, 0.01, 0.1, 1, 10, 100},
},
)
@ -244,18 +256,19 @@ var _ = metrics.NewHistogram(
{
testName: "HistogramVec",
metric: metric{
Name: "histogram",
Namespace: "namespace",
Subsystem: "subsystem",
StabilityLevel: "STABLE",
Buckets: []float64{0.001, 0.01, 0.1, 1, 10, 100},
Help: "help",
Type: histogramMetricType,
Labels: []string{"label-1", "label-2"},
Name: "histogram",
Namespace: "namespace",
Subsystem: "subsystem",
DeprecatedVersion: "1.16",
StabilityLevel: "STABLE",
Buckets: []float64{0.001, 0.01, 0.1, 1, 10, 100},
Help: "help",
Type: histogramMetricType,
Labels: []string{"label-1", "label-2"},
},
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewHistogramVec(
&metrics.HistogramOpts{
Name: "histogram",
@ -263,6 +276,7 @@ var _ = metrics.NewHistogramVec(
Subsystem: "subsystem",
StabilityLevel: metrics.STABLE,
Help: "help",
DeprecatedVersion: "1.16",
Buckets: []float64{0.001, 0.01, 0.1, 1, 10, 100},
},
[]string{"label-2", "label-1"},
@ -277,13 +291,73 @@ var _ = metrics.NewHistogramVec(
},
src: `
package test
import custom "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import custom "k8s.io/component-base/metrics"
var _ = custom.NewCounter(
&custom.CounterOpts{
Name: "metric",
StabilityLevel: custom.STABLE,
},
)
`},
{
testName: "Histogram with linear buckets",
metric: metric{
Name: "histogram",
StabilityLevel: "STABLE",
Buckets: prometheus.LinearBuckets(1, 1, 3),
Type: histogramMetricType,
},
src: `
package test
import "k8s.io/component-base/metrics"
import "github.com/prometheus/client_golang/prometheus"
var _ = metrics.NewHistogram(
&metrics.HistogramOpts{
Name: "histogram",
StabilityLevel: metrics.STABLE,
Buckets: prometheus.LinearBuckets(1, 1, 3),
},
)
`},
{
testName: "Histogram with exponential buckets",
metric: metric{
Name: "histogram",
StabilityLevel: "STABLE",
Buckets: prometheus.ExponentialBuckets(1, 2, 3),
Type: histogramMetricType,
},
src: `
package test
import "k8s.io/component-base/metrics"
import "github.com/prometheus/client_golang/prometheus"
var _ = metrics.NewHistogram(
&metrics.HistogramOpts{
Name: "histogram",
StabilityLevel: metrics.STABLE,
Buckets: prometheus.ExponentialBuckets(1, 2, 3),
},
)
`},
{
testName: "Histogram with default buckets",
metric: metric{
Name: "histogram",
StabilityLevel: "STABLE",
Buckets: prometheus.DefBuckets,
Type: histogramMetricType,
},
src: `
package test
import "k8s.io/component-base/metrics"
import "github.com/prometheus/client_golang/prometheus"
var _ = metrics.NewHistogram(
&metrics.HistogramOpts{
Name: "histogram",
StabilityLevel: metrics.STABLE,
Buckets: prometheus.DefBuckets,
},
)
`},
} {
t.Run(test.testName, func(t *testing.T) {
@ -315,7 +389,7 @@ func TestIncorrectStableMetricDeclarations(t *testing.T) {
err: fmt.Errorf("testdata/metric.go:4:9: Stable summary metric is not supported"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewSummary(
&metrics.SummaryOpts{
StabilityLevel: metrics.STABLE,
@ -327,7 +401,7 @@ var _ = metrics.NewSummary(
err: fmt.Errorf("testdata/metric.go:7:4: Non string attribute it not supported"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
const name = "metric"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
@ -341,7 +415,7 @@ var _ = metrics.NewCounter(
err: fmt.Errorf("testdata/metric.go:9:4: Non string attribute it not supported"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
func getName() string {
return "metric"
}
@ -357,7 +431,7 @@ var _ = metrics.NewCounter(
err: fmt.Errorf("testdata/metric.go:7:4: Non string attribute it not supported"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
import "k8s.io/kubernetes/utils"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
@ -371,7 +445,7 @@ var _ = metrics.NewCounter(
err: fmt.Errorf("testdata/metric.go:9:20: StabilityLevel should be passed STABLE, ALPHA or removed"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
func getMetricStability() metrics.StabilityLevel {
return metrics.STABLE
}
@ -386,7 +460,7 @@ var _ = metrics.NewCounter(
err: fmt.Errorf("testdata/metric.go:6:20: StabilityLevel should be passed STABLE, ALPHA or removed"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
StabilityLevel: "stable",
@ -398,7 +472,7 @@ var _ = metrics.NewCounter(
err: fmt.Errorf("testdata/metric.go:6:20: StabilityLevel should be passed STABLE, ALPHA or removed"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
StabilityLevel: metrics.UNKNOWN,
@ -410,7 +484,7 @@ var _ = metrics.NewCounter(
err: fmt.Errorf("testdata/metric.go:7:20: StabilityLevel should be passed STABLE, ALPHA or removed"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var stable = metrics.STABLE
var _ = metrics.NewCounter(
&metrics.CounterOpts{
@ -423,7 +497,7 @@ var _ = metrics.NewCounter(
err: fmt.Errorf("testdata/metric.go:6:10: Opts for STABLE metric was not directly passed to new metric function"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewCounter(getStableCounterOpts())
func getStableCounterOpts() *metrics.CounterOpts {
return &metrics.CounterOpts{
@ -433,10 +507,10 @@ func getStableCounterOpts() *metrics.CounterOpts {
`},
{
testName: "error . package import of metric framework",
err: fmt.Errorf(`testdata/metric.go:3:8: Importing through "." metrics framework is not supported`),
err: fmt.Errorf(`testdata/metric.go:3:8: Importing using "." is not supported`),
src: `
package test
import . "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import . "k8s.io/component-base/metrics"
var _ = NewCounter(
&CounterOpts{
StabilityLevel: STABLE,
@ -448,7 +522,7 @@ var _ = NewCounter(
err: fmt.Errorf("testdata/metric.go:4:9: Opts for STABLE metric was not directly passed to new metric function"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = RegisterMetric(
&metrics.CounterOpts{
StabilityLevel: metrics.STABLE,
@ -460,7 +534,7 @@ var _ = RegisterMetric(
err: fmt.Errorf("testdata/metric.go:4:9: Opts for STABLE metric was not directly passed to new metric function"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = test.RegisterMetric(
&metrics.CounterOpts{
StabilityLevel: metrics.STABLE,
@ -472,12 +546,57 @@ var _ = test.RegisterMetric(
err: fmt.Errorf("testdata/metric.go:6:4: Positional arguments are not supported"),
src: `
package test
import "k8s.io/kubernetes/staging/src/k8s.io/component-base/metrics"
import "k8s.io/component-base/metrics"
var _ = metrics.NewCounter(
&metrics.CounterOpts{
"counter",
},
)
`},
{
testName: "error stable historgram with unknown prometheus bucket variable",
err: fmt.Errorf("testdata/metric.go:9:13: Buckets should be set to list of floats, result from function call of prometheus.LinearBuckets or prometheus.ExponentialBuckets"),
src: `
package test
import "k8s.io/component-base/metrics"
import "github.com/prometheus/client_golang/prometheus"
var _ = metrics.NewHistogram(
&metrics.HistogramOpts{
Name: "histogram",
StabilityLevel: metrics.STABLE,
Buckets: prometheus.FakeBuckets,
},
)
`},
{
testName: "error stable historgram with unknown bucket variable",
err: fmt.Errorf("testdata/metric.go:9:13: Buckets should be set to list of floats, result from function call of prometheus.LinearBuckets or prometheus.ExponentialBuckets"),
src: `
package test
import "k8s.io/component-base/metrics"
var buckets = []float64{1, 2, 3}
var _ = metrics.NewHistogram(
&metrics.HistogramOpts{
Name: "histogram",
StabilityLevel: metrics.STABLE,
Buckets: buckets,
},
)
`},
{
testName: "error stable historgram with unknown bucket variable from unknown library",
err: fmt.Errorf("testdata/metric.go:9:13: Buckets should be set to list of floats, result from function call of prometheus.LinearBuckets or prometheus.ExponentialBuckets"),
src: `
package test
import "k8s.io/component-base/metrics"
import "github.com/fake_prometheus/prometheus"
var _ = metrics.NewHistogram(
&metrics.HistogramOpts{
Name: "histogram",
StabilityLevel: metrics.STABLE,
Buckets: prometheus.DefBuckets,
},
)
`},
} {
t.Run(test.testName, func(t *testing.T) {