Skip to content

Commit b87487e

Browse files
author
Igor Makhlin
authored
Merge pull request #180 from talIguaz/TSDB-43
Bug TSDB-43: avg_over_time in prom console returns NaN when the series is not present in all the time range
2 parents e02f9d9 + a025ad4 commit b87487e

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

pkg/querier/series.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ type aggrSeriesIterator struct {
251251
// Advance an iterator to the specified time (t)
252252
func (s *aggrSeriesIterator) Seek(t int64) bool {
253253
if t <= s.set.baseTime {
254-
s.index = 0
254+
s.index = s.getNextValidCell(-1)
255255
return true
256256
}
257257

@@ -266,14 +266,16 @@ func (s *aggrSeriesIterator) Seek(t int64) bool {
266266
// Advance an iterator to the next time interval/bucket
267267
func (s *aggrSeriesIterator) Next() bool {
268268
// Advance the index to the next non-empty cell
269-
var nextIndex int
270-
for nextIndex = s.index + 1; nextIndex <= s.aggrSet.GetMaxCell() && !s.aggrSet.DoesCellHaveData(nextIndex); nextIndex++ {
271-
}
272-
273-
s.index = nextIndex
269+
s.index = s.getNextValidCell(s.index)
274270
return s.index <= s.aggrSet.GetMaxCell()
275271
}
276272

273+
func (s *aggrSeriesIterator) getNextValidCell(from int) (nextIndex int) {
274+
for nextIndex = from + 1; nextIndex <= s.aggrSet.GetMaxCell() && !s.aggrSet.DoesCellHaveData(nextIndex); nextIndex++ {
275+
}
276+
return
277+
}
278+
277279
// Return the time and value at the current bucket
278280
func (s *aggrSeriesIterator) At() (t int64, v float64) {
279281
val, _ := s.aggrSet.GetCellValue(s.aggrType, s.index)

pkg/tsdb/v3iotsdb_integration_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,81 @@ func testQueryDataOverlappingWindowCase(test *testing.T, v3ioConfig *config.V3io
471471
}
472472
}
473473

474+
// Calling Seek instead of next for the first time while iterating over data (TSDB-43)
475+
func TestIgnoreNaNWhenSeekingAggSeries(t *testing.T) {
476+
v3ioConfig, err := tsdbtest.LoadV3ioConfig()
477+
if err != nil {
478+
t.Fatalf("unable to load configuration. Error: %v", err)
479+
}
480+
metricsName := "cpu"
481+
baseTime := int64(1532940510000)
482+
userLabels := utils.LabelsFromStrings("os", "linux", "iguaz", "yesplease")
483+
data := []tsdbtest.DataPoint{{Time: baseTime, Value: 300.3},
484+
{Time: baseTime + minuteInMillis, Value: 300.3},
485+
{Time: baseTime + 2*minuteInMillis, Value: 100.4},
486+
{Time: baseTime + 5*minuteInMillis, Value: 200.0}}
487+
from := int64(baseTime - 60*minuteInMillis)
488+
to := int64(baseTime + 6*minuteInMillis)
489+
step := int64(2 * minuteInMillis)
490+
agg := "avg"
491+
expected := map[string][]tsdbtest.DataPoint{
492+
"avg": {{baseTime, 300.3},
493+
{baseTime + step, 100.4},
494+
{baseTime + 2*step, 200}}}
495+
496+
adapter, teardown := tsdbtest.SetUpWithData(t, v3ioConfig, metricsName, data, userLabels)
497+
defer teardown()
498+
499+
qry, err := adapter.Querier(nil, from, to)
500+
if err != nil {
501+
t.Fatalf("Failed to create Querier. reason: %v", err)
502+
}
503+
504+
set, err := qry.Select(metricsName, agg, step, "")
505+
if err != nil {
506+
t.Fatalf("Failed to run Select. reason: %v", err)
507+
}
508+
509+
var counter int
510+
for counter = 0; set.Next(); counter++ {
511+
if set.Err() != nil {
512+
t.Fatalf("Failed to query metric. reason: %v", set.Err())
513+
}
514+
515+
series := set.At()
516+
agg := series.Labels().Get(aggregate.AggregateLabel)
517+
iter := series.Iterator()
518+
if iter.Err() != nil {
519+
t.Fatalf("Failed to query data series. reason: %v", iter.Err())
520+
}
521+
if !iter.Seek(0) {
522+
t.Fatal("Seek time returned false, iterator error:", iter.Err())
523+
}
524+
var actual []tsdbtest.DataPoint
525+
t0, v0 := iter.At()
526+
if iter.Err() != nil {
527+
t.Fatal("error iterating over series", iter.Err())
528+
}
529+
actual = append(actual, tsdbtest.DataPoint{Time: t0, Value: v0})
530+
for iter.Next() {
531+
t1, v1 := iter.At()
532+
533+
if iter.Err() != nil {
534+
t.Fatal("error iterating over series", iter.Err())
535+
}
536+
actual = append(actual, tsdbtest.DataPoint{Time: t1, Value: v1})
537+
}
538+
assert.ElementsMatch(t, expected[agg], actual)
539+
}
540+
541+
if set.Err() != nil {
542+
t.Fatalf("Failed to query metric. reason: %v", set.Err())
543+
}
544+
if counter == 0 && len(expected) > 0 {
545+
t.Fatalf("No data was received")
546+
}
547+
}
548+
474549
func TestCreateTSDB(t *testing.T) {
475550
v3ioConfig, err := tsdbtest.LoadV3ioConfig()
476551
if err != nil {

0 commit comments

Comments
 (0)