Merge pull request #17138 from wbollock/feat/prometheus_refresh_config_label

feat(metrics): add config label to refresh metrics
This commit is contained in:
Bryan Boreham 2025-11-13 14:51:39 +01:00 committed by GitHub
commit e02a65b6bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 307 additions and 176 deletions

View File

@ -113,7 +113,7 @@ func (*EC2SDConfig) Name() string { return "ec2" }
// NewDiscoverer returns a Discoverer for the EC2 Config.
func (c *EC2SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewEC2Discovery(c, opts.Logger, opts.Metrics)
return NewEC2Discovery(c, opts)
}
// UnmarshalYAML implements the yaml.Unmarshaler interface for the EC2 Config.
@ -180,23 +180,24 @@ type EC2Discovery struct {
}
// NewEC2Discovery returns a new EC2Discovery which periodically refreshes its targets.
func NewEC2Discovery(conf *EC2SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*EC2Discovery, error) {
m, ok := metrics.(*ec2Metrics)
func NewEC2Discovery(conf *EC2SDConfig, opts discovery.DiscovererOptions) (*EC2Discovery, error) {
m, ok := opts.Metrics.(*ec2Metrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
if logger == nil {
logger = promslog.NewNopLogger()
if opts.Logger == nil {
opts.Logger = promslog.NewNopLogger()
}
d := &EC2Discovery{
logger: logger,
logger: opts.Logger,
cfg: conf,
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "ec2",
SetName: opts.SetName,
Interval: time.Duration(d.cfg.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net"
"strconv"
"strings"
@ -95,7 +94,7 @@ func (*LightsailSDConfig) Name() string { return "lightsail" }
// NewDiscoverer returns a Discoverer for the Lightsail Config.
func (c *LightsailSDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewLightsailDiscovery(c, opts.Logger, opts.Metrics)
return NewLightsailDiscovery(c, opts)
}
// UnmarshalYAML implements the yaml.Unmarshaler interface for the Lightsail Config.
@ -145,14 +144,14 @@ type LightsailDiscovery struct {
}
// NewLightsailDiscovery returns a new LightsailDiscovery which periodically refreshes its targets.
func NewLightsailDiscovery(conf *LightsailSDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*LightsailDiscovery, error) {
m, ok := metrics.(*lightsailMetrics)
func NewLightsailDiscovery(conf *LightsailSDConfig, opts discovery.DiscovererOptions) (*LightsailDiscovery, error) {
m, ok := opts.Metrics.(*lightsailMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
if logger == nil {
logger = promslog.NewNopLogger()
if opts.Logger == nil {
opts.Logger = promslog.NewNopLogger()
}
d := &LightsailDiscovery{
@ -160,8 +159,9 @@ func NewLightsailDiscovery(conf *LightsailSDConfig, logger *slog.Logger, metrics
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "lightsail",
SetName: opts.SetName,
Interval: time.Duration(d.cfg.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -127,7 +127,7 @@ func (*SDConfig) Name() string { return "azure" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
func validateAuthParam(param, name string) error {
@ -178,28 +178,29 @@ type Discovery struct {
}
// NewDiscovery returns a new AzureDiscovery which periodically refreshes its targets.
func NewDiscovery(cfg *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*azureMetrics)
func NewDiscovery(cfg *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*azureMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
if logger == nil {
logger = promslog.NewNopLogger()
if opts.Logger == nil {
opts.Logger = promslog.NewNopLogger()
}
l := cache.New(cache.AsLRU[string, *armnetwork.Interface](lru.WithCapacity(5000)))
d := &Discovery{
cfg: cfg,
port: cfg.Port,
logger: logger,
logger: opts.Logger,
cache: l,
metrics: m,
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "azure",
SetName: opts.SetName,
Interval: time.Duration(cfg.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -659,7 +659,11 @@ func TestAzureRefresh(t *testing.T) {
refreshMetrics := discovery.NewRefreshMetrics(reg)
metrics := azureSDConfig.NewDiscovererMetrics(reg, refreshMetrics)
sd, err := NewDiscovery(azureSDConfig, nil, metrics)
sd, err := NewDiscovery(azureSDConfig, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "azure",
})
require.NoError(t, err)
tg, err := sd.refreshAzureClient(context.Background(), azureClient)

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net"
"net/http"
"strconv"
@ -84,7 +83,7 @@ func (*SDConfig) Name() string { return "digitalocean" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -112,8 +111,8 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*digitaloceanMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*digitaloceanMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -140,8 +139,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "digitalocean",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -57,7 +57,11 @@ func TestDigitalOceanSDRefresh(t *testing.T) {
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "digitalocean",
})
require.NoError(t, err)
endpoint, err := url.Parse(sdmock.Mock.Endpoint())
require.NoError(t, err)

View File

@ -54,6 +54,9 @@ type DiscovererOptions struct {
// Extra HTTP client options to expose to Discoverers. This field may be
// ignored; Discoverer implementations must opt-in to reading it.
HTTPClientOptions []config.HTTPClientOption
// SetName identifies this discoverer set.
SetName string
}
// RefreshMetrics are used by the "refresh" package.
@ -66,7 +69,7 @@ type RefreshMetrics struct {
// RefreshMetricsInstantiator instantiates the metrics used by the "refresh" package.
type RefreshMetricsInstantiator interface {
Instantiate(mech string) *RefreshMetrics
Instantiate(mech, setName string) *RefreshMetrics
}
// RefreshMetricsManager is an interface for registering, unregistering, and

View File

@ -78,7 +78,7 @@ func (*SDConfig) Name() string { return "dns" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(*c, opts.Logger, opts.Metrics)
return NewDiscovery(*c, opts)
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.
@ -118,14 +118,14 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*dnsMetrics)
func NewDiscovery(conf SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*dnsMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
if logger == nil {
logger = promslog.NewNopLogger()
if opts.Logger == nil {
opts.Logger = promslog.NewNopLogger()
}
qtype := dns.TypeSRV
@ -145,15 +145,16 @@ func NewDiscovery(conf SDConfig, logger *slog.Logger, metrics discovery.Discover
names: conf.Names,
qtype: qtype,
port: conf.Port,
logger: logger,
logger: opts.Logger,
lookupFn: lookupWithSearchPath,
metrics: m,
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "dns",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -259,7 +259,11 @@ func TestDNS(t *testing.T) {
metrics := tc.config.NewDiscovererMetrics(reg, refreshMetrics)
require.NoError(t, metrics.Register())
sd, err := NewDiscovery(tc.config, nil, metrics)
sd, err := NewDiscovery(tc.config, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "dns",
})
require.NoError(t, err)
sd.lookupFn = tc.lookup

View File

@ -16,7 +16,6 @@ package eureka
import (
"context"
"errors"
"log/slog"
"net"
"net/http"
"net/url"
@ -88,7 +87,7 @@ func (*SDConfig) Name() string { return "eureka" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -125,8 +124,8 @@ type Discovery struct {
}
// NewDiscovery creates a new Eureka discovery for the given role.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*eurekaMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*eurekaMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -142,8 +141,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "eureka",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -47,7 +47,11 @@ func testUpdateServices(respHandler http.HandlerFunc) ([]*targetgroup.Group, err
defer metrics.Unregister()
defer refreshMetrics.Unregister()
md, err := NewDiscovery(&conf, nil, metrics)
md, err := NewDiscovery(&conf, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "eureka",
})
if err != nil {
return nil, err
}

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net/http"
"strconv"
"strings"
@ -94,7 +93,7 @@ func (*SDConfig) Name() string { return "gce" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(*c, opts.Logger, opts.Metrics)
return NewDiscovery(*c, opts)
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.
@ -129,8 +128,8 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*gceMetrics)
func NewDiscovery(conf SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*gceMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -155,8 +154,9 @@ func NewDiscovery(conf SDConfig, logger *slog.Logger, metrics discovery.Discover
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "gce",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -78,7 +78,7 @@ func (*SDConfig) Name() string { return "hetzner" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
type refresher interface {
@ -138,21 +138,22 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*refresh.Discovery, error) {
m, ok := metrics.(*hetznerMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*refresh.Discovery, error) {
m, ok := opts.Metrics.(*hetznerMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
r, err := newRefresher(conf, logger)
r, err := newRefresher(conf, opts.Logger)
if err != nil {
return nil, err
}
return refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "hetzner",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: r.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -19,7 +19,6 @@ import (
"errors"
"fmt"
"io"
"log/slog"
"net/http"
"net/url"
"strconv"
@ -69,7 +68,7 @@ func (*SDConfig) Name() string { return "http" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.HTTPClientOptions, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -115,17 +114,17 @@ type Discovery struct {
}
// NewDiscovery returns a new HTTP discovery for the given config.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, clientOpts []config.HTTPClientOption, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*httpMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*httpMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
if logger == nil {
logger = promslog.NewNopLogger()
if opts.Logger == nil {
opts.Logger = promslog.NewNopLogger()
}
client, err := config.NewClientFromConfig(conf.HTTPClientConfig, "http", clientOpts...)
client, err := config.NewClientFromConfig(conf.HTTPClientConfig, "http", opts.HTTPClientOptions...)
if err != nil {
return nil, err
}
@ -140,8 +139,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, clientOpts []config.HTTPC
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "http",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.Refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -49,7 +49,12 @@ func TestHTTPValidRefresh(t *testing.T) {
require.NoError(t, metrics.Register())
defer metrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), nil, metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
HTTPClientOptions: nil,
Metrics: metrics,
SetName: "http",
})
require.NoError(t, err)
ctx := context.Background()
@ -94,7 +99,12 @@ func TestHTTPInvalidCode(t *testing.T) {
require.NoError(t, metrics.Register())
defer metrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), nil, metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
HTTPClientOptions: nil,
Metrics: metrics,
SetName: "http",
})
require.NoError(t, err)
ctx := context.Background()
@ -123,7 +133,12 @@ func TestHTTPInvalidFormat(t *testing.T) {
require.NoError(t, metrics.Register())
defer metrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), nil, metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
HTTPClientOptions: nil,
Metrics: metrics,
SetName: "http",
})
require.NoError(t, err)
ctx := context.Background()
@ -442,7 +457,12 @@ func TestSourceDisappeared(t *testing.T) {
require.NoError(t, metrics.Register())
defer metrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), nil, metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
HTTPClientOptions: nil,
Metrics: metrics,
SetName: "http",
})
require.NoError(t, err)
for _, test := range cases {
ctx := context.Background()

View File

@ -15,7 +15,6 @@ package ionos
import (
"errors"
"log/slog"
"time"
"github.com/prometheus/client_golang/prometheus"
@ -42,8 +41,8 @@ func init() {
type Discovery struct{}
// NewDiscovery returns a new refresh.Discovery for IONOS Cloud.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*refresh.Discovery, error) {
m, ok := metrics.(*ionosMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*refresh.Discovery, error) {
m, ok := opts.Metrics.(*ionosMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -52,15 +51,16 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
conf.ionosEndpoint = "https://api.ionos.com"
}
d, err := newServerDiscovery(conf, logger)
d, err := newServerDiscovery(conf, opts.Logger)
if err != nil {
return nil, err
}
return refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "ionos",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,
@ -101,8 +101,8 @@ func (SDConfig) Name() string {
}
// NewDiscoverer returns a new discovery.Discoverer for IONOS Cloud.
func (c SDConfig) NewDiscoverer(options discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(&c, options.Logger, options.Metrics)
func (c SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(&c, opts)
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net"
"net/http"
"strconv"
@ -103,7 +102,7 @@ func (*SDConfig) Name() string { return "linode" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -138,8 +137,8 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*linodeMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*linodeMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -170,8 +169,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "linode",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -238,7 +238,11 @@ func TestLinodeSDRefresh(t *testing.T) {
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "linode",
})
require.NoError(t, err)
endpoint, err := url.Parse(sdmock.Endpoint())
require.NoError(t, err)

View File

@ -479,6 +479,7 @@ func (m *Manager) registerProviders(cfgs Configs, setName string) int {
Logger: m.logger.With("discovery", typ, "config", setName),
HTTPClientOptions: m.httpOpts,
Metrics: m.sdMetrics[typ],
SetName: setName,
})
if err != nil {
m.logger.Error("Cannot create service discovery", "err", err, "type", typ, "config", setName)

View File

@ -19,7 +19,6 @@ import (
"errors"
"fmt"
"io"
"log/slog"
"math/rand"
"net"
"net/http"
@ -91,7 +90,7 @@ func (*SDConfig) Name() string { return "marathon" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(*c, opts.Logger, opts.Metrics)
return NewDiscovery(*c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -140,8 +139,8 @@ type Discovery struct {
}
// NewDiscovery returns a new Marathon Discovery.
func NewDiscovery(conf SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*marathonMetrics)
func NewDiscovery(conf SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*marathonMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -168,8 +167,9 @@ func NewDiscovery(conf SDConfig, logger *slog.Logger, metrics discovery.Discover
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "marathon",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -51,7 +51,11 @@ func testUpdateServices(client appListClient) ([]*targetgroup.Group, error) {
defer metrics.Unregister()
defer refreshMetrics.Unregister()
md, err := NewDiscovery(cfg, nil, metrics)
md, err := NewDiscovery(cfg, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "marathon",
})
if err != nil {
return nil, err
}
@ -132,7 +136,11 @@ func TestMarathonSDRemoveApp(t *testing.T) {
defer metrics.Unregister()
defer refreshMetrics.Unregister()
md, err := NewDiscovery(cfg, nil, metrics)
md, err := NewDiscovery(cfg, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "marathon",
})
require.NoError(t, err)
md.appsClient = func(context.Context, *http.Client, string) (*appList, error) {

View File

@ -36,14 +36,14 @@ func NewRefreshMetrics(reg prometheus.Registerer) RefreshMetricsManager {
Name: "prometheus_sd_refresh_failures_total",
Help: "Number of refresh failures for the given SD mechanism.",
},
[]string{"mechanism"}),
[]string{"mechanism", "config"}),
durationVec: prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Name: "prometheus_sd_refresh_duration_seconds",
Help: "The duration of a refresh in seconds for the given SD mechanism.",
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
},
[]string{"mechanism"}),
[]string{"mechanism", "config"}),
}
// The reason we register metric vectors instead of metrics is so that
@ -56,11 +56,11 @@ func NewRefreshMetrics(reg prometheus.Registerer) RefreshMetricsManager {
return m
}
// Instantiate returns metrics out of metric vectors.
func (m *RefreshMetricsVecs) Instantiate(mech string) *RefreshMetrics {
// Instantiate returns metrics out of metric vectors for a given mechanism and config.
func (m *RefreshMetricsVecs) Instantiate(mech, config string) *RefreshMetrics {
return &RefreshMetrics{
Failures: m.failuresVec.WithLabelValues(mech),
Duration: m.durationVec.WithLabelValues(mech),
Failures: m.failuresVec.WithLabelValues(mech, config),
Duration: m.durationVec.WithLabelValues(mech, config),
}
}

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net"
"net/http"
"net/url"
@ -94,7 +93,7 @@ func (*DockerSDConfig) Name() string { return "docker" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *DockerSDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDockerDiscovery(c, opts.Logger, opts.Metrics)
return NewDockerDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -129,8 +128,8 @@ type DockerDiscovery struct {
}
// NewDockerDiscovery returns a new DockerDiscovery which periodically refreshes its targets.
func NewDockerDiscovery(conf *DockerSDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*DockerDiscovery, error) {
m, ok := metrics.(*dockerMetrics)
func NewDockerDiscovery(conf *DockerSDConfig, opts discovery.DiscovererOptions) (*DockerDiscovery, error) {
m, ok := opts.Metrics.(*dockerMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -146,7 +145,7 @@ func NewDockerDiscovery(conf *DockerSDConfig, logger *slog.Logger, metrics disco
return nil, err
}
opts := []client.Opt{
clientOpts := []client.Opt{
client.WithHost(conf.Host),
client.WithAPIVersionNegotiation(),
}
@ -166,7 +165,7 @@ func NewDockerDiscovery(conf *DockerSDConfig, logger *slog.Logger, metrics disco
if err != nil {
return nil, err
}
opts = append(opts,
clientOpts = append(clientOpts,
client.WithHTTPClient(&http.Client{
Transport: rt,
Timeout: time.Duration(conf.RefreshInterval),
@ -178,15 +177,16 @@ func NewDockerDiscovery(conf *DockerSDConfig, logger *slog.Logger, metrics disco
)
}
d.client, err = client.NewClientWithOpts(opts...)
d.client, err = client.NewClientWithOpts(clientOpts...)
if err != nil {
return nil, fmt.Errorf("error setting up docker client: %w", err)
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "docker",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -48,7 +48,11 @@ host: %s
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDockerDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDockerDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "docker_swarm",
})
require.NoError(t, err)
ctx := context.Background()
@ -226,7 +230,11 @@ host: %s
require.NoError(t, metrics.Register())
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDockerDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDockerDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "docker_swarm",
})
require.NoError(t, err)
ctx := context.Background()

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net/http"
"net/url"
"time"
@ -81,7 +80,7 @@ func (*DockerSwarmSDConfig) Name() string { return "dockerswarm" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *DockerSwarmSDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -124,8 +123,8 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf *DockerSwarmSDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*dockerswarmMetrics)
func NewDiscovery(conf *DockerSwarmSDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*dockerswarmMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -140,7 +139,7 @@ func NewDiscovery(conf *DockerSwarmSDConfig, logger *slog.Logger, metrics discov
return nil, err
}
opts := []client.Opt{
clientOpts := []client.Opt{
client.WithHost(conf.Host),
client.WithAPIVersionNegotiation(),
}
@ -160,7 +159,7 @@ func NewDiscovery(conf *DockerSwarmSDConfig, logger *slog.Logger, metrics discov
if err != nil {
return nil, err
}
opts = append(opts,
clientOpts = append(clientOpts,
client.WithHTTPClient(&http.Client{
Transport: rt,
Timeout: time.Duration(conf.RefreshInterval),
@ -172,15 +171,16 @@ func NewDiscovery(conf *DockerSwarmSDConfig, logger *slog.Logger, metrics discov
)
}
d.client, err = client.NewClientWithOpts(opts...)
d.client, err = client.NewClientWithOpts(clientOpts...)
if err != nil {
return nil, fmt.Errorf("error setting up docker swarm client: %w", err)
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "dockerswarm",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -48,7 +48,11 @@ host: %s
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "docker_swarm",
})
require.NoError(t, err)
ctx := context.Background()

View File

@ -48,7 +48,11 @@ host: %s
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "moby",
})
require.NoError(t, err)
ctx := context.Background()
@ -349,7 +353,11 @@ filters:
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "moby",
})
require.NoError(t, err)
ctx := context.Background()

View File

@ -48,7 +48,11 @@ host: %s
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "docker_swarm",
})
require.NoError(t, err)
ctx := context.Background()

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net"
"strconv"
"strings"
@ -84,7 +83,7 @@ func (*SDConfig) Name() string { return "nomad" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -121,8 +120,8 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*nomadMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*nomadMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -157,8 +156,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "nomad",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -150,7 +150,11 @@ func TestConfiguredService(t *testing.T) {
require.NoError(t, metrics.Register())
defer metrics.Unregister()
_, err := NewDiscovery(conf, nil, metrics)
_, err := NewDiscovery(conf, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "nomad",
})
if tc.acceptedURL {
require.NoError(t, err)
} else {
@ -178,7 +182,11 @@ func TestNomadSDRefresh(t *testing.T) {
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "nomad",
})
require.NoError(t, err)
tgs, err := d.refresh(context.Background())

View File

@ -78,7 +78,7 @@ func (*SDConfig) Name() string { return "openstack" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -145,20 +145,21 @@ type refresher interface {
}
// NewDiscovery returns a new OpenStack Discoverer which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, l *slog.Logger, metrics discovery.DiscovererMetrics) (*refresh.Discovery, error) {
m, ok := metrics.(*openstackMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*refresh.Discovery, error) {
m, ok := opts.Metrics.(*openstackMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
r, err := newRefresher(conf, l)
r, err := newRefresher(conf, opts.Logger)
if err != nil {
return nil, err
}
return refresh.NewDiscovery(
refresh.Options{
Logger: l,
Logger: opts.Logger,
Mech: "openstack",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: r.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -100,8 +100,8 @@ func createClient(config *SDConfig) (*ovh.Client, error) {
}
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(options discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, options.Logger, options.Metrics)
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts)
}
func init() {
@ -148,21 +148,22 @@ func newRefresher(conf *SDConfig, logger *slog.Logger) (refresher, error) {
}
// NewDiscovery returns a new OVHcloud Discoverer which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*refresh.Discovery, error) {
m, ok := metrics.(*ovhcloudMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*refresh.Discovery, error) {
m, ok := opts.Metrics.(*ovhcloudMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
r, err := newRefresher(conf, logger)
r, err := newRefresher(conf, opts.Logger)
if err != nil {
return nil, err
}
return refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "ovhcloud",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: r.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -20,7 +20,6 @@ import (
"errors"
"fmt"
"io"
"log/slog"
"net"
"net/http"
"net/url"
@ -93,7 +92,7 @@ func (*SDConfig) Name() string { return "puppetdb" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -140,14 +139,14 @@ type Discovery struct {
}
// NewDiscovery returns a new PuppetDB discovery for the given config.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*puppetdbMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*puppetdbMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
if logger == nil {
logger = promslog.NewNopLogger()
if opts.Logger == nil {
opts.Logger = promslog.NewNopLogger()
}
client, err := config.NewClientFromConfig(conf.HTTPClientConfig, "http")
@ -172,8 +171,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "puppetdb",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -70,7 +70,11 @@ func TestPuppetSlashInURL(t *testing.T) {
metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)
require.NoError(t, metrics.Register())
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "puppetdb",
})
require.NoError(t, err)
require.Equal(t, apiURL, d.url)
@ -94,7 +98,11 @@ func TestPuppetDBRefresh(t *testing.T) {
metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)
require.NoError(t, metrics.Register())
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "puppetdb",
})
require.NoError(t, err)
ctx := context.Background()
@ -142,7 +150,11 @@ func TestPuppetDBRefreshWithParameters(t *testing.T) {
metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)
require.NoError(t, metrics.Register())
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "puppetdb",
})
require.NoError(t, err)
ctx := context.Background()
@ -201,7 +213,11 @@ func TestPuppetDBInvalidCode(t *testing.T) {
metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)
require.NoError(t, metrics.Register())
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "puppetdb",
})
require.NoError(t, err)
ctx := context.Background()
@ -229,7 +245,11 @@ func TestPuppetDBInvalidFormat(t *testing.T) {
metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)
require.NoError(t, metrics.Register())
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "puppetdb",
})
require.NoError(t, err)
ctx := context.Background()

View File

@ -28,6 +28,7 @@ import (
type Options struct {
Logger *slog.Logger
Mech string
SetName string
Interval time.Duration
RefreshF func(ctx context.Context) ([]*targetgroup.Group, error)
MetricsInstantiator discovery.RefreshMetricsInstantiator
@ -43,7 +44,7 @@ type Discovery struct {
// NewDiscovery returns a Discoverer function that calls a refresh() function at every interval.
func NewDiscovery(opts Options) *Discovery {
m := opts.MetricsInstantiator.Instantiate(opts.Mech)
m := opts.MetricsInstantiator.Instantiate(opts.Mech, opts.SetName)
var logger *slog.Logger
if opts.Logger == nil {

View File

@ -76,6 +76,7 @@ func TestRefresh(t *testing.T) {
Options{
Logger: nil,
Mech: "test",
SetName: "test-refresh",
Interval: interval,
RefreshF: refresh,
MetricsInstantiator: metrics,

View File

@ -17,7 +17,6 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"net/http"
"os"
"strings"
@ -167,8 +166,8 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(any) error) error {
return c.HTTPClientConfig.Validate()
}
func (c SDConfig) NewDiscoverer(options discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(&c, options.Logger, options.Metrics)
func (c SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(&c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -185,8 +184,8 @@ func init() {
// the Discoverer interface.
type Discovery struct{}
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*refresh.Discovery, error) {
m, ok := metrics.(*scalewayMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*refresh.Discovery, error) {
m, ok := opts.Metrics.(*scalewayMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -198,8 +197,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
return refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "scaleway",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: r.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -87,7 +87,7 @@ func (*SDConfig) Name() string { return "stackit" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
type refresher interface {
@ -126,21 +126,22 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*refresh.Discovery, error) {
m, ok := metrics.(*stackitMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*refresh.Discovery, error) {
m, ok := opts.Metrics.(*stackitMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
r, err := newRefresher(conf, logger)
r, err := newRefresher(conf, opts.Logger)
if err != nil {
return nil, err
}
return refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "stackit",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: r.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -19,7 +19,6 @@ import (
"errors"
"fmt"
"io"
"log/slog"
"net/http"
"net/url"
"strings"
@ -82,7 +81,7 @@ func (*SDConfig) Name() string { return "triton" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return New(opts.Logger, c, opts.Metrics)
return New(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -146,8 +145,8 @@ type Discovery struct {
}
// New returns a new Discovery which periodically refreshes its targets.
func New(logger *slog.Logger, conf *SDConfig, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*tritonMetrics)
func New(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*tritonMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -173,8 +172,9 @@ func New(logger *slog.Logger, conf *SDConfig, metrics discovery.DiscovererMetric
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "triton",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -90,7 +90,11 @@ func newTritonDiscovery(c SDConfig) (*Discovery, discovery.DiscovererMetrics, er
return nil, nil, err
}
d, err := New(nil, &c, metrics)
d, err := New(&c, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "triton",
})
if err != nil {
return nil, nil, err
}

View File

@ -124,7 +124,7 @@ func (*SDConfig) Name() string { return "uyuni" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -213,8 +213,8 @@ func getEndpointInfoForSystems(
}
// NewDiscovery returns a uyuni discovery for the given configuration.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*uyuniMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*uyuniMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -238,13 +238,14 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
entitlement: conf.Entitlement,
separator: conf.Separator,
interval: time.Duration(conf.RefreshInterval),
logger: logger,
logger: opts.Logger,
}
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "uyuni",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -47,7 +47,11 @@ func testUpdateServices(respHandler http.HandlerFunc) ([]*targetgroup.Group, err
defer metrics.Unregister()
defer refreshMetrics.Unregister()
md, err := NewDiscovery(&conf, nil, metrics)
md, err := NewDiscovery(&conf, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "uyuni",
})
if err != nil {
return nil, err
}
@ -127,7 +131,11 @@ func TestUyuniSDSkipLogin(t *testing.T) {
defer metrics.Unregister()
defer refreshMetrics.Unregister()
md, err := NewDiscovery(&conf, nil, metrics)
md, err := NewDiscovery(&conf, discovery.DiscovererOptions{
Logger: nil,
Metrics: metrics,
SetName: "uyuni",
})
if err != nil {
t.Error(err)
}

View File

@ -16,7 +16,6 @@ package vultr
import (
"context"
"errors"
"log/slog"
"net"
"net/http"
"strconv"
@ -86,7 +85,7 @@ func (*SDConfig) Name() string { return "vultr" }
// NewDiscoverer returns a Discoverer for the Config.
func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(c, opts.Logger, opts.Metrics)
return NewDiscovery(c, opts)
}
// SetDirectory joins any relative file paths with dir.
@ -114,8 +113,8 @@ type Discovery struct {
}
// NewDiscovery returns a new Discovery which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.DiscovererMetrics) (*Discovery, error) {
m, ok := metrics.(*vultrMetrics)
func NewDiscovery(conf *SDConfig, opts discovery.DiscovererOptions) (*Discovery, error) {
m, ok := opts.Metrics.(*vultrMetrics)
if !ok {
return nil, errors.New("invalid discovery metrics type")
}
@ -138,8 +137,9 @@ func NewDiscovery(conf *SDConfig, logger *slog.Logger, metrics discovery.Discove
d.Discovery = refresh.NewDiscovery(
refresh.Options{
Logger: logger,
Logger: opts.Logger,
Mech: "vultr",
SetName: opts.SetName,
Interval: time.Duration(conf.RefreshInterval),
RefreshF: d.refresh,
MetricsInstantiator: m.refreshMetrics,

View File

@ -57,7 +57,11 @@ func TestVultrSDRefresh(t *testing.T) {
defer metrics.Unregister()
defer refreshMetrics.Unregister()
d, err := NewDiscovery(&cfg, promslog.NewNopLogger(), metrics)
d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
Logger: promslog.NewNopLogger(),
Metrics: metrics,
SetName: "vultr",
})
require.NoError(t, err)
endpoint, err := url.Parse(sdMock.Mock.Endpoint())
require.NoError(t, err)

View File

@ -39,8 +39,9 @@ an empty list `[]`. Target lists are unordered.
Prometheus caches target lists. If an error occurs while fetching an updated
targets list, Prometheus keeps using the current targets list. The targets list
is not saved across restart. The `prometheus_sd_http_failures_total` counter
metric tracks the number of refresh failures.
is not saved across restart. The `prometheus_sd_refresh_failures_total` counter
metric tracks the number of refresh failures and the `prometheus_sd_refresh_duration_seconds`
bucket can be used to track HTTP SD refresh attempts or performance.
The whole list of targets must be returned on every scrape. There is no support
for incremental updates. A Prometheus instance does not send its hostname and it