diff --git a/storage/local/storage_test.go b/storage/local/storage_test.go index b63f2e30b7..8c905b5111 100644 --- a/storage/local/storage_test.go +++ b/storage/local/storage_test.go @@ -389,7 +389,7 @@ func createRandomSamples(r *rand.Rand) clientmodel.Samples { result = append(result, &clientmodel.Sample{ Metric: metric, Value: createValue(), - Timestamp: clientmodel.Timestamp(timestamp), + Timestamp: clientmodel.TimestampFromUnix(timestamp), }) incTimestamp() case 1: // A streak of random sample values. @@ -397,7 +397,7 @@ func createRandomSamples(r *rand.Rand) clientmodel.Samples { result = append(result, &clientmodel.Sample{ Metric: metric, Value: createValue(), - Timestamp: clientmodel.Timestamp(timestamp), + Timestamp: clientmodel.TimestampFromUnix(timestamp), }) incTimestamp() } @@ -407,7 +407,7 @@ func createRandomSamples(r *rand.Rand) clientmodel.Samples { result = append(result, &clientmodel.Sample{ Metric: metric, Value: value, - Timestamp: clientmodel.Timestamp(timestamp), + Timestamp: clientmodel.TimestampFromUnix(timestamp), }) incTimestamp() value = applyDelta(value) @@ -418,7 +418,7 @@ func createRandomSamples(r *rand.Rand) clientmodel.Samples { result = append(result, &clientmodel.Sample{ Metric: metric, Value: value, - Timestamp: clientmodel.Timestamp(timestamp), + Timestamp: clientmodel.TimestampFromUnix(timestamp), }) incTimestamp() } diff --git a/storage/metric/sample.go b/storage/metric/sample.go index ab592a0ade..2291fd743f 100644 --- a/storage/metric/sample.go +++ b/storage/metric/sample.go @@ -21,7 +21,7 @@ import ( // MarshalJSON implements json.Marshaler. func (s SamplePair) MarshalJSON() ([]byte, error) { - return []byte(fmt.Sprintf("{\"Value\": \"%f\", \"Timestamp\": %d}", s.Value, s.Timestamp)), nil + return []byte(fmt.Sprintf("{\"Value\": \"%f\", \"Timestamp\": %s}", s.Value, s.Timestamp.String())), nil } // SamplePair pairs a SampleValue with a Timestamp. diff --git a/web/api/query.go b/web/api/query.go index bde4da9d1a..92a144645e 100644 --- a/web/api/query.go +++ b/web/api/query.go @@ -78,13 +78,14 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) { params := http_utils.GetQueryParams(r) expr := params.Get("expr") - // Gracefully handle decimal input, by truncating it. + // Input times and durations are in seconds and get converted to nanoseconds. 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) + nanosPerSecond := int64(time.Second / time.Nanosecond) + end := int64(endFloat) * nanosPerSecond + duration := int64(durationFloat) * nanosPerSecond + step := int64(stepFloat) * nanosPerSecond exprNode, err := rules.LoadExprFromString(expr) if err != nil { @@ -97,11 +98,11 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) { } if end == 0 { - end = clientmodel.Now().Unix() + end = clientmodel.Now().UnixNano() } - if step < 1 { - step = 1 + if step <= 0 { + step = nanosPerSecond } if end-duration < 0 { @@ -123,9 +124,9 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) { evalTimer := queryStats.GetTimer(stats.TotalEvalTime).Start() matrix, err := ast.EvalVectorRange( exprNode.(ast.VectorNode), - clientmodel.TimestampFromUnix(end-duration), - clientmodel.TimestampFromUnix(end), - time.Duration(step)*time.Second, + clientmodel.TimestampFromUnixNano(end-duration), + clientmodel.TimestampFromUnixNano(end), + time.Duration(step), serv.Storage, queryStats) if err != nil {