Gate agent behind a feature flag, valide mode flags (#9620)

Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
This commit is contained in:
Julien Pivotto 2021-11-02 14:03:35 +01:00 committed by GitHub
parent 6e1d6edb33
commit 807f46a1ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 93 additions and 9 deletions

View file

@ -132,7 +132,7 @@ func extractFlagName(pc *kingpin.ParseContext) string {
if !ok {
continue
}
return fc.Model().Name
return "--" + fc.Model().Name
}
panic("extractFlagName not called from a kingpin PreAction. This is a bug, please report to Prometheus.")
}
@ -200,6 +200,9 @@ func (c *flagConfig) setFeatureListOptions(logger log.Logger) error {
case "new-service-discovery-manager":
c.enableNewSDManager = true
level.Info(logger).Log("msg", "Experimental service discovery manager")
case "agent":
agentMode = true
level.Info(logger).Log("msg", "Experimental agent mode enabled.")
case "":
continue
default:
@ -238,8 +241,6 @@ func main() {
a.HelpFlag.Short('h')
a.Flag("agent", "Agent mode.").BoolVar(&agentMode)
a.Flag("config.file", "Prometheus configuration file path.").
Default("prometheus.yml").StringVar(&cfg.configFile)
@ -335,16 +336,16 @@ func main() {
PreAction(agentOnlySetting()).
Default("data-agent/").StringVar(&cfg.localStoragePath)
a.Flag("storage.agent.segment-size",
a.Flag("storage.agent.wal-segment-size",
"Size at which to split WAL segment files. Example: 100MB").
PreAction(agentOnlySetting()).
Hidden().PlaceHolder("<bytes>").BytesVar(&cfg.agent.WALSegmentSize)
a.Flag("storage.agent.compression", "Compress the agent WAL.").
a.Flag("storage.agent.wal-compression", "Compress the agent WAL.").
PreAction(agentOnlySetting()).
Default("true").BoolVar(&cfg.agent.WALCompression)
a.Flag("storage.agent.truncate-frequency",
a.Flag("storage.agent.wal-truncate-frequency",
"The frequency at which to truncate the WAL and remove old data.").
PreAction(agentOnlySetting()).
Hidden().PlaceHolder("<duration>").SetValue(&cfg.agent.TruncateFrequency)
@ -434,6 +435,16 @@ func main() {
os.Exit(1)
}
if agentMode && len(serverOnlyFlags) > 0 {
fmt.Fprintf(os.Stderr, "The following flag(s) can not be used in agent mode: %q", serverOnlyFlags)
os.Exit(3)
}
if !agentMode && len(agentOnlyFlags) > 0 {
fmt.Fprintf(os.Stderr, "The following flag(s) can only be used in agent mode: %q", agentOnlyFlags)
os.Exit(3)
}
cfg.web.ExternalURL, err = computeExternalURL(cfg.prometheusURL, cfg.web.ListenAddress)
if err != nil {
fmt.Fprintln(os.Stderr, errors.Wrapf(err, "parse external URL %q", cfg.prometheusURL))
@ -1006,7 +1017,7 @@ func main() {
level.Info(logger).Log("msg", "Starting WAL storage ...")
if cfg.agent.WALSegmentSize != 0 {
if cfg.agent.WALSegmentSize < 10*1024*1024 || cfg.agent.WALSegmentSize > 256*1024*1024 {
return errors.New("flag 'storage.agent.segment-size' must be set between 10MB and 256MB")
return errors.New("flag 'storage.agent.wal-segment-size' must be set between 10MB and 256MB")
}
}
db, err := agent.Open(

View file

@ -350,7 +350,7 @@ func getCurrentGaugeValuesFor(t *testing.T, reg prometheus.Gatherer, metricNames
}
func TestAgentSuccessfulStartup(t *testing.T) {
prom := exec.Command(promPath, "-test.main", "--agent", "--config.file="+agentConfig)
prom := exec.Command(promPath, "-test.main", "--enable-feature=agent", "--config.file="+agentConfig)
err := prom.Start()
require.NoError(t, err)
@ -370,7 +370,7 @@ func TestAgentSuccessfulStartup(t *testing.T) {
}
func TestAgentStartupWithInvalidConfig(t *testing.T) {
prom := exec.Command(promPath, "-test.main", "--agent", "--config.file="+promConfig)
prom := exec.Command(promPath, "-test.main", "--enable-feature=agent", "--config.file="+promConfig)
err := prom.Start()
require.NoError(t, err)
@ -388,3 +388,66 @@ func TestAgentStartupWithInvalidConfig(t *testing.T) {
}
require.Equal(t, expectedExitStatus, actualExitStatus)
}
func TestModeSpecificFlags(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
testcases := []struct {
mode string
arg string
exitStatus int
}{
{"agent", "--storage.agent.path", 0},
{"server", "--storage.tsdb.path", 0},
{"server", "--storage.agent.path", 3},
{"agent", "--storage.tsdb.path", 3},
}
for _, tc := range testcases {
t.Run(fmt.Sprintf("%s mode with option %s", tc.mode, tc.arg), func(t *testing.T) {
args := []string{"-test.main", tc.arg, t.TempDir()}
if tc.mode == "agent" {
args = append(args, "--enable-feature=agent", "--config.file="+agentConfig)
} else {
args = append(args, "--config.file="+promConfig)
}
prom := exec.Command(promPath, args...)
// Log stderr in case of failure.
stderr, err := prom.StderrPipe()
require.NoError(t, err)
go func() {
slurp, _ := ioutil.ReadAll(stderr)
t.Log(string(slurp))
}()
err = prom.Start()
require.NoError(t, err)
if tc.exitStatus == 0 {
done := make(chan error, 1)
go func() { done <- prom.Wait() }()
select {
case err := <-done:
t.Errorf("prometheus should be still running: %v", err)
case <-time.After(5 * time.Second):
prom.Process.Kill()
}
return
}
err = prom.Wait()
require.Error(t, err)
if exitError, ok := err.(*exec.ExitError); ok {
status := exitError.Sys().(syscall.WaitStatus)
require.Equal(t, tc.exitStatus, status.ExitStatus())
} else {
t.Errorf("unable to retrieve the exit status for prometheus: %v", err)
}
})
}
}

View file

@ -86,3 +86,13 @@ issues upstream.
In future releases, this new service discovery manager will become the default and
this feature flag will be ignored.
## Prometheus agent
`--enable-feature=agent`
When enabled, Prometheus runs in agent mode. The agent mode is limited to
discovery, scrape and remote write.
This is useful when you do not need to query the Prometheus data locally, but
only from a central [remote endpoint](https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage).