mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-20 07:19:17 +01:00
app/vmselect/prometheus: report about incorrect time or duration instead of silently using the default value
This should prevent from incorrect usage of the querying API. Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/52
This commit is contained in:
parent
1458450dba
commit
667115a5c7
@ -37,9 +37,18 @@ func FederateHandler(w http.ResponseWriter, r *http.Request) error {
|
|||||||
return fmt.Errorf("cannot parse request form values: %s", err)
|
return fmt.Errorf("cannot parse request form values: %s", err)
|
||||||
}
|
}
|
||||||
matches := r.Form["match[]"]
|
matches := r.Form["match[]"]
|
||||||
maxLookback := getDuration(r, "max_lookback", defaultStep)
|
maxLookback, err := getDuration(r, "max_lookback", defaultStep)
|
||||||
start := getTime(r, "start", ct-maxLookback)
|
if err != nil {
|
||||||
end := getTime(r, "end", ct)
|
return err
|
||||||
|
}
|
||||||
|
start, err := getTime(r, "start", ct-maxLookback)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
end, err := getTime(r, "end", ct)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
deadline := getDeadline(r)
|
deadline := getDeadline(r)
|
||||||
if start >= end {
|
if start >= end {
|
||||||
start = end - defaultStep
|
start = end - defaultStep
|
||||||
@ -99,8 +108,14 @@ func ExportHandler(w http.ResponseWriter, r *http.Request) error {
|
|||||||
match := r.FormValue("match")
|
match := r.FormValue("match")
|
||||||
matches = []string{match}
|
matches = []string{match}
|
||||||
}
|
}
|
||||||
start := getTime(r, "start", 0)
|
start, err := getTime(r, "start", 0)
|
||||||
end := getTime(r, "end", ct)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
end, err := getTime(r, "end", ct)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
format := r.FormValue("format")
|
format := r.FormValue("format")
|
||||||
deadline := getDeadline(r)
|
deadline := getDeadline(r)
|
||||||
if start >= end {
|
if start >= end {
|
||||||
@ -265,8 +280,14 @@ func SeriesHandler(w http.ResponseWriter, r *http.Request) error {
|
|||||||
return fmt.Errorf("cannot parse form values: %s", err)
|
return fmt.Errorf("cannot parse form values: %s", err)
|
||||||
}
|
}
|
||||||
matches := r.Form["match[]"]
|
matches := r.Form["match[]"]
|
||||||
start := getTime(r, "start", ct-defaultStep)
|
start, err := getTime(r, "start", ct-defaultStep)
|
||||||
end := getTime(r, "end", ct)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
end, err := getTime(r, "end", ct)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
deadline := getDeadline(r)
|
deadline := getDeadline(r)
|
||||||
|
|
||||||
tagFilterss, err := getTagFilterssFromMatches(matches)
|
tagFilterss, err := getTagFilterssFromMatches(matches)
|
||||||
@ -324,8 +345,14 @@ func QueryHandler(w http.ResponseWriter, r *http.Request) error {
|
|||||||
ct := currentTime()
|
ct := currentTime()
|
||||||
|
|
||||||
query := r.FormValue("query")
|
query := r.FormValue("query")
|
||||||
start := getTime(r, "time", ct)
|
start, err := getTime(r, "time", ct)
|
||||||
step := getDuration(r, "step", latencyOffset)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
step, err := getDuration(r, "step", latencyOffset)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
deadline := getDeadline(r)
|
deadline := getDeadline(r)
|
||||||
|
|
||||||
if len(query) > *maxQueryLen {
|
if len(query) > *maxQueryLen {
|
||||||
@ -388,9 +415,18 @@ func QueryRangeHandler(w http.ResponseWriter, r *http.Request) error {
|
|||||||
ct := currentTime()
|
ct := currentTime()
|
||||||
|
|
||||||
query := r.FormValue("query")
|
query := r.FormValue("query")
|
||||||
start := getTime(r, "start", ct-defaultStep)
|
start, err := getTime(r, "start", ct-defaultStep)
|
||||||
end := getTime(r, "end", ct)
|
if err != nil {
|
||||||
step := getDuration(r, "step", defaultStep)
|
return err
|
||||||
|
}
|
||||||
|
end, err := getTime(r, "end", ct)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
step, err := getDuration(r, "step", defaultStep)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
deadline := getDeadline(r)
|
deadline := getDeadline(r)
|
||||||
mayCache := !getBool(r, "nocache")
|
mayCache := !getBool(r, "nocache")
|
||||||
|
|
||||||
@ -467,25 +503,25 @@ func adjustLastPoints(tss []netstorage.Result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTime(r *http.Request, argKey string, defaultValue int64) int64 {
|
func getTime(r *http.Request, argKey string, defaultValue int64) (int64, error) {
|
||||||
argValue := r.FormValue(argKey)
|
argValue := r.FormValue(argKey)
|
||||||
if len(argValue) == 0 {
|
if len(argValue) == 0 {
|
||||||
return defaultValue
|
return defaultValue, nil
|
||||||
}
|
}
|
||||||
secs, err := strconv.ParseFloat(argValue, 64)
|
secs, err := strconv.ParseFloat(argValue, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Try parsing string format
|
// Try parsing string format
|
||||||
t, err := time.Parse(time.RFC3339, argValue)
|
t, err := time.Parse(time.RFC3339, argValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return defaultValue
|
return 0, fmt.Errorf("cannot parse %q=%q: %s", argKey, argValue, err)
|
||||||
}
|
}
|
||||||
secs = float64(t.UnixNano()) / 1e9
|
secs = float64(t.UnixNano()) / 1e9
|
||||||
}
|
}
|
||||||
msecs := int64(secs * 1e3)
|
msecs := int64(secs * 1e3)
|
||||||
if msecs < minTimeMsecs || msecs > maxTimeMsecs {
|
if msecs < minTimeMsecs || msecs > maxTimeMsecs {
|
||||||
return defaultValue
|
return 0, fmt.Errorf("%q=%dms is out of allowed range [%d ... %d]", argKey, msecs, minTimeMsecs, maxTimeMsecs)
|
||||||
}
|
}
|
||||||
return msecs
|
return msecs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -494,31 +530,34 @@ const (
|
|||||||
maxTimeMsecs = int64(1<<63-1) / 1e6
|
maxTimeMsecs = int64(1<<63-1) / 1e6
|
||||||
)
|
)
|
||||||
|
|
||||||
func getDuration(r *http.Request, argKey string, defaultValue int64) int64 {
|
func getDuration(r *http.Request, argKey string, defaultValue int64) (int64, error) {
|
||||||
argValue := r.FormValue(argKey)
|
argValue := r.FormValue(argKey)
|
||||||
if len(argValue) == 0 {
|
if len(argValue) == 0 {
|
||||||
return defaultValue
|
return defaultValue, nil
|
||||||
}
|
}
|
||||||
secs, err := strconv.ParseFloat(argValue, 64)
|
secs, err := strconv.ParseFloat(argValue, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Try parsing string format
|
// Try parsing string format
|
||||||
d, err := time.ParseDuration(argValue)
|
d, err := time.ParseDuration(argValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return defaultValue
|
return 0, fmt.Errorf("cannot parse %q=%q: %s", argKey, argValue, err)
|
||||||
}
|
}
|
||||||
secs = d.Seconds()
|
secs = d.Seconds()
|
||||||
}
|
}
|
||||||
msecs := int64(secs * 1e3)
|
msecs := int64(secs * 1e3)
|
||||||
if msecs <= 0 || msecs > maxDurationMsecs {
|
if msecs <= 0 || msecs > maxDurationMsecs {
|
||||||
return defaultValue
|
return 0, fmt.Errorf("%q=%dms is out of allowed range [%d ... %d]", argKey, msecs, 0, maxDurationMsecs)
|
||||||
}
|
}
|
||||||
return msecs
|
return msecs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxDurationMsecs = 100 * 365 * 24 * 3600 * 1000
|
const maxDurationMsecs = 100 * 365 * 24 * 3600 * 1000
|
||||||
|
|
||||||
func getDeadline(r *http.Request) netstorage.Deadline {
|
func getDeadline(r *http.Request) netstorage.Deadline {
|
||||||
d := getDuration(r, "timeout", 0)
|
d, err := getDuration(r, "timeout", 0)
|
||||||
|
if err != nil {
|
||||||
|
d = 0
|
||||||
|
}
|
||||||
dMax := int64(maxQueryDuration.Seconds() * 1e3)
|
dMax := int64(maxQueryDuration.Seconds() * 1e3)
|
||||||
if d <= 0 || d > dMax {
|
if d <= 0 || d > dMax {
|
||||||
d = dMax
|
d = dMax
|
||||||
|
Loading…
Reference in New Issue
Block a user