Skip to content

Commit 54e57af

Browse files
Jay Boydpmorie
Jay Boyd
authored andcommitted
Provide OSB Client proxy to instrument with metrics (openshift#1615)
* proxy for OSB Client to instrument with metrics * break OSB Client metrics out by OSB Method name (GetCatalog, Bind, etc)
1 parent 026b86f commit 54e57af

File tree

3 files changed

+186
-2
lines changed

3 files changed

+186
-2
lines changed

Diff for: cmd/controller-manager/app/controller_manager.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939

4040
"github.com/kubernetes-incubator/service-catalog/pkg/kubernetes/pkg/util/configz"
4141
"github.com/kubernetes-incubator/service-catalog/pkg/metrics"
42+
"github.com/kubernetes-incubator/service-catalog/pkg/metrics/osbclientproxy"
4243

4344
"k8s.io/apimachinery/pkg/runtime/schema"
4445
"k8s.io/apimachinery/pkg/util/wait"
@@ -57,7 +58,6 @@ import (
5758
"github.com/kubernetes-incubator/service-catalog/pkg/controller"
5859

5960
"github.com/golang/glog"
60-
osb "github.com/pmorie/go-open-service-broker-client/v2"
6161
"github.com/spf13/cobra"
6262
"github.com/spf13/pflag"
6363
)
@@ -330,7 +330,7 @@ func StartControllers(s *options.ControllerManagerServer,
330330
serviceCatalogSharedInformers.ServiceInstances(),
331331
serviceCatalogSharedInformers.ServiceBindings(),
332332
serviceCatalogSharedInformers.ClusterServicePlans(),
333-
osb.NewClient,
333+
osbclientproxy.NewClient,
334334
s.ServiceBrokerRelistInterval,
335335
s.OSBAPIPreferredVersion,
336336
recorder,

Diff for: pkg/metrics/metrics.go

+13
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,25 @@ var (
6060
},
6161
[]string{"broker"},
6262
)
63+
64+
// OSBRequestCount exposes the number of HTTP requests made to Open Service
65+
// Brokers. The metric is broken out by broker name and response status
66+
// group (1xx/2xx/3xx/4xx/5xx or 'client-error')
67+
OSBRequestCount = prometheus.NewCounterVec(
68+
prometheus.CounterOpts{
69+
Namespace: catalogNamespace,
70+
Name: "osb_request_count",
71+
Help: "Cumulative number of HTTP requests from the OSB Client to the specified Service Broker grouped by broker name, broker method, and response status.",
72+
},
73+
[]string{"broker", "method", "status"},
74+
)
6375
)
6476

6577
func register() {
6678
registerMetrics.Do(func() {
6779
prometheus.MustRegister(BrokerServiceClassCount)
6880
prometheus.MustRegister(BrokerServicePlanCount)
81+
prometheus.MustRegister(OSBRequestCount)
6982
})
7083
}
7184

Diff for: pkg/metrics/osbclientproxy/osbproxy.go

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package osbclientproxy proxies the OSB Client Library enabling
18+
// metrics instrumentation
19+
package osbclientproxy
20+
21+
import (
22+
"fmt"
23+
24+
"github.com/golang/glog"
25+
"github.com/kubernetes-incubator/service-catalog/pkg/metrics"
26+
osb "github.com/pmorie/go-open-service-broker-client/v2"
27+
)
28+
29+
// proxyclient provides a functional implementation of the OSB V2 Client
30+
// interface
31+
type proxyclient struct {
32+
brokerName string
33+
realOSBClient osb.Client
34+
}
35+
36+
// NewClient is a CreateFunc for creating a new functional Client and
37+
// implements the CreateFunc interface.
38+
func NewClient(config *osb.ClientConfiguration) (osb.Client, error) {
39+
osbClient, err := osb.NewClient(config)
40+
if err != nil {
41+
return nil, err
42+
}
43+
proxy := proxyclient{realOSBClient: osbClient}
44+
proxy.brokerName = config.Name
45+
return proxy, nil
46+
}
47+
48+
var _ osb.CreateFunc = NewClient
49+
50+
const (
51+
getCatalog = "GetCatalog"
52+
provisionInstance = "ProvisionInstance"
53+
deprovisionInstance = "DeprovisionInstance"
54+
updateInstance = "UpdateInstance"
55+
pollLastOperation = "PollLastOperation"
56+
pollBindingLastOperation = "PollBindingLastOperation"
57+
bind = "Bind"
58+
unbind = "Unbind"
59+
getBinding = "GetBinding"
60+
)
61+
62+
// GetCatalog implements go-open-service-broker-client/v2/Client.GetCatalog by
63+
// proxying the method to the underlying implementation and capturing request
64+
// metrics.
65+
func (pc proxyclient) GetCatalog() (*osb.CatalogResponse, error) {
66+
glog.V(9).Info("OSBClientProxy getCatalog()")
67+
response, err := pc.realOSBClient.GetCatalog()
68+
pc.updateMetrics(getCatalog, err)
69+
return response, err
70+
}
71+
72+
// ProvisionInstance implements
73+
// go-open-service-broker-client/v2/Client.ProvisionInstance by proxying the
74+
// method to the underlying implementation and capturing request metrics.
75+
func (pc proxyclient) ProvisionInstance(r *osb.ProvisionRequest) (*osb.ProvisionResponse, error) {
76+
glog.V(9).Info("OSBClientProxy ProvisionInstance()")
77+
response, err := pc.realOSBClient.ProvisionInstance(r)
78+
pc.updateMetrics(provisionInstance, err)
79+
return response, err
80+
81+
}
82+
83+
// UpdateInstance implements
84+
// go-open-service-broker-client/v2/Client.UpdateInstance by proxying the method
85+
// to the underlying implementation and capturing request metrics.
86+
func (pc proxyclient) UpdateInstance(r *osb.UpdateInstanceRequest) (*osb.UpdateInstanceResponse, error) {
87+
glog.V(9).Info("OSBClientProxy UpdateInstance()")
88+
response, err := pc.realOSBClient.UpdateInstance(r)
89+
pc.updateMetrics(updateInstance, err)
90+
return response, err
91+
}
92+
93+
// DeprovisionInstance implements
94+
// go-open-service-broker-client/v2/Client.DeprovisionInstance by proxying the
95+
// method to the underlying implementation and capturing request metrics.
96+
func (pc proxyclient) DeprovisionInstance(r *osb.DeprovisionRequest) (*osb.DeprovisionResponse, error) {
97+
glog.V(9).Info("OSBClientProxy DeprovisionInstance()")
98+
response, err := pc.realOSBClient.DeprovisionInstance(r)
99+
pc.updateMetrics(deprovisionInstance, err)
100+
return response, err
101+
}
102+
103+
// PollLastOperation implements
104+
// go-open-service-broker-client/v2/Client.PollLastOperation by proxying the
105+
// method to the underlying implementation and capturing request metrics.
106+
func (pc proxyclient) PollLastOperation(r *osb.LastOperationRequest) (*osb.LastOperationResponse, error) {
107+
glog.V(9).Info("OSBClientProxy PollLastOperation()")
108+
response, err := pc.realOSBClient.PollLastOperation(r)
109+
pc.updateMetrics(pollLastOperation, err)
110+
return response, err
111+
}
112+
113+
// PollBindingLastOperation implements
114+
// go-open-service-broker-client/v2/Client.PollBindingLastOperation by proxying
115+
// the method to the underlying implementation and capturing request metrics.
116+
func (pc proxyclient) PollBindingLastOperation(r *osb.BindingLastOperationRequest) (*osb.LastOperationResponse, error) {
117+
glog.V(9).Info("OSBClientProxy PollBindingLastOperation()")
118+
response, err := pc.realOSBClient.PollBindingLastOperation(r)
119+
pc.updateMetrics(pollBindingLastOperation, err)
120+
return response, err
121+
}
122+
123+
// Bind implements go-open-service-broker-client/v2/Client.Bind by proxying the
124+
// method to the underlying implementation and capturing request metrics.
125+
func (pc proxyclient) Bind(r *osb.BindRequest) (*osb.BindResponse, error) {
126+
glog.V(9).Info("OSBClientProxy Bind().")
127+
response, err := pc.realOSBClient.Bind(r)
128+
pc.updateMetrics(bind, err)
129+
return response, err
130+
}
131+
132+
// Unbind implements go-open-service-broker-client/v2/Client.Unbind by proxying
133+
// the method to the underlying implementation and capturing request metrics.
134+
func (pc proxyclient) Unbind(r *osb.UnbindRequest) (*osb.UnbindResponse, error) {
135+
glog.V(9).Info("OSBClientProxy Unbind()")
136+
response, err := pc.realOSBClient.Unbind(r)
137+
pc.updateMetrics(unbind, err)
138+
return response, err
139+
}
140+
141+
// GetBinding implements go-open-service-broker-client/v2/Client.GetBinding by
142+
// proxying the method to the underlying implementation and capturing request
143+
// metrics.
144+
func (pc proxyclient) GetBinding(r *osb.GetBindingRequest) (*osb.GetBindingResponse, error) {
145+
glog.V(9).Info("OSBClientProxy GetBinding()")
146+
response, err := pc.realOSBClient.GetBinding(r)
147+
pc.updateMetrics(getBinding, err)
148+
return response, err
149+
}
150+
151+
const clientErr = "client-error"
152+
153+
// updateMetrics bumps the request count metric for the specific broker, method
154+
// and status
155+
func (pc proxyclient) updateMetrics(method string, err error) {
156+
var statusGroup string
157+
158+
// for this metric, lack of an error translates into a 2xx status
159+
if err == nil {
160+
metrics.OSBRequestCount.WithLabelValues(pc.brokerName, method, "2xx").Inc()
161+
return
162+
}
163+
164+
status, httpError := osb.IsHTTPError(err)
165+
if httpError {
166+
statusGroup = fmt.Sprintf("%dxx", status.StatusCode/100)
167+
} else {
168+
statusGroup = clientErr
169+
}
170+
metrics.OSBRequestCount.WithLabelValues(pc.brokerName, method, statusGroup).Inc()
171+
}

0 commit comments

Comments
 (0)