Do not create observability model by default

Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
This commit is contained in:
Romain 2025-01-29 13:56:04 +01:00 committed by GitHub
parent fb527dac1c
commit 857fbb933e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 133 additions and 62 deletions

View file

@ -191,14 +191,14 @@ func applyModel(cfg dynamic.Configuration) dynamic.Configuration {
cp.Observability.AccessLogs = m.Observability.AccessLogs
}
if cp.Observability.Tracing == nil {
cp.Observability.Tracing = m.Observability.Tracing
}
if cp.Observability.Metrics == nil {
cp.Observability.Metrics = m.Observability.Metrics
}
if cp.Observability.Tracing == nil {
cp.Observability.Tracing = m.Observability.Tracing
}
rtName := name
if len(eps) > 1 {
rtName = epName + "-" + name
@ -215,6 +215,9 @@ func applyModel(cfg dynamic.Configuration) dynamic.Configuration {
cfg.HTTP.Routers = rts
}
// Apply default observability model to HTTP routers.
applyDefaultObservabilityModel(cfg)
if cfg.TCP == nil || len(cfg.TCP.Models) == 0 {
return cfg
}
@ -238,3 +241,38 @@ func applyModel(cfg dynamic.Configuration) dynamic.Configuration {
return cfg
}
// applyDefaultObservabilityModel applies the default observability model to the configuration.
// This function is used to ensure that the observability configuration is set for all routers,
// and make sure it is serialized and available in the API.
// We could have introduced a "default" model, but it would have been more complex to manage for now.
// This could be generalized in the future.
func applyDefaultObservabilityModel(cfg dynamic.Configuration) {
if cfg.HTTP != nil {
for _, router := range cfg.HTTP.Routers {
if router.Observability == nil {
router.Observability = &dynamic.RouterObservabilityConfig{
AccessLogs: pointer(true),
Metrics: pointer(true),
Tracing: pointer(true),
}
continue
}
if router.Observability.AccessLogs == nil {
router.Observability.AccessLogs = pointer(true)
}
if router.Observability.Tracing == nil {
router.Observability.Tracing = pointer(true)
}
if router.Observability.Metrics == nil {
router.Observability.Metrics = pointer(true)
}
}
}
}
func pointer[T any](v T) *T { return &v }

View file

@ -9,8 +9,6 @@ import (
"github.com/traefik/traefik/v3/pkg/tls"
)
func pointer[T any](v T) *T { return &v }
func Test_mergeConfiguration(t *testing.T) {
testCases := []struct {
desc string
@ -508,6 +506,33 @@ func Test_applyModel(t *testing.T) {
},
},
},
{
desc: "without model, one router",
input: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{"test": {}},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: make(map[string]*dynamic.Model),
},
},
expected: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
Observability: &dynamic.RouterObservabilityConfig{
AccessLogs: pointer(true),
Metrics: pointer(true),
Tracing: pointer(true),
},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: make(map[string]*dynamic.Model),
},
},
},
{
desc: "with model, not used",
input: dynamic.Configuration{
@ -560,10 +585,14 @@ func Test_applyModel(t *testing.T) {
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"websecure"},
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
Observability: &dynamic.RouterObservabilityConfig{},
EntryPoints: []string{"websecure"},
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
Observability: &dynamic.RouterObservabilityConfig{
AccessLogs: pointer(true),
Metrics: pointer(true),
Tracing: pointer(true),
},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
@ -659,9 +688,9 @@ func Test_applyModel(t *testing.T) {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{CertResolver: "router"},
Observability: &dynamic.RouterObservabilityConfig{
AccessLogs: nil,
Tracing: nil,
Metrics: nil,
AccessLogs: pointer(true),
Metrics: pointer(true),
Tracing: pointer(true),
},
},
},
@ -700,12 +729,21 @@ func Test_applyModel(t *testing.T) {
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"web"},
Observability: &dynamic.RouterObservabilityConfig{
AccessLogs: pointer(true),
Metrics: pointer(true),
Tracing: pointer(true),
},
},
"websecure-test": {
EntryPoints: []string{"websecure"},
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
Observability: &dynamic.RouterObservabilityConfig{},
EntryPoints: []string{"websecure"},
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
Observability: &dynamic.RouterObservabilityConfig{
AccessLogs: pointer(true),
Metrics: pointer(true),
Tracing: pointer(true),
},
},
},
Middlewares: make(map[string]*dynamic.Middleware),

View file

@ -84,7 +84,8 @@ func TestNewConfigurationWatcher(t *testing.T) {
th.WithRouters(
th.WithRouter("test@mock",
th.WithEntryPoints("e"),
th.WithServiceName("scv"))),
th.WithServiceName("scv"),
th.WithObservability())),
th.WithMiddlewares(),
th.WithLoadBalancerServices(),
),
@ -175,7 +176,7 @@ func TestIgnoreTransientConfiguration(t *testing.T) {
expectedConfig := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"))),
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
th.WithLoadBalancerServices(th.WithService("bar@mock")),
th.WithMiddlewares(),
),
@ -200,7 +201,7 @@ func TestIgnoreTransientConfiguration(t *testing.T) {
expectedConfig3 := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"))),
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
th.WithLoadBalancerServices(th.WithService("bar-config3@mock")),
th.WithMiddlewares(),
),
@ -447,7 +448,7 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"))),
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
th.WithLoadBalancerServices(th.WithService("bar@mock")),
th.WithMiddlewares(),
),
@ -538,7 +539,7 @@ func TestListenProvidersIgnoreSameConfig(t *testing.T) {
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"))),
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
th.WithLoadBalancerServices(th.WithService("bar@mock")),
th.WithMiddlewares(),
),
@ -674,7 +675,7 @@ func TestListenProvidersIgnoreIntermediateConfigs(t *testing.T) {
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("final@mock", th.WithEntryPoints("ep"))),
th.WithRouters(th.WithRouter("final@mock", th.WithEntryPoints("ep"), th.WithObservability())),
th.WithLoadBalancerServices(th.WithService("final@mock")),
th.WithMiddlewares(),
),
@ -738,8 +739,8 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(
th.WithRouter("foo@mock", th.WithEntryPoints("ep")),
th.WithRouter("foo@mock2", th.WithEntryPoints("ep")),
th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability()),
th.WithRouter("foo@mock2", th.WithEntryPoints("ep"), th.WithObservability()),
),
th.WithLoadBalancerServices(
th.WithService("bar@mock"),

View file

@ -110,7 +110,7 @@ func (o *ObservabilityMgr) ShouldAddAccessLogs(serviceName string, observability
return false
}
return observabilityConfig == nil || observabilityConfig.AccessLogs != nil && *observabilityConfig.AccessLogs
return observabilityConfig == nil || observabilityConfig.AccessLogs == nil || *observabilityConfig.AccessLogs
}
// ShouldAddMetrics returns whether the metrics should be enabled for the given resource and the observability config.
@ -127,7 +127,7 @@ func (o *ObservabilityMgr) ShouldAddMetrics(serviceName string, observabilityCon
return false
}
return observabilityConfig == nil || observabilityConfig.Metrics != nil && *observabilityConfig.Metrics
return observabilityConfig == nil || observabilityConfig.Metrics == nil || *observabilityConfig.Metrics
}
// ShouldAddTracing returns whether the tracing should be enabled for the given serviceName and the observability config.
@ -144,7 +144,7 @@ func (o *ObservabilityMgr) ShouldAddTracing(serviceName string, observabilityCon
return false
}
return observabilityConfig == nil || observabilityConfig.Tracing != nil && *observabilityConfig.Tracing
return observabilityConfig == nil || observabilityConfig.Tracing == nil || *observabilityConfig.Tracing
}
// MetricsRegistry is an accessor to the metrics registry.