Skip to content

Commit

Permalink
Add metrics for OpenAPI V3
Browse files Browse the repository at this point in the history
Kubernetes-commit: 9ad7d96451bfde5f121e83ae72d8bba84cbaeb6d
  • Loading branch information
Jefftree authored and k8s-publishing-bot committed Mar 14, 2023
1 parent a6998cf commit 336c431
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
23 changes: 21 additions & 2 deletions pkg/controllers/openapiv3/aggregator/aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"sync"
"time"

"k8s.io/apiserver/pkg/endpoints/metrics"
"k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/mux"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -268,6 +269,24 @@ func (s *specProxier) handleGroupVersion(w http.ResponseWriter, r *http.Request)

// Register registers the OpenAPI V3 Discovery and GroupVersion handlers
func (s *specProxier) register(handler common.PathHandlerByGroupVersion) {
handler.Handle("/openapi/v3", http.HandlerFunc(s.handleDiscovery))
handler.HandlePrefix("/openapi/v3/", http.HandlerFunc(s.handleGroupVersion))
handler.Handle("/openapi/v3", metrics.InstrumentHandlerFunc("GET",
/* group = */ "",
/* version = */ "",
/* resource = */ "",
/* subresource = */ "openapi/v3",
/* scope = */ "",
/* component = */ "",
/* deprecated */ false,
/* removedRelease */ "",
http.HandlerFunc(s.handleDiscovery)))
handler.HandlePrefix("/openapi/v3/", metrics.InstrumentHandlerFunc("GET",
/* group = */ "",
/* version = */ "",
/* resource = */ "",
/* subresource = */ "openapi/v3/",
/* scope = */ "",
/* component = */ "",
/* deprecated */ false,
/* removedRelease */ "",
http.HandlerFunc(s.handleGroupVersion)))
}
64 changes: 64 additions & 0 deletions pkg/controllers/openapiv3/aggregator/aggregator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ import (
"bytes"
"encoding/json"
"net/http"
"strings"
"testing"

"github.com/stretchr/testify/assert"

"k8s.io/apiserver/pkg/endpoints/metrics"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/mux"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/component-base/metrics/testutil"
v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
"k8s.io/kube-openapi/pkg/handler3"
)
Expand Down Expand Up @@ -166,6 +170,66 @@ func TestV3APIService(t *testing.T) {
assert.ElementsMatch(t, []string{openAPIV2Converter, apiService.Name}, apiServiceNames)
}

func TestOpenAPIRequestMetrics(t *testing.T) {
metrics.Register()
metrics.Reset()

downloader := Downloader{}

pathHandler := mux.NewPathRecorderMux("aggregator_metrics_test")
var serveHandler http.Handler = pathHandler
specProxier, err := BuildAndRegisterAggregator(downloader, genericapiserver.NewEmptyDelegate(), pathHandler)
if err != nil {
t.Error(err)
}
specJSON := []byte(`{"openapi":"3.0.0","info":{"title":"Kubernetes","version":"unversioned"}}`)
handler := testV3APIService{
etag: "6E8F849B434D4B98A569B9D7718876E9-356ECAB19D7FBE1336BABB1E70F8F3025050DE218BE78256BE81620681CFC9A268508E542B8B55974E17B2184BBFC8FFFAA577E51BE195D32B3CA2547818ABE4",
data: specJSON,
}
apiService := &v1.APIService{
Spec: v1.APIServiceSpec{
Group: "group.example.com",
Version: "v1",
},
}
apiService.Name = "v1.group.example.com"
specProxier.AddUpdateAPIService(handler, apiService)
specProxier.UpdateAPIServiceSpec("v1.group.example.com")

data := sendReq(t, serveHandler, "/openapi/v3")
groupVersionList := handler3.OpenAPIV3Discovery{}
if err := json.Unmarshal(data, &groupVersionList); err != nil {
t.Fatal(err)
}
_, ok := groupVersionList.Paths["apis/group.example.com/v1"]
if !ok {
t.Error("Expected group.example.com/v1 to be in group version list")
}

// Metrics should be updated after requesting the root document.
if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(`
# HELP apiserver_request_total [STABLE] Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, and HTTP response code.
# TYPE apiserver_request_total counter
apiserver_request_total{code="200",component="",dry_run="",group="",resource="",scope="",subresource="openapi/v3",verb="GET",version=""} 1
`), "apiserver_request_total"); err != nil {
t.Fatal(err)
}

_ = sendReq(t, serveHandler, "/openapi/v3/apis/group.example.com/v1")

// Metrics should be updated after requesting OpenAPI for a group version.
if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(`
# HELP apiserver_request_total [STABLE] Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, and HTTP response code.
# TYPE apiserver_request_total counter
apiserver_request_total{code="200",component="",dry_run="",group="",resource="",scope="",subresource="openapi/v3",verb="GET",version=""} 1
apiserver_request_total{code="200",component="",dry_run="",group="",resource="",scope="",subresource="openapi/v3/",verb="GET",version=""} 1
`), "apiserver_request_total"); err != nil {
t.Fatal(err)
}

}

func sendReq(t *testing.T, handler http.Handler, path string) []byte {
req, err := http.NewRequest("GET", path, nil)
if err != nil {
Expand Down

0 comments on commit 336c431

Please sign in to comment.