Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better combines stats in ingesters #9474

Merged
merged 1 commit into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions pkg/ingester/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ func (i *instance) GetStats(ctx context.Context, req *logproto.IndexStatsRequest
// Consider streams which overlap our time range
if shouldConsiderStream(s, from, through) {
s.chunkMtx.RLock()
res.Streams++
var hasChunkOverlap bool
for _, chk := range s.chunks {
// Consider chunks which overlap our time range
// and haven't been flushed.
Expand All @@ -584,12 +584,17 @@ func (i *instance) GetStats(ctx context.Context, req *logproto.IndexStatsRequest
chkFrom, chkThrough := chk.chunk.Bounds()

if !chk.flushed.Equal(zeroValueTime) && from.Before(chkThrough) && through.After(chkFrom) {
Copy link
Contributor

@DylanGuedes DylanGuedes May 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double checking: shouldn't here be from.Before(chkThrough) || through.After(chkFrom) as it is a partial overlap?
Ex:
edit: ok I suck at doing ascii art

	//       From ______ chkFrom____Through____chkThrough|             
	//       │____________|_______ Chunk _____________│       

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from.Before(chkThrough) && through.After(chkFrom) can only be true when there's some degree of overlap with the time range and chunk. In your ascii example that holds true. If we used || instead of &&, it would include potentially non-overlapping ranges.

hasChunkOverlap = true
res.Chunks++
res.Entries += uint64(chk.chunk.Size())
res.Bytes += uint64(chk.chunk.UncompressedSize())
factor := util.GetFactorOfTime(from.UnixNano(), through.UnixNano(), chkFrom.UnixNano(), chkThrough.UnixNano())
res.Entries += uint64(factor * float64(chk.chunk.Size()))
res.Bytes += uint64(factor * float64(chk.chunk.UncompressedSize()))
}

}
if hasChunkOverlap {
res.Streams++
}
s.chunkMtx.RUnlock()
}
return nil
Expand Down
27 changes: 4 additions & 23 deletions pkg/storage/stores/tsdb/index/chunk.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (

"github.com/prometheus/common/model"

"github.com/grafana/loki/pkg/util"
"github.com/grafana/loki/pkg/util/encoding"
"github.com/grafana/loki/pkg/util/math"
)

// Meta holds information about a chunk of data.
Expand Down Expand Up @@ -245,27 +245,8 @@ func (cs *ChunkStats) addRaw(chunks int, kb, entries uint32) {
}

func (cs *ChunkStats) AddChunk(chk *ChunkMeta, from, through int64) {
// Assuming entries and bytes are evenly distributed in the chunk,
// We will take the proportional number of entries and number of bytes
// if (chk.MinTime < from) and/or (chk.MaxTime > through).
//
// MinTime From Through MaxTime
// ┌────────┬─────────────────┬────────┐
// │ * Chunk * │
// └────────┴─────────────────┴────────┘
// ▲ A | C | B ▲
// └───────────────────────────────────┘
// T = MinTime - MaxTime
//
// We want to get the percentage of time that fits into C
// to use it as a factor to get the amount of bytes and entries
// factor = C = (T - (A + B)) / T = (chunkTime - (leadingTime + trailingTime)) / chunkTime
chunkTime := chk.MaxTime - chk.MinTime
leadingTime := math.Max64(0, from-chk.MinTime)
trailingTime := math.Max64(0, chk.MaxTime-through)
factor := float32(chunkTime-(leadingTime+trailingTime)) / float32(chunkTime)

kb := uint32(float32(chk.KB) * factor)
entries := uint32(float32(chk.Entries) * factor)
factor := util.GetFactorOfTime(from, through, chk.MinTime, chk.MaxTime)
kb := uint32(float64(chk.KB) * factor)
entries := uint32(float64(chk.Entries) * factor)
cs.addRaw(1, kb, entries)
}