Log provider namespace during startup

This commit is contained in:
shreealt 2025-10-03 19:00:05 +05:30 committed by GitHub
parent 0b7f0b4042
commit 7cc8b099d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 86 additions and 2 deletions

View File

@ -2,6 +2,7 @@ package aggregator
import (
"context"
"fmt"
"time"
"github.com/rs/zerolog/log"
@ -203,8 +204,16 @@ func (p *ProviderAggregator) launchProvider(configurationChan chan<- dynamic.Mes
log.Debug().Err(err).Msgf("Cannot marshal the provider configuration %T", prd)
}
log.Info().Msgf("Starting provider %T", prd)
log.Debug().RawJSON("config", []byte(jsonConf)).Msgf("%T provider configuration", prd)
// Check if provider has namespace information.
var namespaceInfo string
if namespaceProvider, ok := prd.(provider.NamespacedProvider); ok {
if namespace := namespaceProvider.Namespace(); namespace != "" {
namespaceInfo = fmt.Sprintf(" (namespace: %s)", namespace)
}
}
log.Info().Msgf("Starting provider %T%s", prd, namespaceInfo)
log.Debug().RawJSON("config", []byte(jsonConf)).Msgf("%T provider configuration%s", prd, namespaceInfo)
if err := maybeThrottledProvide(prd, p.providersThrottleDuration)(configurationChan, pool); err != nil {
log.Error().Err(err).Msgf("Cannot start the provider %T", prd)

View File

@ -1,9 +1,13 @@
package aggregator
import (
"bytes"
"testing"
"time"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/provider"
@ -40,6 +44,34 @@ func TestProviderAggregator_Provide(t *testing.T) {
require.NoError(t, <-errCh)
}
func TestLaunchNamespacedProvider(t *testing.T) {
// Capture log output
var buf bytes.Buffer
originalLogger := log.Logger
log.Logger = zerolog.New(&buf).Level(zerolog.InfoLevel)
providerWithNamespace := &mockNamespacedProvider{namespace: "test-namespace"}
aggregator := ProviderAggregator{
internalProvider: providerWithNamespace,
}
cfgCh := make(chan dynamic.Message)
pool := safe.NewPool(t.Context())
t.Cleanup(func() {
pool.Stop()
log.Logger = originalLogger
})
err := aggregator.Provide(cfgCh, pool)
require.NoError(t, err)
output := buf.String()
assert.Contains(t, output, "Starting provider *aggregator.mockNamespacedProvider (namespace: test-namespace)")
}
// requireReceivedMessageFromProviders makes sure the given providers have emitted a message on the given message channel.
// Providers order is not enforced.
func requireReceivedMessageFromProviders(t *testing.T, cfgCh <-chan dynamic.Message, names []string) {
@ -76,3 +108,20 @@ func (p *providerMock) Provide(configurationChan chan<- dynamic.Message, pool *s
return nil
}
// mockNamespacedProvider is a mock implementation of NamespacedProvider for testing.
type mockNamespacedProvider struct {
namespace string
}
func (m *mockNamespacedProvider) Namespace() string {
return m.namespace
}
func (m *mockNamespacedProvider) Provide(_ chan<- dynamic.Message, _ *safe.Pool) error {
return nil
}
func (m *mockNamespacedProvider) Init() error {
return nil
}

View File

@ -647,3 +647,8 @@ func repeatSend(ctx context.Context, interval time.Duration, c chan<- struct{})
}
}
}
// Namespace returns the namespace of the ConsulCatalog provider.
func (p *Provider) Namespace() string {
return p.namespace
}

View File

@ -97,3 +97,8 @@ func (p *Provider) Init() error {
return p.Provider.Init(consul.StoreName, p.name, config)
}
// Namespace returns the namespace of the Consul provider.
func (p *Provider) Namespace() string {
return p.namespace
}

View File

@ -571,3 +571,8 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s
return eventsChanBuffered
}
// Namespace returns the namespace of the Nomad provider.
func (p *Provider) Namespace() string {
return p.namespace
}

View File

@ -12,3 +12,14 @@ type Provider interface {
Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error
Init() error
}
// NamespacedProvider is implemented by providers that support namespace-scoped configurations,
// where each configured namespace results in a dedicated provider instance.
// This enables clear identification of which namespace each provider instance serves during
// startup logging and operational monitoring.
type NamespacedProvider interface {
Provider
// Namespace returns the specific namespace this provider instance is configured for.
Namespace() string
}