diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go index 1f3ce809448..c40ec854add 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go @@ -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/features" @@ -93,7 +94,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) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go index a7712f115fa..b9536d77a72 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go @@ -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/features" @@ -77,7 +78,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 diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/metrics/metrics.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/metrics/metrics.go index 694ff53b25e..a870f3db418 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/metrics/metrics.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/metrics/metrics.go @@ -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)) +} diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go index a0a8fb6ca77..504f41233cf 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go @@ -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/features" @@ -105,7 +106,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) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go index e413661e760..7f005a37167 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -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 } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go index 5a7e39979ba..5518839523b 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go @@ -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") diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go index cb0ba5d7de8..3d77b1c5818 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go @@ -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/features" @@ -76,7 +77,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) diff --git a/vendor/modules.txt b/vendor/modules.txt index 1b99b6847ed..b245ea5c6e7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1600,6 +1600,7 @@ k8s.io/apiserver/pkg/endpoints/handlers k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal k8s.io/apiserver/pkg/endpoints/handlers/finisher +k8s.io/apiserver/pkg/endpoints/handlers/metrics k8s.io/apiserver/pkg/endpoints/handlers/negotiation k8s.io/apiserver/pkg/endpoints/handlers/responsewriters k8s.io/apiserver/pkg/endpoints/metrics