add metrics for backend_retries_total

This commit is contained in:
Marco Jantke 2017-04-18 08:22:06 +02:00 committed by Timo Reimann
parent 7874ffd506
commit e007bb7546
8 changed files with 530 additions and 125 deletions

View file

@ -192,11 +192,9 @@ func (server *Server) startHTTPServers() {
if server.accessLoggerMiddleware != nil {
serverMiddlewares = append(serverMiddlewares, server.accessLoggerMiddleware)
}
if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Metrics != nil {
if server.globalConfiguration.Web.Metrics.Prometheus != nil {
metricsMiddleware := middlewares.NewMetricsWrapper(middlewares.NewPrometheus(newServerEntryPointName, server.globalConfiguration.Web.Metrics.Prometheus))
serverMiddlewares = append(serverMiddlewares, metricsMiddleware)
}
metrics := newMetrics(server.globalConfiguration, newServerEntryPointName)
if metrics != nil {
serverMiddlewares = append(serverMiddlewares, middlewares.NewMetricsWrapper(metrics))
}
if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Statistics != nil {
statsRecorder = middlewares.NewStatsRecorder(server.globalConfiguration.Web.Statistics.RecentErrors)
@ -726,21 +724,15 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
continue frontend
}
}
// retry ?
if globalConfiguration.Retry != nil {
retries := len(configuration.Backends[frontend.Backend].Servers)
if globalConfiguration.Retry.Attempts > 0 {
retries = globalConfiguration.Retry.Attempts
}
lb = middlewares.NewRetry(retries, lb)
log.Debugf("Creating retries max attempts %d", retries)
}
if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Metrics != nil {
if server.globalConfiguration.Web.Metrics.Prometheus != nil {
metricsMiddlewareBackend := middlewares.NewMetricsWrapper(middlewares.NewPrometheus(frontend.Backend, server.globalConfiguration.Web.Metrics.Prometheus))
negroni.Use(metricsMiddlewareBackend)
}
metrics := newMetrics(server.globalConfiguration, frontend.Backend)
if globalConfiguration.Retry != nil {
retryListener := middlewares.NewMetricsRetryListener(metrics)
lb = registerRetryMiddleware(lb, globalConfiguration, configuration, frontend.Backend, retryListener)
}
if metrics != nil {
negroni.Use(middlewares.NewMetricsWrapper(metrics))
}
ipWhitelistMiddleware, err := configureIPWhitelistMiddleware(frontend.WhitelistSourceRange)
@ -961,3 +953,37 @@ func (*Server) configureBackends(backends map[string]*types.Backend) {
}
}
}
// newMetrics instantiates the proper Metrics implementation, depending on the global configuration.
// Note that given there is no metrics instrumentation configured, it will return nil.
func newMetrics(globalConfig GlobalConfiguration, name string) middlewares.Metrics {
metricsEnabled := globalConfig.Web != nil && globalConfig.Web.Metrics != nil
if metricsEnabled && globalConfig.Web.Metrics.Prometheus != nil {
metrics, _, err := middlewares.NewPrometheus(name, globalConfig.Web.Metrics.Prometheus)
if err != nil {
log.Errorf("Error creating Prometheus Metrics implementation: %s", err)
return nil
}
return metrics
}
return nil
}
func registerRetryMiddleware(
httpHandler http.Handler,
globalConfig GlobalConfiguration,
config *types.Configuration,
backend string,
listener middlewares.RetryListener,
) http.Handler {
retries := len(config.Backends[backend].Servers)
if globalConfig.Retry.Attempts > 0 {
retries = globalConfig.Retry.Attempts
}
httpHandler = middlewares.NewRetry(retries, httpHandler, listener)
log.Debugf("Creating retries max attempts %d", retries)
return httpHandler
}

View file

@ -11,6 +11,7 @@ import (
"github.com/containous/flaeg"
"github.com/containous/mux"
"github.com/containous/traefik/healthcheck"
"github.com/containous/traefik/middlewares"
"github.com/containous/traefik/testhelpers"
"github.com/containous/traefik/types"
"github.com/davecgh/go-spew/spew"
@ -409,3 +410,109 @@ func TestConfigureBackends(t *testing.T) {
})
}
}
func TestNewMetrics(t *testing.T) {
testCases := []struct {
desc string
globalConfig GlobalConfiguration
}{
{
desc: "metrics disabled",
globalConfig: GlobalConfiguration{},
},
{
desc: "prometheus metrics",
globalConfig: GlobalConfiguration{
Web: &WebProvider{
Metrics: &types.Metrics{
Prometheus: &types.Prometheus{
Buckets: types.Buckets{0.1, 0.3, 1.2, 5.0},
},
},
},
},
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.desc, func(t *testing.T) {
t.Parallel()
metricsImpl := newMetrics(tc.globalConfig, "test1")
if metricsImpl != nil {
if _, ok := metricsImpl.(*middlewares.Prometheus); !ok {
t.Errorf("invalid metricsImpl type, got %T want %T", metricsImpl, &middlewares.Prometheus{})
}
}
})
}
}
func TestRegisterRetryMiddleware(t *testing.T) {
testCases := []struct {
name string
globalConfig GlobalConfiguration
countServers int
expectedRetries int
}{
{
name: "configured retry attempts",
globalConfig: GlobalConfiguration{
Retry: &Retry{
Attempts: 3,
},
},
expectedRetries: 3,
},
{
name: "retry attempts defaults to server amount",
globalConfig: GlobalConfiguration{
Retry: &Retry{},
},
expectedRetries: 2,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
var retryListener middlewares.RetryListener
httpHandler := okHTTPHandler{}
dynamicConfig := &types.Configuration{
Backends: map[string]*types.Backend{
"backend": {
Servers: map[string]types.Server{
"server": {
URL: "http://localhost",
},
"server2": {
URL: "http://localhost",
},
},
},
},
}
httpHandlerWithRetry := registerRetryMiddleware(httpHandler, tc.globalConfig, dynamicConfig, "backend", retryListener)
retry, ok := httpHandlerWithRetry.(*middlewares.Retry)
if !ok {
t.Fatalf("httpHandler was not decorated with retry httpHandler, got %#v", httpHandlerWithRetry)
}
expectedRetry := middlewares.NewRetry(tc.expectedRetries, httpHandler, retryListener)
if !reflect.DeepEqual(retry, expectedRetry) {
t.Errorf("retry httpHandler was not instantiated correctly, got %#v want %#v", retry, expectedRetry)
}
})
}
}
type okHTTPHandler struct{}
func (okHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}