mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/promscrape: add -promscrape.configCheckInterval
command-line flag for automating config checking
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/431
This commit is contained in:
parent
83e4c8427e
commit
387a21c96d
3 changed files with 40 additions and 10 deletions
|
@ -97,16 +97,16 @@ func loadStaticConfigs(path string) ([]StaticConfig, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadConfig loads Prometheus config from the given path.
|
// loadConfig loads Prometheus config from the given path.
|
||||||
func loadConfig(path string) (cfg *Config, err error) {
|
func loadConfig(path string) (cfg *Config, data []byte, err error) {
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err = ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot read Prometheus config from %q: %s", path, err)
|
return nil, nil, fmt.Errorf("cannot read Prometheus config from %q: %s", path, err)
|
||||||
}
|
}
|
||||||
var cfgObj Config
|
var cfgObj Config
|
||||||
if err := cfgObj.parse(data, path); err != nil {
|
if err := cfgObj.parse(data, path); err != nil {
|
||||||
return nil, fmt.Errorf("cannot parse Prometheus config from %q: %s", path, err)
|
return nil, nil, fmt.Errorf("cannot parse Prometheus config from %q: %s", path, err)
|
||||||
}
|
}
|
||||||
return &cfgObj, nil
|
return &cfgObj, data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Config) parse(data []byte, path string) error {
|
func (cfg *Config) parse(data []byte, path string) error {
|
||||||
|
|
|
@ -42,7 +42,7 @@ func TestLoadStaticConfigs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadConfig(t *testing.T) {
|
func TestLoadConfig(t *testing.T) {
|
||||||
cfg, err := loadConfig("testdata/prometheus.yml")
|
cfg, _, err := loadConfig("testdata/prometheus.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %s", err)
|
t.Fatalf("unexpected error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ func TestLoadConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try loading non-existing file
|
// Try loading non-existing file
|
||||||
cfg, err = loadConfig("testdata/non-existing-file")
|
cfg, _, err = loadConfig("testdata/non-existing-file")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expecting non-nil error")
|
t.Fatalf("expecting non-nil error")
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ func TestLoadConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try loading invalid file
|
// Try loading invalid file
|
||||||
cfg, err = loadConfig("testdata/file_sd_1.yml")
|
cfg, _, err = loadConfig("testdata/file_sd_1.yml")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expecting non-nil error")
|
t.Fatalf("expecting non-nil error")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package promscrape
|
package promscrape
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -14,6 +15,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
configCheckInterval = flag.Duration("promscrape.configCheckInterval", 0, "Interval for checking for changes in '-promscrape.config' file. "+
|
||||||
|
"By default the checking is disabled. Send SIGHUP signal in order to force config check for changes")
|
||||||
fileSDCheckInterval = flag.Duration("promscrape.fileSDCheckInterval", 30*time.Second, "Interval for checking for changes in 'file_sd_config'. "+
|
fileSDCheckInterval = flag.Duration("promscrape.fileSDCheckInterval", 30*time.Second, "Interval for checking for changes in 'file_sd_config'. "+
|
||||||
"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config")
|
"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config")
|
||||||
kubernetesSDCheckInterval = flag.Duration("promscrape.kubernetesSDCheckInterval", 30*time.Second, "Interval for checking for changes in Kubernetes API server. "+
|
kubernetesSDCheckInterval = flag.Duration("promscrape.kubernetesSDCheckInterval", 30*time.Second, "Interval for checking for changes in Kubernetes API server. "+
|
||||||
|
@ -55,11 +58,18 @@ func runScraper(configFile string, pushData func(wr *prompbmarshal.WriteRequest)
|
||||||
signal.Notify(sighupCh, syscall.SIGHUP)
|
signal.Notify(sighupCh, syscall.SIGHUP)
|
||||||
|
|
||||||
logger.Infof("reading Prometheus configs from %q", configFile)
|
logger.Infof("reading Prometheus configs from %q", configFile)
|
||||||
cfg, err := loadConfig(configFile)
|
cfg, data, err := loadConfig(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("cannot read %q: %s", configFile, err)
|
logger.Fatalf("cannot read %q: %s", configFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tickerCh <-chan time.Time
|
||||||
|
if *configCheckInterval > 0 {
|
||||||
|
ticker := time.NewTicker(*configCheckInterval)
|
||||||
|
tickerCh = ticker.C
|
||||||
|
defer ticker.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
mustStop := false
|
mustStop := false
|
||||||
for !mustStop {
|
for !mustStop {
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
|
@ -84,16 +94,36 @@ func runScraper(configFile string, pushData func(wr *prompbmarshal.WriteRequest)
|
||||||
select {
|
select {
|
||||||
case <-sighupCh:
|
case <-sighupCh:
|
||||||
logger.Infof("SIGHUP received; reloading Prometheus configs from %q", configFile)
|
logger.Infof("SIGHUP received; reloading Prometheus configs from %q", configFile)
|
||||||
cfgNew, err := loadConfig(configFile)
|
cfgNew, dataNew, err := loadConfig(configFile)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("cannot read %q on SIGHUP: %s; continuing with the previous config", configFile, err)
|
||||||
|
goto waitForChans
|
||||||
|
}
|
||||||
|
if bytes.Equal(data, dataNew) {
|
||||||
|
logger.Infof("nothing changed in %q", configFile)
|
||||||
|
goto waitForChans
|
||||||
|
}
|
||||||
|
cfg = cfgNew
|
||||||
|
data = dataNew
|
||||||
|
case <-tickerCh:
|
||||||
|
cfgNew, dataNew, err := loadConfig(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("cannot read %q: %s; continuing with the previous config", configFile, err)
|
logger.Errorf("cannot read %q: %s; continuing with the previous config", configFile, err)
|
||||||
goto waitForChans
|
goto waitForChans
|
||||||
}
|
}
|
||||||
|
if bytes.Equal(data, dataNew) {
|
||||||
|
// Nothing changed since the previous loadConfig
|
||||||
|
goto waitForChans
|
||||||
|
}
|
||||||
cfg = cfgNew
|
cfg = cfgNew
|
||||||
|
data = dataNew
|
||||||
case <-globalStopCh:
|
case <-globalStopCh:
|
||||||
mustStop = true
|
mustStop = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !mustStop {
|
||||||
|
logger.Infof("found changes in %q; applying these changes", configFile)
|
||||||
|
}
|
||||||
logger.Infof("stopping Prometheus scrapers")
|
logger.Infof("stopping Prometheus scrapers")
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
close(stopCh)
|
close(stopCh)
|
||||||
|
|
Loading…
Reference in a new issue