2015-01-21 11:07:45 -08:00
|
|
|
// Copyright 2013 The Prometheus Authors
|
2013-01-04 05:41:47 -08:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package retrieval
|
|
|
|
|
|
|
|
import (
|
2015-04-20 03:24:25 -07:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
2014-11-11 15:38:28 -08:00
|
|
|
"sync"
|
2014-12-26 04:37:30 -08:00
|
|
|
|
2015-10-03 01:21:43 -07:00
|
|
|
"github.com/prometheus/common/log"
|
2015-08-20 08:18:46 -07:00
|
|
|
"github.com/prometheus/common/model"
|
2016-02-17 10:33:17 -08:00
|
|
|
"golang.org/x/net/context"
|
2013-06-25 05:02:27 -07:00
|
|
|
|
|
|
|
"github.com/prometheus/prometheus/config"
|
2015-04-20 03:24:25 -07:00
|
|
|
"github.com/prometheus/prometheus/retrieval/discovery"
|
2015-03-14 19:36:15 -07:00
|
|
|
"github.com/prometheus/prometheus/storage"
|
2013-01-04 05:41:47 -08:00
|
|
|
)
|
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
// A TargetProvider provides information about target groups. It maintains a set
|
|
|
|
// of sources from which TargetGroups can originate. Whenever a target provider
|
2015-04-25 03:59:05 -07:00
|
|
|
// detects a potential change, it sends the TargetGroup through its provided channel.
|
2015-04-20 03:24:25 -07:00
|
|
|
//
|
|
|
|
// The TargetProvider does not have to guarantee that an actual change happened.
|
|
|
|
// It does guarantee that it sends the new TargetGroup whenever a change happens.
|
2015-08-13 11:38:25 -07:00
|
|
|
//
|
2016-02-17 10:33:17 -08:00
|
|
|
// Providers must initially send all known target groups as soon as it can.
|
2015-04-20 03:24:25 -07:00
|
|
|
type TargetProvider interface {
|
|
|
|
// Run hands a channel to the target provider through which it can send
|
|
|
|
// updated target groups. The channel must be closed by the target provider
|
|
|
|
// if no more updates will be sent.
|
2015-08-10 07:44:32 -07:00
|
|
|
// On receiving from done Run must return.
|
2016-02-18 08:26:27 -08:00
|
|
|
Run(ctx context.Context, up chan<- []*config.TargetGroup)
|
2013-01-04 05:41:47 -08:00
|
|
|
}
|
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
// TargetManager maintains a set of targets, starts and stops their scraping and
|
|
|
|
// creates the new targets based on the target groups it receives from various
|
|
|
|
// target providers.
|
|
|
|
type TargetManager struct {
|
2016-02-17 10:33:17 -08:00
|
|
|
appender storage.SampleAppender
|
|
|
|
|
|
|
|
mtx sync.RWMutex
|
|
|
|
ctx context.Context
|
|
|
|
cancel func()
|
|
|
|
wg sync.WaitGroup
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2015-04-25 03:59:05 -07:00
|
|
|
// Providers by the scrape configs they are derived from.
|
2016-02-17 10:33:17 -08:00
|
|
|
scrapeSets []*scrapeSet
|
2013-01-04 05:41:47 -08:00
|
|
|
}
|
|
|
|
|
2015-05-12 07:52:56 -07:00
|
|
|
// NewTargetManager creates a new TargetManager.
|
2016-02-17 10:33:17 -08:00
|
|
|
func NewTargetManager(app storage.SampleAppender) *TargetManager {
|
|
|
|
return &TargetManager{
|
|
|
|
appender: app,
|
2015-08-10 07:44:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
// Run starts background processing to handle target updates.
|
|
|
|
func (tm *TargetManager) Run() {
|
2015-05-20 09:10:29 -07:00
|
|
|
log.Info("Starting target manager...")
|
2013-01-04 05:41:47 -08:00
|
|
|
|
2015-08-10 07:44:32 -07:00
|
|
|
tm.mtx.Lock()
|
2016-02-17 10:33:17 -08:00
|
|
|
tm.ctx, tm.cancel = context.WithCancel(context.Background())
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
for _, ss := range tm.scrapeSets {
|
|
|
|
tm.wg.Add(1)
|
2014-12-03 09:07:23 -08:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
go func(ss *scrapeSet) {
|
|
|
|
ss.run(tm.ctx)
|
|
|
|
tm.wg.Done()
|
|
|
|
}(ss)
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
2016-02-17 10:33:17 -08:00
|
|
|
|
|
|
|
tm.mtx.Unlock()
|
|
|
|
tm.wg.Wait()
|
2013-02-22 12:07:35 -08:00
|
|
|
}
|
2013-01-04 05:41:47 -08:00
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
// Stop all background processing.
|
|
|
|
func (tm *TargetManager) Stop() {
|
2016-02-17 10:33:17 -08:00
|
|
|
log.Infoln("Stopping target manager...")
|
2015-05-27 03:32:39 -07:00
|
|
|
|
2015-08-10 07:44:32 -07:00
|
|
|
tm.mtx.Lock()
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
// Cancel the base context, this will cause all in-flight scrapes to abort immmediately.
|
|
|
|
// Started inserts will be finished before terminating.
|
|
|
|
tm.cancel()
|
|
|
|
tm.mtx.Unlock()
|
2013-01-07 14:24:26 -08:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
// Wait for all provider sets to terminate.
|
|
|
|
tm.wg.Wait()
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Pools returns the targets currently being scraped bucketed by their job name.
|
2015-05-18 04:14:41 -07:00
|
|
|
func (tm *TargetManager) Pools() map[string][]*Target {
|
2015-08-10 07:44:32 -07:00
|
|
|
tm.mtx.RLock()
|
|
|
|
defer tm.mtx.RUnlock()
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2015-05-18 04:14:41 -07:00
|
|
|
pools := map[string][]*Target{}
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
// TODO(fabxc): this is just a hack to maintain compatibility for now.
|
|
|
|
for _, ps := range tm.scrapeSets {
|
|
|
|
for _, ts := range ps.tgroups {
|
|
|
|
for _, t := range ts {
|
|
|
|
job := string(t.Labels()[model.JobLabel])
|
|
|
|
pools[job] = append(pools[job], t)
|
|
|
|
}
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return pools
|
|
|
|
}
|
|
|
|
|
|
|
|
// ApplyConfig resets the manager's target providers and job configurations as defined
|
|
|
|
// by the new cfg. The state of targets that are valid in the new configuration remains unchanged.
|
2015-06-02 09:44:41 -07:00
|
|
|
// Returns true on success.
|
|
|
|
func (tm *TargetManager) ApplyConfig(cfg *config.Config) bool {
|
2015-08-10 07:44:32 -07:00
|
|
|
tm.mtx.RLock()
|
2016-02-17 10:33:17 -08:00
|
|
|
running := tm.ctx != nil
|
2015-08-10 07:44:32 -07:00
|
|
|
tm.mtx.RUnlock()
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2015-05-27 03:32:39 -07:00
|
|
|
if running {
|
2016-02-17 10:33:17 -08:00
|
|
|
tm.Stop()
|
|
|
|
defer func() {
|
|
|
|
go tm.Run()
|
|
|
|
}()
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
2016-02-17 10:33:17 -08:00
|
|
|
|
|
|
|
tm.mtx.Lock()
|
|
|
|
|
|
|
|
tm.scrapeSets = tm.scrapeSets[:0]
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2015-05-07 01:55:03 -07:00
|
|
|
for _, scfg := range cfg.ScrapeConfigs {
|
2016-02-17 10:33:17 -08:00
|
|
|
tm.scrapeSets = append(tm.scrapeSets, newScrapeSet(tm.appender, scfg))
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
tm.mtx.Unlock()
|
2015-05-27 03:32:39 -07:00
|
|
|
|
2015-06-02 09:44:41 -07:00
|
|
|
return true
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
// scrapeSet holds several TargetProviders for which the same scrape configuration
|
|
|
|
// is used. It runs the target providers and starts and stops scrapers as it
|
|
|
|
// receives target updates.
|
|
|
|
type scrapeSet struct {
|
|
|
|
appender storage.SampleAppender
|
2015-08-07 04:18:19 -07:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
config *config.ScrapeConfig
|
|
|
|
tgroups map[string]map[model.Fingerprint]*Target
|
|
|
|
|
|
|
|
mtx sync.RWMutex
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
func newScrapeSet(app storage.SampleAppender, cfg *config.ScrapeConfig) *scrapeSet {
|
|
|
|
return &scrapeSet{
|
|
|
|
appender: app,
|
|
|
|
config: cfg,
|
|
|
|
tgroups: map[string]map[model.Fingerprint]*Target{},
|
|
|
|
}
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
// run starts the target providers with the given context and consumes
|
|
|
|
// and handles their updates. If the context is done, it blocks until the
|
|
|
|
// target scrapers have terminated.
|
|
|
|
func (ss *scrapeSet) run(ctx context.Context) {
|
|
|
|
var (
|
|
|
|
providers = providersFromConfig(ss.config)
|
|
|
|
wg sync.WaitGroup
|
|
|
|
)
|
|
|
|
|
|
|
|
for name, prov := range providers {
|
|
|
|
var (
|
2016-02-18 08:26:27 -08:00
|
|
|
updates = make(chan []*config.TargetGroup)
|
2016-02-17 10:33:17 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
// The update and stopping operations for the target provider handling are blocking.
|
|
|
|
// Thus the run method only returns if all background processing is complete.
|
|
|
|
go func(name string, prov TargetProvider) {
|
|
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
ss.stopScrapers(name)
|
|
|
|
return
|
2016-02-18 08:26:27 -08:00
|
|
|
case tgs := <-updates:
|
|
|
|
for _, tg := range tgs {
|
|
|
|
if err := ss.update(name, tg); err != nil {
|
|
|
|
log.With("target_group", tg).Errorf("Target update failed: %s", err)
|
|
|
|
}
|
2016-02-17 10:33:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}(name, prov)
|
|
|
|
|
2016-02-18 08:26:27 -08:00
|
|
|
go prov.Run(ctx, updates)
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
wg.Wait()
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
// stopScrapers shuts down all active scrapers for a provider.
|
|
|
|
func (ss *scrapeSet) stopScrapers(name string) {
|
|
|
|
var wg sync.WaitGroup
|
2015-08-07 04:18:19 -07:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
ss.mtx.RLock()
|
|
|
|
// TODO(fabxc): the prefixing is slightly hacky but this will be gone with subsequent changes.
|
|
|
|
for source, tgroup := range ss.tgroups {
|
|
|
|
if !strings.HasPrefix(source, name) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, t := range tgroup {
|
|
|
|
wg.Add(1)
|
2015-08-10 07:44:32 -07:00
|
|
|
|
2016-02-17 10:33:17 -08:00
|
|
|
go func(t *Target) {
|
|
|
|
t.StopScraper()
|
|
|
|
wg.Done()
|
|
|
|
}(t)
|
2015-08-10 07:44:32 -07:00
|
|
|
}
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
2016-02-17 10:33:17 -08:00
|
|
|
ss.mtx.RUnlock()
|
|
|
|
|
|
|
|
wg.Wait()
|
|
|
|
}
|
|
|
|
|
|
|
|
// update handles a target group update from a target provider identified by the name.
|
|
|
|
func (ss *scrapeSet) update(name string, tgroup *config.TargetGroup) error {
|
|
|
|
var (
|
|
|
|
source = name + "/" + tgroup.Source
|
|
|
|
prevTargets = ss.tgroups[source]
|
|
|
|
)
|
|
|
|
|
|
|
|
targets, err := targetsFromGroup(tgroup, ss.config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
ss.mtx.Lock()
|
|
|
|
ss.tgroups[source] = targets
|
|
|
|
|
|
|
|
for fp, tnew := range targets {
|
|
|
|
// If the same target existed before, we let it run and replace
|
|
|
|
// the new one with it.
|
|
|
|
if told, ok := prevTargets[fp]; ok {
|
|
|
|
targets[fp] = told
|
|
|
|
} else {
|
|
|
|
go tnew.RunScraper(ss.appender)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ss.mtx.Unlock()
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
for fp, told := range prevTargets {
|
|
|
|
// A previous target is no longer in the group.
|
|
|
|
if _, ok := targets[fp]; !ok {
|
|
|
|
wg.Add(1)
|
|
|
|
|
|
|
|
go func(told *Target) {
|
|
|
|
told.StopScraper()
|
|
|
|
wg.Done()
|
|
|
|
}(told)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Wait for all potentially stopped scrapers to terminate.
|
|
|
|
// This covers the case of flapping targets. If the server is under high load, a new scraper
|
|
|
|
// may be active and tries to insert. The old scraper that didn't terminate yet could still
|
|
|
|
// be inserting a previous sample set.
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
return nil
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// providersFromConfig returns all TargetProviders configured in cfg.
|
2016-02-17 10:33:17 -08:00
|
|
|
func providersFromConfig(cfg *config.ScrapeConfig) map[string]TargetProvider {
|
|
|
|
providers := map[string]TargetProvider{}
|
2015-08-07 04:18:19 -07:00
|
|
|
|
|
|
|
app := func(mech string, i int, tp TargetProvider) {
|
2016-02-17 10:33:17 -08:00
|
|
|
providers[fmt.Sprintf("%s/%d", mech, i)] = tp
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, c := range cfg.DNSSDConfigs {
|
|
|
|
app("dns", i, discovery.NewDNSDiscovery(c))
|
|
|
|
}
|
|
|
|
for i, c := range cfg.FileSDConfigs {
|
|
|
|
app("file", i, discovery.NewFileDiscovery(c))
|
|
|
|
}
|
|
|
|
for i, c := range cfg.ConsulSDConfigs {
|
2015-11-30 09:41:48 -08:00
|
|
|
k, err := discovery.NewConsulDiscovery(c)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Cannot create Consul discovery: %s", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
app("consul", i, k)
|
2015-08-07 04:18:19 -07:00
|
|
|
}
|
|
|
|
for i, c := range cfg.MarathonSDConfigs {
|
|
|
|
app("marathon", i, discovery.NewMarathonDiscovery(c))
|
|
|
|
}
|
2015-07-18 14:23:58 -07:00
|
|
|
for i, c := range cfg.KubernetesSDConfigs {
|
|
|
|
k, err := discovery.NewKubernetesDiscovery(c)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Cannot create Kubernetes discovery: %s", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
app("kubernetes", i, k)
|
|
|
|
}
|
2015-08-07 04:18:19 -07:00
|
|
|
for i, c := range cfg.ServersetSDConfigs {
|
|
|
|
app("serverset", i, discovery.NewServersetDiscovery(c))
|
|
|
|
}
|
2016-01-09 15:34:32 -08:00
|
|
|
for i, c := range cfg.NerveSDConfigs {
|
|
|
|
app("nerve", i, discovery.NewNerveDiscovery(c))
|
|
|
|
}
|
2015-09-21 11:49:19 -07:00
|
|
|
for i, c := range cfg.EC2SDConfigs {
|
|
|
|
app("ec2", i, discovery.NewEC2Discovery(c))
|
|
|
|
}
|
2015-08-07 04:18:19 -07:00
|
|
|
if len(cfg.TargetGroups) > 0 {
|
|
|
|
app("static", 0, NewStaticProvider(cfg.TargetGroups))
|
|
|
|
}
|
|
|
|
|
|
|
|
return providers
|
|
|
|
}
|
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
// targetsFromGroup builds targets based on the given TargetGroup and config.
|
2016-02-17 10:33:17 -08:00
|
|
|
func targetsFromGroup(tg *config.TargetGroup, cfg *config.ScrapeConfig) (map[model.Fingerprint]*Target, error) {
|
|
|
|
targets := make(map[model.Fingerprint]*Target, len(tg.Targets))
|
2015-04-20 03:24:25 -07:00
|
|
|
for i, labels := range tg.Targets {
|
2015-07-05 12:25:45 -07:00
|
|
|
for k, v := range cfg.Params {
|
|
|
|
if len(v) > 0 {
|
2015-08-20 08:18:46 -07:00
|
|
|
labels[model.LabelName(model.ParamLabelPrefix+k)] = model.LabelValue(v[0])
|
2015-07-05 12:25:45 -07:00
|
|
|
}
|
|
|
|
}
|
2015-04-25 03:59:05 -07:00
|
|
|
// Copy labels into the labelset for the target if they are not
|
|
|
|
// set already. Apply the labelsets in order of decreasing precedence.
|
2015-08-20 08:18:46 -07:00
|
|
|
labelsets := []model.LabelSet{
|
2015-04-25 03:59:05 -07:00
|
|
|
tg.Labels,
|
2015-05-24 11:48:56 -07:00
|
|
|
{
|
2015-08-20 08:18:46 -07:00
|
|
|
model.SchemeLabel: model.LabelValue(cfg.Scheme),
|
|
|
|
model.MetricsPathLabel: model.LabelValue(cfg.MetricsPath),
|
|
|
|
model.JobLabel: model.LabelValue(cfg.JobName),
|
2015-05-07 01:55:03 -07:00
|
|
|
},
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
2015-04-25 03:59:05 -07:00
|
|
|
for _, lset := range labelsets {
|
|
|
|
for ln, lv := range lset {
|
|
|
|
if _, ok := labels[ln]; !ok {
|
|
|
|
labels[ln] = lv
|
|
|
|
}
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
2015-04-25 03:59:05 -07:00
|
|
|
|
2015-08-20 08:18:46 -07:00
|
|
|
if _, ok := labels[model.AddressLabel]; !ok {
|
2015-04-28 15:08:58 -07:00
|
|
|
return nil, fmt.Errorf("instance %d in target group %s has no address", i, tg)
|
|
|
|
}
|
|
|
|
|
2015-06-05 13:42:39 -07:00
|
|
|
preRelabelLabels := labels
|
|
|
|
|
2015-05-07 01:55:03 -07:00
|
|
|
labels, err := Relabel(labels, cfg.RelabelConfigs...)
|
2015-04-28 15:08:58 -07:00
|
|
|
if err != nil {
|
2015-05-12 07:52:56 -07:00
|
|
|
return nil, fmt.Errorf("error while relabeling instance %d in target group %s: %s", i, tg, err)
|
2015-04-28 15:08:58 -07:00
|
|
|
}
|
|
|
|
// Check if the target was dropped.
|
|
|
|
if labels == nil {
|
|
|
|
continue
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
2015-11-08 03:42:18 -08:00
|
|
|
// If no port was provided, infer it based on the used scheme.
|
|
|
|
addr := string(labels[model.AddressLabel])
|
|
|
|
if !strings.Contains(addr, ":") {
|
|
|
|
switch labels[model.SchemeLabel] {
|
|
|
|
case "http", "":
|
|
|
|
addr = fmt.Sprintf("%s:80", addr)
|
|
|
|
case "https":
|
|
|
|
addr = fmt.Sprintf("%s:443", addr)
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("targetsFromGroup: invalid scheme %q", cfg.Scheme))
|
|
|
|
}
|
|
|
|
labels[model.AddressLabel] = model.LabelValue(addr)
|
|
|
|
}
|
2015-11-07 06:25:51 -08:00
|
|
|
if err = config.CheckTargetAddress(labels[model.AddressLabel]); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2013-01-07 14:24:26 -08:00
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
for ln := range labels {
|
2015-04-25 03:59:05 -07:00
|
|
|
// Meta labels are deleted after relabelling. Other internal labels propagate to
|
|
|
|
// the target which decides whether they will be part of their label set.
|
2015-08-20 08:18:46 -07:00
|
|
|
if strings.HasPrefix(string(ln), model.MetaLabelPrefix) {
|
2015-04-20 03:24:25 -07:00
|
|
|
delete(labels, ln)
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
}
|
2016-02-08 12:26:00 -08:00
|
|
|
tr, err := NewTarget(cfg, labels, preRelabelLabels)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error while creating instance %d in target group %s: %s", i, tg, err)
|
|
|
|
}
|
2016-02-17 10:33:17 -08:00
|
|
|
|
|
|
|
targets[tr.fingerprint()] = tr
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
2015-04-25 03:59:05 -07:00
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
return targets, nil
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
2013-02-22 12:07:35 -08:00
|
|
|
|
2015-04-20 03:24:25 -07:00
|
|
|
// StaticProvider holds a list of target groups that never change.
|
|
|
|
type StaticProvider struct {
|
|
|
|
TargetGroups []*config.TargetGroup
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewStaticProvider returns a StaticProvider configured with the given
|
|
|
|
// target groups.
|
2015-05-07 01:55:03 -07:00
|
|
|
func NewStaticProvider(groups []*config.TargetGroup) *StaticProvider {
|
2015-04-20 03:24:25 -07:00
|
|
|
for i, tg := range groups {
|
2015-08-07 04:18:19 -07:00
|
|
|
tg.Source = fmt.Sprintf("%d", i)
|
2015-05-07 01:55:03 -07:00
|
|
|
}
|
2016-02-18 08:26:27 -08:00
|
|
|
return &StaticProvider{groups}
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Run implements the TargetProvider interface.
|
2016-02-18 08:26:27 -08:00
|
|
|
func (sd *StaticProvider) Run(ctx context.Context, ch chan<- []*config.TargetGroup) {
|
|
|
|
// We still have to consider that the consumer exits right away in which case
|
|
|
|
// the context will be canceled.
|
|
|
|
select {
|
|
|
|
case ch <- sd.TargetGroups:
|
|
|
|
case <-ctx.Done():
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
2016-02-18 08:26:27 -08:00
|
|
|
close(ch)
|
2013-12-11 06:30:27 -08:00
|
|
|
}
|