Add request body size metric
Change-Id: Ica5d9b5457d4f844c4500b2c05b2f0631c27454c Kubernetes-commit: 43c95cbf0682895cf5bb79452b1f011123ac4513
This commit is contained in:
parent
270d177e30
commit
ce7b4d6e8c
|
@ -37,6 +37,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/audit"
|
"k8s.io/apiserver/pkg/audit"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
|
"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/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
@ -86,7 +87,7 @@ func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Int
|
||||||
return
|
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})
|
trace.Step("limitedReadBody done", utiltrace.Field{"len", len(body)}, utiltrace.Field{"err", err})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/audit"
|
"k8s.io/apiserver/pkg/audit"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
|
"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/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
@ -70,7 +71,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestSc
|
||||||
|
|
||||||
options := &metav1.DeleteOptions{}
|
options := &metav1.DeleteOptions{}
|
||||||
if allowsOptions {
|
if allowsOptions {
|
||||||
body, err := limitedReadBody(req, scope.MaxRequestBodyBytes)
|
body, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.Patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
return
|
return
|
||||||
|
|
|
@ -17,9 +17,19 @@ limitations under the License.
|
||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"k8s.io/component-base/metrics"
|
"k8s.io/component-base/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type RequestBodyVerb string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Patch RequestBodyVerb = "patch"
|
||||||
|
Delete RequestBodyVerb = "delete"
|
||||||
|
Update RequestBodyVerb = "update"
|
||||||
|
Create RequestBodyVerb = "create"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
RequestBodySizes = metrics.NewHistogramVec(
|
RequestBodySizes = metrics.NewHistogramVec(
|
||||||
&metrics.HistogramOpts{
|
&metrics.HistogramOpts{
|
||||||
|
@ -34,3 +44,7 @@ var (
|
||||||
[]string{"resource", "verb"},
|
[]string{"resource", "verb"},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func RecordRequestBodySize(ctx context.Context, resource string, verb RequestBodyVerb, size int) {
|
||||||
|
RequestBodySizes.WithContext(ctx).WithLabelValues(resource, string(verb)).Observe(float64(size))
|
||||||
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
jsonpatch "github.com/evanphx/json-patch"
|
||||||
kjson "sigs.k8s.io/json"
|
kjson "sigs.k8s.io/json"
|
||||||
|
|
||||||
jsonpatch "github.com/evanphx/json-patch"
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme"
|
metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme"
|
||||||
|
@ -45,6 +45,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
|
"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/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
@ -98,7 +99,7 @@ func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interfac
|
||||||
return
|
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})
|
trace.Step("limitedReadBody done", utiltrace.Field{"len", len(patchBytes)}, utiltrace.Field{"err", err})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
|
|
|
@ -41,6 +41,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
"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/handlers/responsewriters"
|
||||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
@ -390,6 +391,15 @@ func limitedReadBody(req *http.Request, limit int64) ([]byte, error) {
|
||||||
return data, nil
|
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 {
|
func isDryRun(url *url.URL) bool {
|
||||||
return len(url.Query()["dryRun"]) != 0
|
return len(url.Query()["dryRun"]) != 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -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="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="3.05e+06"} 1
|
||||||
apiserver_request_body_sizes_bucket{resource="resource.group",verb="create",le="+Inf"} 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
|
apiserver_request_body_sizes_count{resource="resource.group",verb="create"} 1
|
||||||
`,
|
`,
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
|
@ -185,7 +185,7 @@ func TestLimitedReadBody(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("err not expected: got %v", err)
|
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 tc.expectedErr {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("err expected: got nil")
|
t.Errorf("err expected: got nil")
|
||||||
|
|
|
@ -35,6 +35,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/finisher"
|
"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/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
@ -69,7 +70,7 @@ func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interfa
|
||||||
return
|
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})
|
trace.Step("limitedReadBody done", utiltrace.Field{"len", len(body)}, utiltrace.Field{"err", err})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
|
|
Loading…
Reference in New Issue