Skip to content

Commit e4bb1da

Browse files
committed
apiserver: increment metric for deprecated API use
1 parent e06b063 commit e4bb1da

File tree

5 files changed

+42
-19
lines changed

5 files changed

+42
-19
lines changed

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
360360
}
361361

362362
if handlerFunc != nil {
363-
handlerFunc = metrics.InstrumentHandlerFunc(verb, requestInfo.APIGroup, requestInfo.APIVersion, resource, subresource, scope, metrics.APIServerComponent, handlerFunc)
363+
handlerFunc = metrics.InstrumentHandlerFunc(verb, requestInfo.APIGroup, requestInfo.APIVersion, resource, subresource, scope, metrics.APIServerComponent, false, "", handlerFunc)
364364
handler := genericfilters.WithWaitGroup(handlerFunc, longRunningFilter, crdInfo.waitGroup)
365365
handler.ServeHTTP(w, req)
366366
return

staging/src/k8s.io/apiserver/pkg/endpoints/installer.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,9 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
629629
var (
630630
enableWarningHeaders = utilfeature.DefaultFeatureGate.Enabled(features.WarningHeaders)
631631

632-
warnings []string
633-
deprecated bool
632+
warnings []string
633+
deprecated bool
634+
removedRelease string
634635
)
635636

636637
{
@@ -639,6 +640,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
639640
currentMajor, currentMinor, _ := deprecation.MajorMinor(versioninfo.Get())
640641
deprecated = deprecation.IsDeprecated(versionedPtrWithGVK, currentMajor, currentMinor)
641642
if deprecated {
643+
removedRelease = deprecation.RemovedRelease(versionedPtrWithGVK)
642644
warnings = append(warnings, deprecation.WarningMessage(versionedPtrWithGVK))
643645
}
644646
}
@@ -654,9 +656,9 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
654656

655657
if needOverride {
656658
// need change the reported verb
657-
handler = metrics.InstrumentRouteFunc(verbOverrider.OverrideMetricsVerb(action.Verb), group, version, resource, subresource, requestScope, metrics.APIServerComponent, handler)
659+
handler = metrics.InstrumentRouteFunc(verbOverrider.OverrideMetricsVerb(action.Verb), group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, handler)
658660
} else {
659-
handler = metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, handler)
661+
handler = metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, handler)
660662
}
661663
if enableWarningHeaders {
662664
handler = utilwarning.AddWarningsHandler(handler, warnings)
@@ -690,7 +692,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
690692
if isSubresource {
691693
doc = "list " + subresource + " of objects of kind " + kind
692694
}
693-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulListResource(lister, watcher, reqScope, false, a.minRequestTimeout))
695+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulListResource(lister, watcher, reqScope, false, a.minRequestTimeout))
694696
if enableWarningHeaders {
695697
handler = utilwarning.AddWarningsHandler(handler, warnings)
696698
}
@@ -725,7 +727,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
725727
if isSubresource {
726728
doc = "replace " + subresource + " of the specified " + kind
727729
}
728-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulUpdateResource(updater, reqScope, admit))
730+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulUpdateResource(updater, reqScope, admit))
729731
if enableWarningHeaders {
730732
handler = utilwarning.AddWarningsHandler(handler, warnings)
731733
}
@@ -758,7 +760,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
758760
if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
759761
supportedTypes = append(supportedTypes, string(types.ApplyPatchType))
760762
}
761-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulPatchResource(patcher, reqScope, admit, supportedTypes))
763+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulPatchResource(patcher, reqScope, admit, supportedTypes))
762764
if enableWarningHeaders {
763765
handler = utilwarning.AddWarningsHandler(handler, warnings)
764766
}
@@ -783,7 +785,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
783785
} else {
784786
handler = restfulCreateResource(creater, reqScope, admit)
785787
}
786-
handler = metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, handler)
788+
handler = metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, handler)
787789
if enableWarningHeaders {
788790
handler = utilwarning.AddWarningsHandler(handler, warnings)
789791
}
@@ -819,7 +821,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
819821
if deleteReturnsDeletedObject {
820822
deleteReturnType = producedObject
821823
}
822-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulDeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit))
824+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulDeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit))
823825
if enableWarningHeaders {
824826
handler = utilwarning.AddWarningsHandler(handler, warnings)
825827
}
@@ -845,7 +847,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
845847
if isSubresource {
846848
doc = "delete collection of " + subresource + " of a " + kind
847849
}
848-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulDeleteCollection(collectionDeleter, isCollectionDeleter, reqScope, admit))
850+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulDeleteCollection(collectionDeleter, isCollectionDeleter, reqScope, admit))
849851
if enableWarningHeaders {
850852
handler = utilwarning.AddWarningsHandler(handler, warnings)
851853
}
@@ -875,7 +877,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
875877
doc = "watch changes to " + subresource + " of an object of kind " + kind
876878
}
877879
doc += ". deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter."
878-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
880+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
879881
if enableWarningHeaders {
880882
handler = utilwarning.AddWarningsHandler(handler, warnings)
881883
}
@@ -898,7 +900,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
898900
doc = "watch individual changes to a list of " + subresource + " of " + kind
899901
}
900902
doc += ". deprecated: use the 'watch' parameter with a list operation instead."
901-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
903+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
902904
if enableWarningHeaders {
903905
handler = utilwarning.AddWarningsHandler(handler, warnings)
904906
}
@@ -924,7 +926,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
924926
if isSubresource {
925927
doc = "connect " + method + " requests to " + subresource + " of " + kind
926928
}
927-
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulConnectResource(connecter, reqScope, admit, path, isSubresource))
929+
handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, restfulConnectResource(connecter, reqScope, admit, path, isSubresource))
928930
if enableWarningHeaders {
929931
handler = utilwarning.AddWarningsHandler(handler, warnings)
930932
}

staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ const (
6060
* the metric stability policy.
6161
*/
6262
var (
63+
deprecatedRequestGauge = compbasemetrics.NewGaugeVec(
64+
&compbasemetrics.GaugeOpts{
65+
Name: "apiserver_requested_deprecated_apis",
66+
Help: "Gauge of deprecated APIs that have been requested, broken out by API group, version, resource, subresource, and removed_release.",
67+
StabilityLevel: compbasemetrics.ALPHA,
68+
},
69+
[]string{"group", "version", "resource", "subresource", "removed_release"},
70+
)
71+
6372
// TODO(a-robinson): Add unit tests for the handling of these metrics once
6473
// the upstream library supports it.
6574
requestCounter = compbasemetrics.NewCounterVec(
@@ -162,6 +171,7 @@ var (
162171
kubectlExeRegexp = regexp.MustCompile(`^.*((?i:kubectl\.exe))`)
163172

164173
metrics = []resettableCollector{
174+
deprecatedRequestGauge,
165175
requestCounter,
166176
longRunningRequestGauge,
167177
requestLatencies,
@@ -288,12 +298,15 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, comp
288298

289299
// MonitorRequest handles standard transformations for client and the reported verb and then invokes Monitor to record
290300
// a request. verb must be uppercase to be backwards compatible with existing monitoring tooling.
291-
func MonitorRequest(req *http.Request, verb, group, version, resource, subresource, scope, component, contentType string, httpCode, respSize int, elapsed time.Duration) {
301+
func MonitorRequest(req *http.Request, verb, group, version, resource, subresource, scope, component string, deprecated bool, removedRelease string, contentType string, httpCode, respSize int, elapsed time.Duration) {
292302
reportedVerb := cleanVerb(verb, req)
293303
dryRun := cleanDryRun(req.URL)
294304
elapsedSeconds := elapsed.Seconds()
295305
cleanContentType := cleanContentType(contentType)
296306
requestCounter.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component, cleanContentType, codeToString(httpCode)).Inc()
307+
if deprecated {
308+
deprecatedRequestGauge.WithLabelValues(group, version, resource, subresource, removedRelease).Set(1)
309+
}
297310
requestLatencies.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component).Observe(elapsedSeconds)
298311
// We are only interested in response sizes of read requests.
299312
if verb == "GET" || verb == "LIST" {
@@ -303,7 +316,7 @@ func MonitorRequest(req *http.Request, verb, group, version, resource, subresour
303316

304317
// InstrumentRouteFunc works like Prometheus' InstrumentHandlerFunc but wraps
305318
// the go-restful RouteFunction instead of a HandlerFunc plus some Kubernetes endpoint specific information.
306-
func InstrumentRouteFunc(verb, group, version, resource, subresource, scope, component string, routeFunc restful.RouteFunction) restful.RouteFunction {
319+
func InstrumentRouteFunc(verb, group, version, resource, subresource, scope, component string, deprecated bool, removedRelease string, routeFunc restful.RouteFunction) restful.RouteFunction {
307320
return restful.RouteFunction(func(request *restful.Request, response *restful.Response) {
308321
now := time.Now()
309322

@@ -322,12 +335,12 @@ func InstrumentRouteFunc(verb, group, version, resource, subresource, scope, com
322335

323336
routeFunc(request, response)
324337

325-
MonitorRequest(request.Request, verb, group, version, resource, subresource, scope, component, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now))
338+
MonitorRequest(request.Request, verb, group, version, resource, subresource, scope, component, deprecated, removedRelease, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now))
326339
})
327340
}
328341

329342
// InstrumentHandlerFunc works like Prometheus' InstrumentHandlerFunc but adds some Kubernetes endpoint specific information.
330-
func InstrumentHandlerFunc(verb, group, version, resource, subresource, scope, component string, handler http.HandlerFunc) http.HandlerFunc {
343+
func InstrumentHandlerFunc(verb, group, version, resource, subresource, scope, component string, deprecated bool, removedRelease string, handler http.HandlerFunc) http.HandlerFunc {
331344
return func(w http.ResponseWriter, req *http.Request) {
332345
now := time.Now()
333346

@@ -344,7 +357,7 @@ func InstrumentHandlerFunc(verb, group, version, resource, subresource, scope, c
344357

345358
handler(w, req)
346359

347-
MonitorRequest(req, verb, group, version, resource, subresource, scope, component, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now))
360+
MonitorRequest(req, verb, group, version, resource, subresource, scope, component, deprecated, removedRelease, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now))
348361
}
349362
}
350363

staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ func InstallPathHandler(mux mux, path string, checks ...HealthChecker) {
131131
/* subresource = */ path,
132132
/* scope = */ "",
133133
/* component = */ "",
134+
/* deprecated */ false,
135+
/* removedRelease */ "",
134136
handleRootHealthz(checks...)))
135137
for _, check := range checks {
136138
mux.Handle(fmt.Sprintf("%s/%v", path, check.Name()), adaptCheckToHandler(check.Check))

test/integration/metrics/metrics_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,17 @@ func TestApiserverMetrics(t *testing.T) {
9595
t.Fatalf("unexpected error getting pods: %v", err)
9696
}
9797

98+
// Make a request to a deprecated API to ensure there's at least one data point
99+
if _, err := client.RbacV1beta1().Roles(metav1.NamespaceDefault).List(context.TODO(), metav1.ListOptions{}); err != nil {
100+
t.Fatalf("unexpected error getting rbac roles: %v", err)
101+
}
102+
98103
metrics, err := scrapeMetrics(s)
99104
if err != nil {
100105
t.Fatal(err)
101106
}
102107
checkForExpectedMetrics(t, metrics, []string{
108+
"apiserver_requested_deprecated_apis",
103109
"apiserver_request_total",
104110
"apiserver_request_duration_seconds_sum",
105111
"etcd_request_duration_seconds_sum",

0 commit comments

Comments
 (0)