Skip to content

Commit

Permalink
Merge pull request #84777 from RainbowMango/manually-cherry-pick-of-#…
Browse files Browse the repository at this point in the history
…83427-upstream-release-1.16

Manually cherry pick of #83427: Fix double counting issue for request metrics on timeout
  • Loading branch information
k8s-ci-robot authored Nov 7, 2019
2 parents a1260f0 + 412cbe0 commit 0869af6
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 10 deletions.
38 changes: 31 additions & 7 deletions staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ var (
},
[]string{"group", "version", "kind"},
)
// Because of volatality of the base metric this is pre-aggregated one. Instead of reporing current usage all the time
// Because of volatility of the base metric this is pre-aggregated one. Instead of reporting current usage all the time
// it reports maximal usage during the last second.
currentInflightRequests = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Expand All @@ -150,6 +150,15 @@ var (
},
[]string{"requestKind"},
)

requestTerminationsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "apiserver_request_terminations_total",
Help: "Number of requests which apiserver terminated in self-defense.",
},
[]string{"verb", "group", "version", "resource", "subresource", "scope", "component", "code"},
)

kubectlExeRegexp = regexp.MustCompile(`^.*((?i:kubectl\.exe))`)

metrics = []resettableCollector{
Expand All @@ -164,6 +173,7 @@ var (
DeprecatedDroppedRequests,
RegisteredWatchers,
currentInflightRequests,
requestTerminationsTotal,
}
)

Expand Down Expand Up @@ -197,18 +207,20 @@ func UpdateInflightRequestMetrics(nonmutating, mutating int) {
currentInflightRequests.WithLabelValues(MutatingKind).Set(float64(mutating))
}

// Record records a single request to the standard metrics endpoints. For use by handlers that perform their own
// processing. All API paths should use InstrumentRouteFunc implicitly. Use this instead of MonitorRequest if
// you already have a RequestInfo object.
func Record(req *http.Request, requestInfo *request.RequestInfo, component, contentType string, code int, responseSizeInBytes int, elapsed time.Duration) {
// RecordRequestTermination records that the request was terminated early as part of a resource
// preservation or apiserver self-defense mechanism (e.g. timeouts, maxinflight throttling,
// proxyHandler errors). RecordRequestTermination should only be called zero or one times
// per request.
func RecordRequestTermination(req *http.Request, requestInfo *request.RequestInfo, component string, code int) {
if requestInfo == nil {
requestInfo = &request.RequestInfo{Verb: req.Method, Path: req.URL.Path}
}
scope := CleanScope(requestInfo)
verb := canonicalVerb(strings.ToUpper(req.Method), scope)
if requestInfo.IsResourceRequest {
MonitorRequest(req, strings.ToUpper(requestInfo.Verb), requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component, contentType, code, responseSizeInBytes, elapsed)
requestTerminationsTotal.WithLabelValues(cleanVerb(verb, req), requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component, codeToString(code)).Inc()
} else {
MonitorRequest(req, strings.ToUpper(requestInfo.Verb), "", "", "", requestInfo.Path, scope, component, contentType, code, responseSizeInBytes, elapsed)
requestTerminationsTotal.WithLabelValues(cleanVerb(verb, req), "", "", "", requestInfo.Path, scope, component, codeToString(code)).Inc()
}
}

Expand Down Expand Up @@ -312,6 +324,18 @@ func CleanScope(requestInfo *request.RequestInfo) string {
return ""
}

func canonicalVerb(verb string, scope string) string {
switch verb {
case "GET", "HEAD":
if scope != "resource" {
return "LIST"
}
return "GET"
default:
return verb
}
}

func cleanVerb(verb string, request *http.Request) string {
reportedVerb := verb
if verb == "LIST" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func WithMaxInFlightLimit(
}
}
}
metrics.Record(r, requestInfo, metrics.APIServerComponent, "", http.StatusTooManyRequests, 0, 0)
metrics.RecordRequestTermination(r, requestInfo, metrics.APIServerComponent, http.StatusTooManyRequests)
tooManyRequests(r, w)
}
}
Expand Down
2 changes: 1 addition & 1 deletion staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func WithTimeoutForNonLongRunningRequests(handler http.Handler, longRunning apir

postTimeoutFn := func() {
cancel()
metrics.Record(req, requestInfo, metrics.APIServerComponent, "", http.StatusGatewayTimeout, 0, 0)
metrics.RecordRequestTermination(req, requestInfo, metrics.APIServerComponent, http.StatusGatewayTimeout)
}
return req, time.After(timeout), postTimeoutFn, apierrors.NewTimeoutError(fmt.Sprintf("request did not complete within %s", timeout), 0)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func proxyError(w http.ResponseWriter, req *http.Request, error string, code int
return
}
// TODO: record long-running request differently? The long-running check func does not necessarily match the one of the aggregated apiserver
endpointmetrics.Record(req, info, aggregatorComponent, "", code, 0, 0)
endpointmetrics.RecordRequestTermination(req, info, aggregatorComponent, code)
}

func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
Expand Down

0 comments on commit 0869af6

Please sign in to comment.