Skip to content

Commit b28ea95

Browse files
committed
Reintroduce AddMetricsExtraHandler on manager
Signed-off-by: Vince Prignano <[email protected]>
1 parent 9bc967a commit b28ea95

File tree

4 files changed

+57
-5
lines changed

4 files changed

+57
-5
lines changed

pkg/manager/internal.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,26 @@ func (cm *controllerManager) add(r Runnable) error {
179179
return cm.runnables.Add(r)
180180
}
181181

182+
// AddMetricsExtraHandler adds extra handler served on path to the http server that serves metrics.
183+
func (cm *controllerManager) AddMetricsExtraHandler(path string, handler http.Handler) error {
184+
cm.Lock()
185+
defer cm.Unlock()
186+
187+
if cm.started {
188+
return fmt.Errorf("unable to add new metrics handler because metrics endpoint has already been created")
189+
}
190+
191+
if path == metricsserver.DefaultMetricsEndpoint {
192+
return fmt.Errorf("overriding builtin %s endpoint is not allowed", metricsserver.DefaultMetricsEndpoint)
193+
}
194+
195+
if err := cm.metricsServer.AddExtraHandler(path, handler); err != nil {
196+
return err
197+
}
198+
cm.logger.V(2).Info("Registering metrics http server extra handler", "path", path)
199+
return nil
200+
}
201+
182202
// AddHealthzCheck allows you to add Healthz checker.
183203
func (cm *controllerManager) AddHealthzCheck(name string, check healthz.Checker) error {
184204
cm.Lock()

pkg/manager/manager.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ type Manager interface {
6464
// election was configured.
6565
Elected() <-chan struct{}
6666

67+
// AddMetricsExtraHandler adds an extra handler served on path to the http server that serves metrics.
68+
// Might be useful to register some diagnostic endpoints e.g. pprof.
69+
//
70+
// Note that these endpoints meant to be sensitive and shouldn't be exposed publicly.
71+
//
72+
// If the simple path -> handler mapping offered here is not enough,
73+
// a new http server/listener should be added as Runnable to the manager via Add method.
74+
AddMetricsExtraHandler(path string, handler http.Handler) error
75+
6776
// AddHealthzCheck allows you to add Healthz checker
6877
AddHealthzCheck(name string, check healthz.Checker) error
6978

pkg/manager/manager_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,12 @@ var _ = Describe("manger.Manager", func() {
13121312
m, err := New(cfg, opts)
13131313
Expect(err).NotTo(HaveOccurred())
13141314

1315+
// Should error when we add another extra endpoint on the already registered path.
1316+
err = m.AddMetricsExtraHandler("/debug", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
1317+
_, _ = w.Write([]byte("Another debug info"))
1318+
}))
1319+
Expect(err).To(HaveOccurred())
1320+
13151321
ctx, cancel := context.WithCancel(context.Background())
13161322
defer cancel()
13171323
go func() {

pkg/metrics/server/server.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,17 @@ import (
3838
)
3939

4040
const (
41-
defaultMetricsEndpoint = "/metrics"
41+
DefaultMetricsEndpoint = "/metrics"
4242
)
4343

4444
// DefaultBindAddress is the default bind address for the metrics server.
4545
var DefaultBindAddress = ":8080"
4646

4747
// Server is a server that serves metrics.
4848
type Server interface {
49+
// AddExtraHandler adds extra handler served on path to the http server that serves metrics.
50+
AddExtraHandler(path string, handler http.Handler) error
51+
4952
// NeedLeaderElection implements the LeaderElectionRunnable interface, which indicates
5053
// the metrics server doesn't need leader election.
5154
NeedLeaderElection() bool
@@ -120,8 +123,8 @@ func NewServer(o Options, config *rest.Config, httpClient *http.Client) (Server,
120123

121124
// Validate that ExtraHandlers is not overwriting the default /metrics endpoint.
122125
if o.ExtraHandlers != nil {
123-
if _, ok := o.ExtraHandlers[defaultMetricsEndpoint]; ok {
124-
return nil, fmt.Errorf("overriding builtin %s endpoint is not allowed", defaultMetricsEndpoint)
126+
if _, ok := o.ExtraHandlers[DefaultMetricsEndpoint]; ok {
127+
return nil, fmt.Errorf("overriding builtin %s endpoint is not allowed", DefaultMetricsEndpoint)
125128
}
126129
}
127130

@@ -182,6 +185,20 @@ func (*defaultServer) NeedLeaderElection() bool {
182185
return false
183186
}
184187

188+
// AddMetricsExtraHandler adds extra handler served on path to the http server that serves metrics.
189+
func (s *defaultServer) AddExtraHandler(path string, handler http.Handler) error {
190+
s.mu.Lock()
191+
defer s.mu.Unlock()
192+
if s.options.ExtraHandlers == nil {
193+
s.options.ExtraHandlers = make(map[string]http.Handler)
194+
}
195+
if _, found := s.options.ExtraHandlers[path]; found {
196+
return fmt.Errorf("can't register extra handler by duplicate path %q on metrics http server", path)
197+
}
198+
s.options.ExtraHandlers[path] = handler
199+
return nil
200+
}
201+
185202
// Start runs the server.
186203
// It will install the metrics related resources depend on the server configuration.
187204
func (s *defaultServer) Start(ctx context.Context) error {
@@ -202,15 +219,15 @@ func (s *defaultServer) Start(ctx context.Context) error {
202219
ErrorHandling: promhttp.HTTPErrorOnError,
203220
})
204221
if s.metricsFilter != nil {
205-
log := log.WithValues("path", defaultMetricsEndpoint)
222+
log := log.WithValues("path", DefaultMetricsEndpoint)
206223
var err error
207224
handler, err = s.metricsFilter(log, handler)
208225
if err != nil {
209226
return fmt.Errorf("failed to start metrics server: failed to add metrics filter: %w", err)
210227
}
211228
}
212229
// TODO(JoelSpeed): Use existing Kubernetes machinery for serving metrics
213-
mux.Handle(defaultMetricsEndpoint, handler)
230+
mux.Handle(DefaultMetricsEndpoint, handler)
214231

215232
for path, extraHandler := range s.options.ExtraHandlers {
216233
if s.metricsFilter != nil {

0 commit comments

Comments
 (0)