github.com/thanos-io/thanos@v0.32.5/pkg/discovery/memcache/provider.go (about) 1 // Copyright (c) The Thanos Authors. 2 // Licensed under the Apache License 2.0. 3 4 package memcache 5 6 import ( 7 "context" 8 "fmt" 9 "sync" 10 "time" 11 12 "github.com/go-kit/log" 13 "github.com/go-kit/log/level" 14 "github.com/prometheus/client_golang/prometheus" 15 "github.com/prometheus/client_golang/prometheus/promauto" 16 17 "github.com/thanos-io/thanos/pkg/errutil" 18 "github.com/thanos-io/thanos/pkg/extprom" 19 ) 20 21 // Provider is a stateful cache for asynchronous memcached auto-discovery resolution. It provides a way to resolve 22 // addresses and obtain them. 23 type Provider struct { 24 sync.RWMutex 25 resolver Resolver 26 clusterConfigs map[string]*clusterConfig 27 logger log.Logger 28 29 configVersion *extprom.TxGaugeVec 30 resolvedAddresses *extprom.TxGaugeVec 31 resolverFailuresCount prometheus.Counter 32 resolverLookupsCount prometheus.Counter 33 } 34 35 func NewProvider(logger log.Logger, reg prometheus.Registerer, dialTimeout time.Duration) *Provider { 36 p := &Provider{ 37 resolver: &memcachedAutoDiscovery{dialTimeout: dialTimeout}, 38 clusterConfigs: map[string]*clusterConfig{}, 39 configVersion: extprom.NewTxGaugeVec(reg, prometheus.GaugeOpts{ 40 Name: "auto_discovery_config_version", 41 Help: "The current auto discovery config version", 42 }, []string{"addr"}), 43 resolvedAddresses: extprom.NewTxGaugeVec(reg, prometheus.GaugeOpts{ 44 Name: "auto_discovery_resolved_addresses", 45 Help: "The number of memcached nodes found via auto discovery", 46 }, []string{"addr"}), 47 resolverLookupsCount: promauto.With(reg).NewCounter(prometheus.CounterOpts{ 48 Name: "auto_discovery_total", 49 Help: "The number of memcache auto discovery attempts", 50 }), 51 resolverFailuresCount: promauto.With(reg).NewCounter(prometheus.CounterOpts{ 52 Name: "auto_discovery_failures_total", 53 Help: "The number of memcache auto discovery failures", 54 }), 55 logger: logger, 56 } 57 return p 58 } 59 60 // Resolve stores a list of nodes auto-discovered from the provided addresses. 61 func (p *Provider) Resolve(ctx context.Context, addresses []string) error { 62 clusterConfigs := map[string]*clusterConfig{} 63 errs := errutil.MultiError{} 64 65 for _, address := range addresses { 66 clusterConfig, err := p.resolver.Resolve(ctx, address) 67 p.resolverLookupsCount.Inc() 68 69 if err != nil { 70 level.Warn(p.logger).Log( 71 "msg", "failed to perform auto-discovery for memcached", 72 "address", address, 73 ) 74 errs.Add(err) 75 p.resolverFailuresCount.Inc() 76 77 // Use cached values. 78 p.RLock() 79 clusterConfigs[address] = p.clusterConfigs[address] 80 p.RUnlock() 81 } else { 82 clusterConfigs[address] = clusterConfig 83 } 84 } 85 86 p.Lock() 87 defer p.Unlock() 88 89 p.resolvedAddresses.ResetTx() 90 p.configVersion.ResetTx() 91 for address, config := range clusterConfigs { 92 p.resolvedAddresses.WithLabelValues(address).Set(float64(len(config.nodes))) 93 p.configVersion.WithLabelValues(address).Set(float64(config.version)) 94 } 95 p.resolvedAddresses.Submit() 96 p.configVersion.Submit() 97 98 p.clusterConfigs = clusterConfigs 99 100 return errs.Err() 101 } 102 103 // Addresses returns the latest addresses present in the Provider. 104 func (p *Provider) Addresses() []string { 105 p.RLock() 106 defer p.RUnlock() 107 108 var result []string 109 for _, config := range p.clusterConfigs { 110 for _, node := range config.nodes { 111 result = append(result, fmt.Sprintf("%s:%d", node.dns, node.port)) 112 } 113 } 114 return result 115 }