diff --git a/cmd/prometheus/main.go b/cmd/prometheus/main.go index a611fe3232..7a94b2623e 100644 --- a/cmd/prometheus/main.go +++ b/cmd/prometheus/main.go @@ -278,7 +278,14 @@ func main() { } cfg.web.Flags = map[string]string{} + + // Exclude kingpin default flags to expose only Prometheus ones. + boilerplateFlags := kingpin.New("", "").Version("") for _, f := range a.Model().Flags { + if boilerplateFlags.GetFlag(f.Name) != nil { + continue + } + cfg.web.Flags[f.Name] = f.Value.String() } diff --git a/docs/querying/api.md b/docs/querying/api.md index f885b110b4..502658f378 100644 --- a/docs/querying/api.md +++ b/docs/querying/api.md @@ -382,6 +382,57 @@ $ curl http://localhost:9090/api/v1/alertmanagers } ``` +## Status + +Following status endpoints expose current Prometheus configuration. + +### Config + +The following endpoint returns currently loaded configuration file: + +``` +GET /api/v1/status/config +``` + +The config is returned as dumped YAML file. Due to limitation of the YAML +library, YAML comments are not included. + +```json +$ curl http://localhost:9090/api/v1/status/config +{ + "status": "success", + "data": { + "yaml": "", + } +} +``` + +### Flags + +The following endpoint returns flag values that Prometheus was configured with: + +``` +GET /api/v1/status/flags +``` + +All values are in a form of "string". + +```json +$ curl http://localhost:9090/api/v1/status/flags +{ + "status": "success", + "data": { + "alertmanager.notification-queue-capacity": "10000", + "alertmanager.timeout": "10s", + "log.level": "info", + "query.lookback-delta": "5m", + "query.max-concurrency": "20", + ... + } +} +``` + +*New in v2.2* ## TSDB Admin APIs These are APIs that expose database functionalities for the advanced user. These APIs are not enabled unless the `--web.enable-admin-api` is set. diff --git a/web/api/v1/api.go b/web/api/v1/api.go index c0cb8c6a7f..4f9eb2bfed 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -114,9 +114,10 @@ type API struct { targetRetriever targetRetriever alertmanagerRetriever alertmanagerRetriever - now func() time.Time - config func() config.Config - ready func(http.HandlerFunc) http.HandlerFunc + now func() time.Time + config func() config.Config + flagsMap map[string]string + ready func(http.HandlerFunc) http.HandlerFunc db func() *tsdb.DB enableAdmin bool @@ -129,6 +130,7 @@ func NewAPI( tr targetRetriever, ar alertmanagerRetriever, configFunc func() config.Config, + flagsMap map[string]string, readyFunc func(http.HandlerFunc) http.HandlerFunc, db func() *tsdb.DB, enableAdmin bool, @@ -140,6 +142,7 @@ func NewAPI( alertmanagerRetriever: ar, now: time.Now, config: configFunc, + flagsMap: flagsMap, ready: readyFunc, db: db, enableAdmin: enableAdmin, @@ -180,6 +183,7 @@ func (api *API) Register(r *route.Router) { r.Get("/alertmanagers", instr("alertmanagers", api.alertmanagers)) r.Get("/status/config", instr("config", api.serveConfig)) + r.Get("/status/flags", instr("flags", api.serveFlags)) r.Post("/read", api.ready(prometheus.InstrumentHandler("read", http.HandlerFunc(api.remoteRead)))) // Admin APIs @@ -494,6 +498,10 @@ func (api *API) serveConfig(r *http.Request) (interface{}, *apiError) { return cfg, nil } +func (api *API) serveFlags(r *http.Request) (interface{}, *apiError) { + return api.flagsMap, nil +} + func (api *API) remoteRead(w http.ResponseWriter, r *http.Request) { req, err := remote.DecodeReadRequest(r) if err != nil { diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 9b6ebe5424..6716f94a21 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -63,6 +63,11 @@ var samplePrometheusCfg = config.Config{ RemoteReadConfigs: []*config.RemoteReadConfig{}, } +var sampleFlagMap = map[string]string{ + "flag1": "value1", + "flag2": "value2", +} + func TestEndpoints(t *testing.T) { suite, err := promql.NewTest(t, ` load 1m @@ -108,9 +113,10 @@ func TestEndpoints(t *testing.T) { QueryEngine: suite.QueryEngine(), targetRetriever: tr, alertmanagerRetriever: ar, - now: func() time.Time { return now }, - config: func() config.Config { return samplePrometheusCfg }, - ready: func(f http.HandlerFunc) http.HandlerFunc { return f }, + now: func() time.Time { return now }, + config: func() config.Config { return samplePrometheusCfg }, + flagsMap: sampleFlagMap, + ready: func(f http.HandlerFunc) http.HandlerFunc { return f }, } start := time.Unix(0, 0) @@ -449,6 +455,10 @@ func TestEndpoints(t *testing.T) { YAML: samplePrometheusCfg.String(), }, }, + { + endpoint: api.serveFlags, + response: sampleFlagMap, + }, } methods := func(f apiFunc) []string { diff --git a/web/web.go b/web/web.go index d5f0cbe5a7..63324435f4 100644 --- a/web/web.go +++ b/web/web.go @@ -187,6 +187,7 @@ func New(logger log.Logger, o *Options) *Handler { defer h.mtx.RUnlock() return *h.config }, + o.Flags, h.testReady, h.options.TSDB, h.options.EnableAdminAPI,