Merge current v1.7 into master
This commit is contained in:
parent
dad0e75121
commit
e92b01c528
8 changed files with 129 additions and 25 deletions
|
@ -108,7 +108,7 @@ The endpoint may be specified to override the environment variable values inside
|
||||||
|
|
||||||
When the environment variables are not found, Traefik will try to connect to the Kubernetes API server with an external-cluster client.
|
When the environment variables are not found, Traefik will try to connect to the Kubernetes API server with an external-cluster client.
|
||||||
In this case, the endpoint is required.
|
In this case, the endpoint is required.
|
||||||
Specifically, it may be set to the URL used by `kubectl proxy` to connect to a Kubernetes cluster using the granted autentication and authorization of the associated kubeconfig.
|
Specifically, it may be set to the URL used by `kubectl proxy` to connect to a Kubernetes cluster using the granted authentication and authorization of the associated kubeconfig.
|
||||||
|
|
||||||
### `labelselector`
|
### `labelselector`
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Tracing
|
# Tracing
|
||||||
|
|
||||||
Tracing system allows developers to visualize call flows in there infrastructures.
|
The tracing system allows developers to visualize call flows in their infrastructure.
|
||||||
|
|
||||||
We use [OpenTracing](http://opentracing.io). It is an open standard designed for distributed tracing.
|
We use [OpenTracing](http://opentracing.io). It is an open standard designed for distributed tracing.
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ IP: 172.27.0.3
|
||||||
Run more instances of your `whoami` service with the following command:
|
Run more instances of your `whoami` service with the following command:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker-compose up -d --scale whoami=2
|
docker-compose scale whoami=2
|
||||||
```
|
```
|
||||||
|
|
||||||
Go back to your browser ([http://localhost:8080](http://localhost:8080)) and see that Træfik has automatically detected the new instance of the container.
|
Go back to your browser ([http://localhost:8080](http://localhost:8080)) and see that Træfik has automatically detected the new instance of the container.
|
||||||
|
|
|
@ -232,7 +232,7 @@ Finally but not unimportantly, we tell Træfik to route **to** port `9000`, sinc
|
||||||
`Service labels` allow managing many routes for the same container.
|
`Service labels` allow managing many routes for the same container.
|
||||||
|
|
||||||
When both `container labels` and `service labels` are defined, `container labels` are just used as default values for missing `service labels` but no frontend/backend are going to be defined only with these labels.
|
When both `container labels` and `service labels` are defined, `container labels` are just used as default values for missing `service labels` but no frontend/backend are going to be defined only with these labels.
|
||||||
Obviously, labels `traefik.frontend.rule` and `traefik.port` described above, will only be used to complete information set in `service labels` during the container frontends/bakends creation.
|
Obviously, labels `traefik.frontend.rule` and `traefik.port` described above, will only be used to complete information set in `service labels` during the container frontends/backends creation.
|
||||||
|
|
||||||
In the example, two service names are defined : `basic` and `admin`.
|
In the example, two service names are defined : `basic` and `admin`.
|
||||||
They allow creating two frontends and two backends.
|
They allow creating two frontends and two backends.
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containous/mux"
|
"github.com/containous/mux"
|
||||||
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/safe"
|
"github.com/containous/traefik/safe"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/go-kit/kit/metrics"
|
"github.com/go-kit/kit/metrics"
|
||||||
|
@ -15,25 +16,31 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
metricNamePrefix = "traefik_"
|
// MetricNamePrefix prefix of all metric names
|
||||||
|
MetricNamePrefix = "traefik_"
|
||||||
|
|
||||||
// server meta information
|
// server meta information
|
||||||
configReloadsTotalName = metricNamePrefix + "config_reloads_total"
|
metricConfigPrefix = MetricNamePrefix + "config_"
|
||||||
configReloadsFailuresTotalName = metricNamePrefix + "config_reloads_failure_total"
|
configReloadsTotalName = metricConfigPrefix + "reloads_total"
|
||||||
configLastReloadSuccessName = metricNamePrefix + "config_last_reload_success"
|
configReloadsFailuresTotalName = metricConfigPrefix + "reloads_failure_total"
|
||||||
configLastReloadFailureName = metricNamePrefix + "config_last_reload_failure"
|
configLastReloadSuccessName = metricConfigPrefix + "last_reload_success"
|
||||||
|
configLastReloadFailureName = metricConfigPrefix + "last_reload_failure"
|
||||||
|
|
||||||
// entrypoint
|
// entrypoint
|
||||||
entrypointReqsTotalName = metricNamePrefix + "entrypoint_requests_total"
|
metricEntryPointPrefix = MetricNamePrefix + "entrypoint_"
|
||||||
entrypointReqDurationName = metricNamePrefix + "entrypoint_request_duration_seconds"
|
entrypointReqsTotalName = metricEntryPointPrefix + "requests_total"
|
||||||
entrypointOpenConnsName = metricNamePrefix + "entrypoint_open_connections"
|
entrypointReqDurationName = metricEntryPointPrefix + "request_duration_seconds"
|
||||||
|
entrypointOpenConnsName = metricEntryPointPrefix + "open_connections"
|
||||||
|
|
||||||
// backend level
|
// backend level.
|
||||||
backendReqsTotalName = metricNamePrefix + "backend_requests_total"
|
|
||||||
backendReqDurationName = metricNamePrefix + "backend_request_duration_seconds"
|
// MetricBackendPrefix prefix of all backend metric names
|
||||||
backendOpenConnsName = metricNamePrefix + "backend_open_connections"
|
MetricBackendPrefix = MetricNamePrefix + "backend_"
|
||||||
backendRetriesTotalName = metricNamePrefix + "backend_retries_total"
|
backendReqsTotalName = MetricBackendPrefix + "requests_total"
|
||||||
backendServerUpName = metricNamePrefix + "backend_server_up"
|
backendReqDurationName = MetricBackendPrefix + "request_duration_seconds"
|
||||||
|
backendOpenConnsName = MetricBackendPrefix + "open_connections"
|
||||||
|
backendRetriesTotalName = MetricBackendPrefix + "retries_total"
|
||||||
|
backendServerUpName = MetricBackendPrefix + "server_up"
|
||||||
)
|
)
|
||||||
|
|
||||||
// promState holds all metric state internally and acts as the only Collector we register for Prometheus.
|
// promState holds all metric state internally and acts as the only Collector we register for Prometheus.
|
||||||
|
@ -61,6 +68,16 @@ func (h PrometheusHandler) AddRoutes(router *mux.Router) {
|
||||||
// RegisterPrometheus registers all Prometheus metrics.
|
// RegisterPrometheus registers all Prometheus metrics.
|
||||||
// It must be called only once and failing to register the metrics will lead to a panic.
|
// It must be called only once and failing to register the metrics will lead to a panic.
|
||||||
func RegisterPrometheus(config *types.Prometheus) Registry {
|
func RegisterPrometheus(config *types.Prometheus) Registry {
|
||||||
|
standardRegistry := initStandardRegistry(config)
|
||||||
|
|
||||||
|
if !registerPromState() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return standardRegistry
|
||||||
|
}
|
||||||
|
|
||||||
|
func initStandardRegistry(config *types.Prometheus) Registry {
|
||||||
buckets := []float64{0.1, 0.3, 1.2, 5.0}
|
buckets := []float64{0.1, 0.3, 1.2, 5.0}
|
||||||
if config.Buckets != nil {
|
if config.Buckets != nil {
|
||||||
buckets = config.Buckets
|
buckets = config.Buckets
|
||||||
|
@ -137,7 +154,6 @@ func RegisterPrometheus(config *types.Prometheus) Registry {
|
||||||
backendRetries.cv.Describe,
|
backendRetries.cv.Describe,
|
||||||
backendServerUp.gv.Describe,
|
backendServerUp.gv.Describe,
|
||||||
}
|
}
|
||||||
stdprometheus.MustRegister(promState)
|
|
||||||
|
|
||||||
return &standardRegistry{
|
return &standardRegistry{
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -156,6 +172,17 @@ func RegisterPrometheus(config *types.Prometheus) Registry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func registerPromState() bool {
|
||||||
|
if err := stdprometheus.Register(promState); err != nil {
|
||||||
|
if _, ok := err.(stdprometheus.AlreadyRegisteredError); !ok {
|
||||||
|
log.Errorf("Unable to register Traefik to Prometheus: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
log.Debug("Prometheus collector already registered.")
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// OnConfigurationUpdate receives the current configuration from Traefik.
|
// OnConfigurationUpdate receives the current configuration from Traefik.
|
||||||
// It then converts the configuration to the optimized package internal format
|
// It then converts the configuration to the optimized package internal format
|
||||||
// and sets it to the promState.
|
// and sets it to the promState.
|
||||||
|
|
|
@ -11,8 +11,82 @@ import (
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestRegisterPromState(t *testing.T) {
|
||||||
|
// Reset state of global promState.
|
||||||
|
defer promState.reset()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
prometheusSlice []*types.Prometheus
|
||||||
|
initPromState bool
|
||||||
|
unregisterPromState bool
|
||||||
|
expectedNbRegistries int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "Register once",
|
||||||
|
prometheusSlice: []*types.Prometheus{{}},
|
||||||
|
expectedNbRegistries: 1,
|
||||||
|
initPromState: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Register once with no promState init",
|
||||||
|
prometheusSlice: []*types.Prometheus{{}},
|
||||||
|
expectedNbRegistries: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Register twice",
|
||||||
|
prometheusSlice: []*types.Prometheus{{}, {}},
|
||||||
|
expectedNbRegistries: 2,
|
||||||
|
initPromState: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Register twice with no promstate init",
|
||||||
|
prometheusSlice: []*types.Prometheus{{}, {}},
|
||||||
|
expectedNbRegistries: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Register twice with unregister",
|
||||||
|
prometheusSlice: []*types.Prometheus{{}, {}},
|
||||||
|
unregisterPromState: true,
|
||||||
|
expectedNbRegistries: 2,
|
||||||
|
initPromState: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Register twice with unregister but no promstate init",
|
||||||
|
prometheusSlice: []*types.Prometheus{{}, {}},
|
||||||
|
unregisterPromState: true,
|
||||||
|
expectedNbRegistries: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
actualNbRegistries := 0
|
||||||
|
for _, prom := range test.prometheusSlice {
|
||||||
|
if test.initPromState {
|
||||||
|
initStandardRegistry(prom)
|
||||||
|
}
|
||||||
|
|
||||||
|
promReg := registerPromState()
|
||||||
|
if promReg != false {
|
||||||
|
actualNbRegistries++
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.unregisterPromState {
|
||||||
|
prometheus.Unregister(promState)
|
||||||
|
}
|
||||||
|
|
||||||
|
promState.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
prometheus.Unregister(promState)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expectedNbRegistries, actualNbRegistries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// reset is a utility method for unit testing. It should be called after each
|
// reset is a utility method for unit testing. It should be called after each
|
||||||
// test run that changes promState internally in order to avoid dependencies
|
// test run that changes promState internally in order to avoid dependencies
|
||||||
// between unit tests.
|
// between unit tests.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
mkdocs>=0.17.3
|
mkdocs==0.17.5
|
||||||
pymdown-extensions>=1.4
|
pymdown-extensions==4.12
|
||||||
mkdocs-bootswatch>=0.4.0
|
mkdocs-bootswatch==0.5.0
|
||||||
mkdocs-material>=2.2.6
|
mkdocs-material==2.9.4
|
||||||
|
|
|
@ -633,9 +633,12 @@ func registerMetricClients(metricsConfig *types.Metrics) metrics.Registry {
|
||||||
|
|
||||||
var registries []metrics.Registry
|
var registries []metrics.Registry
|
||||||
if metricsConfig.Prometheus != nil {
|
if metricsConfig.Prometheus != nil {
|
||||||
registries = append(registries, metrics.RegisterPrometheus(metricsConfig.Prometheus))
|
prometheusRegister := metrics.RegisterPrometheus(metricsConfig.Prometheus)
|
||||||
|
if prometheusRegister != nil {
|
||||||
|
registries = append(registries, prometheusRegister)
|
||||||
log.Debug("Configured Prometheus metrics")
|
log.Debug("Configured Prometheus metrics")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if metricsConfig.Datadog != nil {
|
if metricsConfig.Datadog != nil {
|
||||||
registries = append(registries, metrics.RegisterDatadog(metricsConfig.Datadog))
|
registries = append(registries, metrics.RegisterDatadog(metricsConfig.Datadog))
|
||||||
log.Debugf("Configured DataDog metrics pushing to %s once every %s", metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval)
|
log.Debugf("Configured DataDog metrics pushing to %s once every %s", metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval)
|
||||||
|
|
Loading…
Reference in a new issue