Permalink
Browse files

Make query_range more robust.

Gracefully handle decimal values, by truncating them.

Limit amount of steps, to avoid accidentally pulling too much data.
This limit returns up to ~500kB per timeseries, and allows
for 60s granularity for a week and 1h granularity for a year.

Change-Id: Ie549fc24deb2eecbc6c5d1b6088a548a6b02e849
  • Loading branch information...
brian-brazil authored and beorn7 committed Oct 20, 2014
1 parent 75e37db commit f114bbd4e70a6b0dbfd6bff4cc3c4561e03cf912
Showing with 15 additions and 3 deletions.
  1. +15 −3 web/api/query.go
@@ -77,9 +77,14 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) {

params := http_utils.GetQueryParams(r)
expr := params.Get("expr")
end, _ := strconv.ParseInt(params.Get("end"), 0, 64)
duration, _ := strconv.ParseInt(params.Get("range"), 0, 64)
step, _ := strconv.ParseInt(params.Get("step"), 0, 64)

// Gracefully handle decimal input, by truncating it.
endFloat, _ := strconv.ParseFloat(params.Get("end"), 64)
durationFloat, _ := strconv.ParseFloat(params.Get("range"), 64)
stepFloat, _ := strconv.ParseFloat(params.Get("step"), 64)
end := int64(endFloat)
duration := int64(durationFloat)
step := int64(stepFloat)

exprNode, err := rules.LoadExprFromString(expr)
if err != nil {
@@ -103,6 +108,13 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) {
duration = end
}

// For safety, limit the number of returned points per timeseries.
// This is sufficient for 60s resolution for a week or 1h resolution for a year.
if duration/step > 11000 {
fmt.Fprint(w, ast.ErrorToJSON(errors.New("Exceeded maximum resolution of 11,000 points per timeseries. Try decreasing the query resolution (?step=XX).")))
return
}

// Align the start to step "tick" boundary.
end -= end % step

0 comments on commit f114bbd

Please sign in to comment.