add metric and test

Change-Id: Ic2bcf39caef791b2e13448a97d2c3203ed1d94b9
This commit is contained in:
Han Kang 2022-08-24 08:54:51 -07:00
parent 58c10aa6eb
commit 07020ab42e
3 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1,4 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- logicalhan

View File

@ -0,0 +1,36 @@
/*
Copyright 2022 The Kubernetes Authors.
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.
*/
package metrics
import (
"k8s.io/component-base/metrics"
)
var (
RequestBodySizes = metrics.NewHistogramVec(
&metrics.HistogramOpts{
Subsystem: "apiserver",
Name: "request_body_sizes",
Help: "Apiserver request body sizes broken out by size.",
// we use 0.05 KB as the smallest bucket with 0.1 KB increments up to the
// apiserver limit.
Buckets: metrics.LinearBuckets(50000, 100000, 31),
StabilityLevel: metrics.ALPHA,
},
[]string{"resource", "verb"},
)
)

View File

@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"io"
"net/http"
"reflect"
"strings"
@ -45,9 +46,12 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/apis/example"
examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
"k8s.io/apiserver/pkg/endpoints/handlers/metrics"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/component-base/metrics/testutil"
utiltrace "k8s.io/utils/trace"
)
@ -107,6 +111,94 @@ func TestPatchAnonymousField(t *testing.T) {
}
}
func TestLimitedReadBody(t *testing.T) {
defer legacyregistry.Reset()
legacyregistry.Register(metrics.RequestBodySizes)
testcases := []struct {
desc string
requestBody io.Reader
limit int64
expectedMetrics string
expectedErr bool
}{
{
desc: "aaaa with limit 1",
requestBody: strings.NewReader("aaaa"),
limit: 1,
expectedMetrics: "",
expectedErr: true,
},
{
desc: "aaaa with limit 5",
requestBody: strings.NewReader("aaaa"),
limit: 5,
expectedMetrics: `
# HELP apiserver_request_body_sizes [ALPHA] Apiserver request body sizes broken out by size.
# TYPE apiserver_request_body_sizes histogram
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="50000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="150000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="250000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="350000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="450000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="550000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="650000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="750000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="850000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="950000"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.05e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.15e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.25e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.35e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.45e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.55e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.65e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.75e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.85e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="1.95e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.05e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.15e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.25e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.35e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.45e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.55e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.65e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.75e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.85e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="2.95e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="3.05e+06"} 1
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="+Inf"} 1
apiserver_request_body_sizes_sum{resource="resource.group",verb="create"} 3
apiserver_request_body_sizes_count{resource="resource.group",verb="create"} 1
`,
expectedErr: false,
},
}
for _, tc := range testcases {
t.Run(tc.desc, func(t *testing.T) {
// reset metrics
defer metrics.RequestBodySizes.Reset()
defer legacyregistry.Reset()
req, err := http.NewRequest("POST", "/", tc.requestBody)
if err != nil {
t.Errorf("err not expected: got %v", err)
}
_, err = limitedReadBody(context.Background(), req, tc.limit, "resource.group", "create")
if tc.expectedErr {
if err == nil {
t.Errorf("err expected: got nil")
}
return
}
if err = testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tc.expectedMetrics), "apiserver_request_body_sizes"); err != nil {
t.Errorf("unexpected err: %v", err)
}
})
}
}
func TestStrategicMergePatchInvalid(t *testing.T) {
testGV := schema.GroupVersion{Group: "", Version: "v"}
scheme.AddKnownTypes(testGV, &testPatchType{})