diff --git a/Makefile.common b/Makefile.common index a422e1b69..7e86f4543 100644 --- a/Makefile.common +++ b/Makefile.common @@ -87,14 +87,14 @@ ifeq ($(GOHOSTARCH),amd64) endif endif -.PHONY: all -all: precheck style staticcheck unused build test - # This rule is used to forward a target like "build" to "common-build". This # allows a new "build" target to be defined in a Makefile which includes this # one and override "common-build" without override warnings. %: common-% ; +.PHONY: common-all +common-all: precheck style check_license staticcheck unused build test + .PHONY: common-style common-style: @echo ">> checking code style" diff --git a/cmd/prometheus/main.go b/cmd/prometheus/main.go index 79675ec83..a3f21967f 100644 --- a/cmd/prometheus/main.go +++ b/cmd/prometheus/main.go @@ -187,13 +187,13 @@ func main() { Hidden().PlaceHolder("").BytesVar(&cfg.tsdb.WALSegmentSize) a.Flag("storage.tsdb.retention", "[DEPRECATED] How long to retain samples in storage. This flag has been deprecated, use \"storage.tsdb.retention.time\" instead"). - Default(defaultRetentionString).SetValue(&oldFlagRetentionDuration) + SetValue(&oldFlagRetentionDuration) - a.Flag("storage.tsdb.retention.time", "How long to retain samples in storage. Overrides \"storage.tsdb.retention\" if this flag is set to anything other than default."). - Default(defaultRetentionString).SetValue(&newFlagRetentionDuration) + a.Flag("storage.tsdb.retention.time", "How long to retain samples in storage. When this flag is set it overrides \"storage.tsdb.retention\". If neither this flag nor \"storage.tsdb.retention\" nor \"storage.tsdb.retention.size\" is set, the retention time defaults to "+defaultRetentionString+"."). + SetValue(&newFlagRetentionDuration) a.Flag("storage.tsdb.retention.size", "[EXPERIMENTAL] Maximum number of bytes that can be stored for blocks. Units supported: KB, MB, GB, TB, PB. This flag is experimental and can be changed in future releases."). - Default("0").BytesVar(&cfg.tsdb.MaxBytes) + BytesVar(&cfg.tsdb.MaxBytes) a.Flag("storage.tsdb.no-lockfile", "Do not create lockfile in data directory."). Default("false").BoolVar(&cfg.tsdb.NoLockfile) @@ -245,6 +245,8 @@ func main() { os.Exit(2) } + logger := promlog.New(&cfg.promlogConfig) + 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)) @@ -265,36 +267,46 @@ func main() { // RoutePrefix must always be at least '/'. cfg.web.RoutePrefix = "/" + strings.Trim(cfg.web.RoutePrefix, "/") - cfg.tsdb.RetentionDuration = chooseRetention(oldFlagRetentionDuration, newFlagRetentionDuration) - - // Check for overflows. This limits our max retention to ~292.5y. - if cfg.tsdb.RetentionDuration < 0 { - cfg.tsdb.RetentionDuration = math.MaxInt64 - } - - if cfg.tsdb.MaxBlockDuration == 0 { - cfg.tsdb.MaxBlockDuration = cfg.tsdb.RetentionDuration / 10 - - // Prevent blocks from getting too big. - monthLong, err := model.ParseDuration("31d") - if err != nil { - panic(err) + { // Time retention settings. + if oldFlagRetentionDuration != 0 { + level.Warn(logger).Log("deprecation_notice", "'storage.tsdb.retention' flag is deprecated use 'storage.tsdb.retention.time' instead.") + cfg.tsdb.RetentionDuration = oldFlagRetentionDuration } - if cfg.tsdb.MaxBlockDuration > monthLong { - cfg.tsdb.MaxBlockDuration = monthLong + // When the new flag is set it takes precedence. + if newFlagRetentionDuration != 0 { + cfg.tsdb.RetentionDuration = newFlagRetentionDuration + } + + if cfg.tsdb.RetentionDuration == 0 && cfg.tsdb.MaxBytes == 0 { + cfg.tsdb.RetentionDuration = defaultRetentionDuration + level.Info(logger).Log("msg", "no time or size retention was set so using the default time retention", "duration", defaultRetentionDuration) + } + + // Check for overflows. This limits our max retention to ~292.5y. + if cfg.tsdb.RetentionDuration < 0 { + cfg.tsdb.RetentionDuration = math.MaxInt64 + } + } + + { // Max block size settings. + if cfg.tsdb.MaxBlockDuration == 0 { + maxBlockDuration, err := model.ParseDuration("31d") + if err != nil { + panic(err) + } + // When the time retention is set and not too big use to define the max block duration. + if cfg.tsdb.RetentionDuration != 0 && cfg.tsdb.RetentionDuration/10 < maxBlockDuration { + maxBlockDuration = cfg.tsdb.RetentionDuration / 10 + } + + cfg.tsdb.MaxBlockDuration = maxBlockDuration } } promql.LookbackDelta = time.Duration(cfg.lookbackDelta) promql.SetDefaultEvaluationInterval(time.Duration(config.DefaultGlobalConfig.EvaluationInterval)) - logger := promlog.New(&cfg.promlogConfig) - - if oldFlagRetentionDuration != defaultRetentionDuration { - level.Warn(logger).Log("deprecation_notice", `"storage.tsdb.retention" flag is deprecated use "storage.tsdb.retention.time" instead.`) - } - // Above level 6, the k8s client would log bearer tokens in clear-text. klog.ClampLevel(6) klog.SetLogger(log.With(logger, "component", "k8s_client_runtime")) @@ -633,6 +645,14 @@ func main() { return fmt.Errorf("opening storage failed: %s", err) } level.Info(logger).Log("msg", "TSDB started") + level.Debug(logger).Log("msg", "TSDB options", + "MinBlockDuration", cfg.tsdb.MinBlockDuration, + "MaxBlockDuration", cfg.tsdb.MaxBlockDuration, + "MaxBytes", cfg.tsdb.MaxBytes, + "NoLockfile", cfg.tsdb.NoLockfile, + "RetentionDuration", cfg.tsdb.RetentionDuration, + "WALSegmentSize", cfg.tsdb.WALSegmentSize, + ) startTimeMargin := int64(2 * time.Duration(cfg.tsdb.MinBlockDuration).Seconds() * 1000) localStorage.Set(db, startTimeMargin) @@ -799,19 +819,3 @@ func sendAlerts(s sender, externalURL string) rules.NotifyFunc { } } } - -// chooseRetention is some roundabout code to support both RetentionDuration and Retention (for different flags). -// If Retention is 15d, then it means that the default value is set and the value of RetentionDuration is used. -func chooseRetention(oldFlagDuration, newFlagDuration model.Duration) model.Duration { - retention := oldFlagDuration - if retention == defaultRetentionDuration { - retention = newFlagDuration - } - - // Further newFlag takes precedence if it's set to anything other than default. - if newFlagDuration != defaultRetentionDuration { - retention = newFlagDuration - } - - return retention -} diff --git a/cmd/prometheus/main_test.go b/cmd/prometheus/main_test.go index 0671d759e..e82e55bc3 100644 --- a/cmd/prometheus/main_test.go +++ b/cmd/prometheus/main_test.go @@ -25,7 +25,6 @@ import ( "testing" "time" - "github.com/prometheus/common/model" "github.com/prometheus/prometheus/notifier" "github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/rules" @@ -285,31 +284,3 @@ func TestWALSegmentSizeBounds(t *testing.T) { } } } - -func TestChooseRetention(t *testing.T) { - retention1, err := model.ParseDuration("20d") - testutil.Ok(t, err) - retention2, err := model.ParseDuration("30d") - testutil.Ok(t, err) - - cases := []struct { - oldFlagRetention model.Duration - newFlagRetention model.Duration - - chosen model.Duration - }{ - // Both are default (unset flags). - {defaultRetentionDuration, defaultRetentionDuration, defaultRetentionDuration}, - // Old flag is set and new flag is unset. - {retention1, defaultRetentionDuration, retention1}, - // Old flag is unset and new flag is set. - {defaultRetentionDuration, retention2, retention2}, - // Both flags are set. - {retention1, retention2, retention2}, - } - - for _, tc := range cases { - retention := chooseRetention(tc.oldFlagRetention, tc.newFlagRetention) - testutil.Equals(t, tc.chosen, retention) - } -} diff --git a/console_libraries/menu.lib b/console_libraries/menu.lib index 7ee2120c3..199ebf9f4 100644 --- a/console_libraries/menu.lib +++ b/console_libraries/menu.lib @@ -20,8 +20,8 @@ + + {{ end }} diff --git a/console_libraries/prom.lib b/console_libraries/prom.lib index db6f825b7..98c9c49ac 100644 --- a/console_libraries/prom.lib +++ b/console_libraries/prom.lib @@ -19,8 +19,9 @@ var PATH_PREFIX = "{{ pathPrefix }}"; {{ end }} {{/* Top of all pages. */}} -{{ define "head" }} - +{{ define "head" -}} + + {{ template "prom_console_head" }} diff --git a/consoles/prometheus.html b/consoles/prometheus.html index ffb67dd2e..e0d026376 100644 --- a/consoles/prometheus.html +++ b/consoles/prometheus.html @@ -27,6 +27,7 @@ {{ else }} No devices found. {{ end }} + {{ template "prom_content_tail" . }} diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 2f1772692..2230643e2 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -266,6 +266,7 @@ func (api *API) query(r *http.Request) apiFuncResult { var err error ts, err = parseTime(t) if err != nil { + err = fmt.Errorf("invalid parameter 'time': %s", err) return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} } } else { @@ -277,6 +278,7 @@ func (api *API) query(r *http.Request) apiFuncResult { var cancel context.CancelFunc timeout, err := parseDuration(to) if err != nil { + err = fmt.Errorf("invalid parameter 'timeout': %s", err) return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} } @@ -286,6 +288,7 @@ func (api *API) query(r *http.Request) apiFuncResult { qry, err := api.QueryEngine.NewInstantQuery(api.Queryable, r.FormValue("query"), ts) if err != nil { + err = fmt.Errorf("invalid parameter 'query': %s", err) return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} } @@ -310,10 +313,12 @@ func (api *API) query(r *http.Request) apiFuncResult { func (api *API) queryRange(r *http.Request) apiFuncResult { start, err := parseTime(r.FormValue("start")) if err != nil { + err = fmt.Errorf("invalid parameter 'start': %s", err) return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} } end, err := parseTime(r.FormValue("end")) if err != nil { + err = fmt.Errorf("invalid parameter 'end': %s", err) return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} } if end.Before(start) { @@ -323,6 +328,7 @@ func (api *API) queryRange(r *http.Request) apiFuncResult { step, err := parseDuration(r.FormValue("step")) if err != nil { + err = fmt.Errorf("invalid parameter 'step': %s", err) return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} } @@ -343,6 +349,7 @@ func (api *API) queryRange(r *http.Request) apiFuncResult { var cancel context.CancelFunc timeout, err := parseDuration(to) if err != nil { + err = fmt.Errorf("invalid parameter 'timeout': %s", err) return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} }