Add request body size metric

Change-Id: Ica5d9b5457d4f844c4500b2c05b2f0631c27454c

Kubernetes-commit: 43c95cbf0682895cf5bb79452b1f011123ac4513
This commit is contained in:
Han Kang 2022-08-24 09:15:23 -07:00 committed by Kubernetes Publisher
parent 270d177e30
commit ce7b4d6e8c
7 changed files with 35 additions and 7 deletions

View File

@ -37,6 +37,7 @@ import (
"k8s.io/apiserver/pkg/audit"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
requestmetrics "k8s.io/apiserver/pkg/endpoints/handlers/metrics"
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
@ -86,7 +87,7 @@ func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Int
return
}
body, err := limitedReadBody(req, scope.MaxRequestBodyBytes)
body, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.Create)
trace.Step("limitedReadBody done", utiltrace.Field{"len", len(body)}, utiltrace.Field{"err", err})
if err != nil {
scope.err(err, w, req)

View File

@ -33,6 +33,7 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/audit"
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
requestmetrics "k8s.io/apiserver/pkg/endpoints/handlers/metrics"
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
@ -70,7 +71,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestSc
options := &metav1.DeleteOptions{}
if allowsOptions {
body, err := limitedReadBody(req, scope.MaxRequestBodyBytes)
body, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.Patch)
if err != nil {
scope.err(err, w, req)
return

View File

@ -17,9 +17,19 @@ limitations under the License.
package metrics
import (
"context"
"k8s.io/component-base/metrics"
)
type RequestBodyVerb string
const (
Patch RequestBodyVerb = "patch"
Delete RequestBodyVerb = "delete"
Update RequestBodyVerb = "update"
Create RequestBodyVerb = "create"
)
var (
RequestBodySizes = metrics.NewHistogramVec(
&metrics.HistogramOpts{
@ -34,3 +44,7 @@ var (
[]string{"resource", "verb"},
)
)
func RecordRequestBodySize(ctx context.Context, resource string, verb RequestBodyVerb, size int) {
RequestBodySizes.WithContext(ctx).WithLabelValues(resource, string(verb)).Observe(float64(size))
}

View File

@ -23,9 +23,9 @@ import (
"strings"
"time"
jsonpatch "github.com/evanphx/json-patch"
kjson "sigs.k8s.io/json"
jsonpatch "github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme"
@ -45,6 +45,7 @@ import (
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
requestmetrics "k8s.io/apiserver/pkg/endpoints/handlers/metrics"
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
@ -98,7 +99,7 @@ func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interfac
return
}
patchBytes, err := limitedReadBody(req, scope.MaxRequestBodyBytes)
patchBytes, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.Patch)
trace.Step("limitedReadBody done", utiltrace.Field{"len", len(patchBytes)}, utiltrace.Field{"err", err})
if err != nil {
scope.err(err, w, req)

View File

@ -41,6 +41,7 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
requestmetrics "k8s.io/apiserver/pkg/endpoints/handlers/metrics"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
"k8s.io/apiserver/pkg/endpoints/metrics"
"k8s.io/apiserver/pkg/endpoints/request"
@ -390,6 +391,15 @@ func limitedReadBody(req *http.Request, limit int64) ([]byte, error) {
return data, nil
}
func limitedReadBodyWithRecordMetric(ctx context.Context, req *http.Request, limit int64, resourceGroup string, verb requestmetrics.RequestBodyVerb) ([]byte, error) {
readBody, err := limitedReadBody(req, limit)
if err == nil {
// only record if we've read successfully
requestmetrics.RecordRequestBodySize(ctx, resourceGroup, verb, len(readBody))
}
return readBody, err
}
func isDryRun(url *url.URL) bool {
return len(url.Query()["dryRun"]) != 0
}

View File

@ -168,7 +168,7 @@ func TestLimitedReadBody(t *testing.T) {
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_sum{resource="resource.group",verb="create"} 4
apiserver_request_body_sizes_count{resource="resource.group",verb="create"} 1
`,
expectedErr: false,
@ -185,7 +185,7 @@ func TestLimitedReadBody(t *testing.T) {
if err != nil {
t.Errorf("err not expected: got %v", err)
}
_, err = limitedReadBody(context.Background(), req, tc.limit, "resource.group", "create")
_, err = limitedReadBodyWithRecordMetric(context.Background(), req, tc.limit, "resource.group", metrics.Create)
if tc.expectedErr {
if err == nil {
t.Errorf("err expected: got nil")

View File

@ -35,6 +35,7 @@ import (
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
requestmetrics "k8s.io/apiserver/pkg/endpoints/handlers/metrics"
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
@ -69,7 +70,7 @@ func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interfa
return
}
body, err := limitedReadBody(req, scope.MaxRequestBodyBytes)
body, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.Update)
trace.Step("limitedReadBody done", utiltrace.Field{"len", len(body)}, utiltrace.Field{"err", err})
if err != nil {
scope.err(err, w, req)