diff --git a/pkg/ingester/flush.go b/pkg/ingester/flush.go index 2928029723bd2ad2bd16d35f19094831e1ff04e1..d45c11bea6377e60e74b600def3c854cd29f39d1 100644 --- a/pkg/ingester/flush.go +++ b/pkg/ingester/flush.go @@ -18,6 +18,7 @@ import ( "github.com/cortexproject/cortex/pkg/ingester/client" "github.com/cortexproject/cortex/pkg/util" "github.com/grafana/loki/pkg/chunkenc" + loki_util "github.com/grafana/loki/pkg/util" ) var ( @@ -261,12 +262,12 @@ func (i *Ingester) flushChunks(ctx context.Context, fp model.Fingerprint, labelP wireChunks := make([]chunk.Chunk, 0, len(cs)) for _, c := range cs { - firstTime, lastTime := c.chunk.Bounds() + firstTime, lastTime := loki_util.RoundToMilliseconds(c.chunk.Bounds()) c := chunk.NewChunk( userID, fp, metric, chunkenc.NewFacade(c.chunk), - model.TimeFromUnixNano(firstTime.UnixNano()), - model.TimeFromUnixNano(lastTime.UnixNano()), + firstTime, + lastTime, ) start := time.Now() diff --git a/pkg/storage/store.go b/pkg/storage/store.go index 0ff8fccae6154ed6bae855fee4c1ea29a0c6c5e0..7e15663734ffec752180df950e848107b1e40706 100644 --- a/pkg/storage/store.go +++ b/pkg/storage/store.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/loki/pkg/iter" "github.com/grafana/loki/pkg/logproto" "github.com/grafana/loki/pkg/logql" + "github.com/grafana/loki/pkg/util" "github.com/opentracing/opentracing-go" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/pkg/labels" @@ -56,7 +57,7 @@ func (s *store) LazyQuery(ctx context.Context, req *logproto.QueryRequest) (iter } matchers = append(matchers, nameLabelMatcher) - from, through := model.TimeFromUnixNano(req.Start.UnixNano()), model.TimeFromUnixNano(req.End.UnixNano()) + from, through := util.RoundToMilliseconds(req.Start, req.End) chks, fetchers, err := s.GetChunkRefs(ctx, from, through, matchers...) if err != nil { return nil, err diff --git a/pkg/util/conv.go b/pkg/util/conv.go index bc95638cb8ee0e9909aa5b8c6e18ee0896093e6d..54e31dcd4f9e4ab64e1ac41c770aa835931ae78e 100644 --- a/pkg/util/conv.go +++ b/pkg/util/conv.go @@ -1,8 +1,10 @@ package util import ( + "math" "sort" "strings" + "time" "github.com/cortexproject/cortex/pkg/ingester/client" "github.com/grafana/loki/pkg/logql" @@ -41,3 +43,10 @@ func ModelLabelSetToMap(m model.LabelSet) map[string]string { } return result } + +// RoundToMilliseconds returns milliseconds precision time from nanoseconds. +// from will be rounded down to the nearest milliseconds while through is rounded up. +func RoundToMilliseconds(from, through time.Time) (model.Time, model.Time) { + return model.Time(int64(math.Floor(float64(from.UnixNano()) / float64(time.Millisecond)))), + model.Time(int64(math.Ceil(float64(through.UnixNano()) / float64(time.Millisecond)))) +} diff --git a/pkg/util/conv_test.go b/pkg/util/conv_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ab27d230b26f9c98badf42b25fafd9819ad2a7f8 --- /dev/null +++ b/pkg/util/conv_test.go @@ -0,0 +1,59 @@ +package util + +import ( + "reflect" + "testing" + "time" + + "github.com/prometheus/common/model" +) + +func TestRoundToMilliseconds(t *testing.T) { + tests := []struct { + name string + from time.Time + through time.Time + wantFrom model.Time + wantThrough model.Time + }{ + { + "0", + time.Unix(0, 0), + time.Unix(0, 1), + model.Time(0), + model.Time(1), + }, + { + "equal", + time.Unix(0, time.Millisecond.Nanoseconds()), + time.Unix(0, time.Millisecond.Nanoseconds()), + model.Time(1), + model.Time(1), + }, + { + "exact", + time.Unix(0, time.Millisecond.Nanoseconds()), + time.Unix(0, 2*time.Millisecond.Nanoseconds()), + model.Time(1), + model.Time(2), + }, + { + "rounding", + time.Unix(0, time.Millisecond.Nanoseconds()+10), + time.Unix(0, 2*time.Millisecond.Nanoseconds()+10), + model.Time(1), + model.Time(3), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + from, through := RoundToMilliseconds(tt.from, tt.through) + if !reflect.DeepEqual(from, tt.wantFrom) { + t.Errorf("RoundToMilliseconds() from = %v, want %v", from, tt.wantFrom) + } + if !reflect.DeepEqual(through, tt.wantThrough) { + t.Errorf("RoundToMilliseconds() through = %v, want %v", through, tt.wantThrough) + } + }) + } +}