Review comments, added metric namespace, moved utility functions, and etc

This commit is contained in:
Chinmay Chapla 2023-05-31 01:04:57 +00:00
parent 8df1a5e6dc
commit 705c6ff315
3 changed files with 77 additions and 81 deletions

View File

@ -99,7 +99,8 @@ const (
) )
var ( var (
Metrics = newWebhookConversionMetrics() Metrics = newWebhookConversionMetrics()
namespace = "apiserver"
) )
// WebhookConversionMetrics instruments webhook conversion with prometheus metrics. // WebhookConversionMetrics instruments webhook conversion with prometheus metrics.
@ -111,7 +112,8 @@ type WebhookConversionMetrics struct {
func newWebhookConversionMetrics() *WebhookConversionMetrics { func newWebhookConversionMetrics() *WebhookConversionMetrics {
webhookConversionRequest := metrics.NewCounterVec( webhookConversionRequest := metrics.NewCounterVec(
&metrics.CounterOpts{ &metrics.CounterOpts{
Name: "webhook_conversion_requests", Name: "webhook_conversion_request_total",
Namespace: namespace,
Help: "Counter for webhook conversion requests with success/failure and failure error type", Help: "Counter for webhook conversion requests with success/failure and failure error type",
StabilityLevel: metrics.ALPHA, StabilityLevel: metrics.ALPHA,
}, },
@ -119,8 +121,10 @@ func newWebhookConversionMetrics() *WebhookConversionMetrics {
webhookConversionLatency := metrics.NewHistogramVec( webhookConversionLatency := metrics.NewHistogramVec(
&metrics.HistogramOpts{ &metrics.HistogramOpts{
Name: "webhook_conversion_duration_seconds", Name: "webhook_conversion_duration_seconds",
Help: "Webhook conversion request latency", Namespace: namespace,
Help: "Webhook conversion request latency",
// 0.001, 0.002, 0.004, .... 16.384 [1ms, 2ms, 4ms, ...., 16,384 ms]
Buckets: metrics.ExponentialBuckets(0.001, 2, 15), Buckets: metrics.ExponentialBuckets(0.001, 2, 15),
StabilityLevel: metrics.ALPHA, StabilityLevel: metrics.ALPHA,
}, },

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2019 The Kubernetes Authors. Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -18,11 +18,11 @@ package conversion
import ( import (
"context" "context"
"fmt"
"testing" "testing"
"time" "time"
"k8s.io/component-base/metrics" "k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/component-base/metrics/testutil" "k8s.io/component-base/metrics/testutil"
) )
@ -32,7 +32,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T)
webhookConversionLatency *metrics.HistogramVec webhookConversionLatency *metrics.HistogramVec
} }
type args struct { type args struct {
ctx context.Context
elapsed time.Duration elapsed time.Duration
} }
tests := []struct { tests := []struct {
@ -50,7 +49,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T)
webhookConversionLatency: Metrics.webhookConversionLatency, webhookConversionLatency: Metrics.webhookConversionLatency,
}, },
args: args{ args: args{
ctx: context.TODO(),
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
}, },
wantLabels: map[string]string{ wantLabels: map[string]string{
@ -65,7 +63,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T)
webhookConversionLatency: Metrics.webhookConversionLatency, webhookConversionLatency: Metrics.webhookConversionLatency,
}, },
args: args{ args: args{
ctx: context.TODO(),
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
}, },
wantLabels: map[string]string{ wantLabels: map[string]string{
@ -81,9 +78,9 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T)
webhookConversionRequest: tt.fields.webhookConversionRequest, webhookConversionRequest: tt.fields.webhookConversionRequest,
webhookConversionLatency: tt.fields.webhookConversionLatency, webhookConversionLatency: tt.fields.webhookConversionLatency,
} }
m.ObserveWebhookConversionSuccess(tt.args.ctx, tt.args.elapsed) m.ObserveWebhookConversionSuccess(context.TODO(), tt.args.elapsed)
expectCounterValue(t, "webhook_conversion_requests", tt.wantLabels, tt.expectedRequestValue) testutil.AssertVectorCount(t, fmt.Sprintf("%s_webhook_conversion_request_total", namespace), tt.wantLabels, tt.expectedRequestValue)
expectHistogramCountTotal(t, "webhook_conversion_duration_seconds", tt.wantLabels, tt.expectedRequestValue) testutil.AssertHistogramTotalCount(t, fmt.Sprintf("%s_webhook_conversion_duration_seconds", namespace), tt.wantLabels, tt.expectedRequestValue)
}) })
} }
} }
@ -94,7 +91,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
webhookConversionLatency *metrics.HistogramVec webhookConversionLatency *metrics.HistogramVec
} }
type args struct { type args struct {
ctx context.Context
elapsed time.Duration elapsed time.Duration
errorType WebhookConversionErrorType errorType WebhookConversionErrorType
} }
@ -114,7 +110,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
webhookConversionLatency: Metrics.webhookConversionLatency, webhookConversionLatency: Metrics.webhookConversionLatency,
}, },
args: args{ args: args{
ctx: context.TODO(),
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionCallFailure, errorType: WebhookConversionCallFailure,
}, },
@ -131,7 +126,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
webhookConversionLatency: Metrics.webhookConversionLatency, webhookConversionLatency: Metrics.webhookConversionLatency,
}, },
args: args{ args: args{
ctx: context.TODO(),
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionMalformedResponseFailure, errorType: WebhookConversionMalformedResponseFailure,
}, },
@ -148,7 +142,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
webhookConversionLatency: Metrics.webhookConversionLatency, webhookConversionLatency: Metrics.webhookConversionLatency,
}, },
args: args{ args: args{
ctx: context.TODO(),
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionPartialResponseFailure, errorType: WebhookConversionPartialResponseFailure,
}, },
@ -165,7 +158,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
webhookConversionLatency: Metrics.webhookConversionLatency, webhookConversionLatency: Metrics.webhookConversionLatency,
}, },
args: args{ args: args{
ctx: context.TODO(),
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionInvalidConvertedObjectFailure, errorType: WebhookConversionInvalidConvertedObjectFailure,
}, },
@ -182,7 +174,6 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
webhookConversionLatency: Metrics.webhookConversionLatency, webhookConversionLatency: Metrics.webhookConversionLatency,
}, },
args: args{ args: args{
ctx: context.TODO(),
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionNoObjectsReturnedFailure, errorType: WebhookConversionNoObjectsReturnedFailure,
}, },
@ -200,69 +191,9 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
webhookConversionRequest: tt.fields.webhookConversionRequest, webhookConversionRequest: tt.fields.webhookConversionRequest,
webhookConversionLatency: tt.fields.webhookConversionLatency, webhookConversionLatency: tt.fields.webhookConversionLatency,
} }
m.ObserveWebhookConversionFailure(tt.args.ctx, tt.args.elapsed, tt.args.errorType) m.ObserveWebhookConversionFailure(context.TODO(), tt.args.elapsed, tt.args.errorType)
expectCounterValue(t, "webhook_conversion_requests", tt.wantLabels, tt.expectedRequestValue) testutil.AssertVectorCount(t, fmt.Sprintf("%s_webhook_conversion_request_total", namespace), tt.wantLabels, tt.expectedRequestValue)
expectHistogramCountTotal(t, "webhook_conversion_duration_seconds", tt.wantLabels, tt.expectedRequestValue) testutil.AssertHistogramTotalCount(t, fmt.Sprintf("%s_webhook_conversion_duration_seconds", namespace), tt.wantLabels, tt.expectedRequestValue)
}) })
} }
} }
func expectCounterValue(t *testing.T, name string, labelFilter map[string]string, wantCount int) {
metrics, err := legacyregistry.DefaultGatherer.Gather()
if err != nil {
t.Fatalf("Failed to gather metrics: %s", err)
}
counterSum := 0
for _, mf := range metrics {
if mf.GetName() != name {
continue // Ignore other metrics.
}
for _, metric := range mf.GetMetric() {
if !testutil.LabelsMatch(metric, labelFilter) {
continue
}
counterSum += int(metric.GetCounter().GetValue())
}
}
if wantCount != counterSum {
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
for _, mf := range metrics {
if mf.GetName() == name {
for _, metric := range mf.GetMetric() {
t.Logf("\tnear match: %s", metric.String())
}
}
}
}
}
func expectHistogramCountTotal(t *testing.T, name string, labelFilter map[string]string, wantCount int) {
metrics, err := legacyregistry.DefaultGatherer.Gather()
if err != nil {
t.Fatalf("Failed to gather metrics: %s", err)
}
counterSum := 0
for _, mf := range metrics {
if mf.GetName() != name {
continue // Ignore other metrics.
}
for _, metric := range mf.GetMetric() {
if !testutil.LabelsMatch(metric, labelFilter) {
continue
}
counterSum += int(metric.GetHistogram().GetSampleCount())
}
}
if wantCount != counterSum {
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
for _, mf := range metrics {
if mf.GetName() == name {
for _, metric := range mf.GetMetric() {
t.Logf("\tnear match: %s\n", metric.String())
}
}
}
}
}

View File

@ -19,11 +19,13 @@ package testutil
import ( import (
"fmt" "fmt"
"io" "io"
"testing"
"github.com/prometheus/client_golang/prometheus/testutil" "github.com/prometheus/client_golang/prometheus/testutil"
apimachineryversion "k8s.io/apimachinery/pkg/version" apimachineryversion "k8s.io/apimachinery/pkg/version"
"k8s.io/component-base/metrics" "k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
) )
// CollectAndCompare registers the provided Collector with a newly created // CollectAndCompare registers the provided Collector with a newly created
@ -91,3 +93,62 @@ func NewFakeKubeRegistry(ver string) metrics.KubeRegistry {
return metrics.NewKubeRegistry() return metrics.NewKubeRegistry()
} }
func AssertVectorCount(t *testing.T, name string, labelFilter map[string]string, wantCount int) {
metrics, err := legacyregistry.DefaultGatherer.Gather()
if err != nil {
t.Fatalf("Failed to gather metrics: %s", err)
}
counterSum := 0
for _, mf := range metrics {
if mf.GetName() != name {
continue // Ignore other metrics.
}
for _, metric := range mf.GetMetric() {
if !LabelsMatch(metric, labelFilter) {
continue
}
counterSum += int(metric.GetCounter().GetValue())
}
}
if wantCount != counterSum {
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
for _, mf := range metrics {
if mf.GetName() == name {
for _, metric := range mf.GetMetric() {
t.Logf("\tnear match: %s", metric.String())
}
}
}
}
}
func AssertHistogramTotalCount(t *testing.T, name string, labelFilter map[string]string, wantCount int) {
metrics, err := legacyregistry.DefaultGatherer.Gather()
if err != nil {
t.Fatalf("Failed to gather metrics: %s", err)
}
counterSum := 0
for _, mf := range metrics {
if mf.GetName() != name {
continue // Ignore other metrics.
}
for _, metric := range mf.GetMetric() {
if !LabelsMatch(metric, labelFilter) {
continue
}
counterSum += int(metric.GetHistogram().GetSampleCount())
}
}
if wantCount != counterSum {
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
for _, mf := range metrics {
if mf.GetName() == name {
for _, metric := range mf.GetMetric() {
t.Logf("\tnear match: %s\n", metric.String())
}
}
}
}
}