From 4bf77662d35789b92a2bf04bfec3c802caba3473 Mon Sep 17 00:00:00 2001 From: Cyril Tovena <cyril.tovena@gmail.com> Date: Thu, 18 Jul 2019 08:49:58 -0400 Subject: [PATCH] rounds nanoseconds boundaries to milliseconds (#771) * rounds nanoseconds boundaries to milliseconds * convert also store query --- pkg/ingester/flush.go | 7 ++--- pkg/storage/store.go | 3 ++- pkg/util/conv.go | 9 +++++++ pkg/util/conv_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 pkg/util/conv_test.go diff --git a/pkg/ingester/flush.go b/pkg/ingester/flush.go index 29280297..d45c11be 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 0ff8fcca..7e156637 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 bc95638c..54e31dcd 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 00000000..ab27d230 --- /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) + } + }) + } +} -- GitLab