mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
fix le buckets when adjacent vmrange is empty (#4021)
There is a bug here where if you have a single bucket like: foo{vmrange="4.084e+02...4.642e+02"} 2 123 The expected output is three le encoded buckets like: foo{le="4.084e+02"} 0 123 foo{le="4.642e+02"} 2 123 foo{le="+Inf"} 2 123 This correctly encodes the start and end of the vmrange. If however, the input contains the previous bucket, and that bucket is empty then you only get the end le and +Inf out currently, i.e: foo{vmrange="7.743e+05...8.799e+05"} 5 123 foo{vmrange="6.813e+05...7.743e+05"} 0 123 results in: foo{le="8.799e+05"} 5 123 foo{le="+Inf"} 5 123 This causes issues when you go to compute a quantile because this means that the assumed lower bound of the buckets is 0 and this we interpolate between 0->end rather than the vmrange start->end as expected.
This commit is contained in:
parent
87769b36d1
commit
b3ee33eb8e
2 changed files with 27 additions and 1 deletions
|
@ -548,14 +548,25 @@ func vmrangeBucketsToLE(tss []*timeseries) []*timeseries {
|
||||||
sort.Slice(xss, func(i, j int) bool { return xss[i].end < xss[j].end })
|
sort.Slice(xss, func(i, j int) bool { return xss[i].end < xss[j].end })
|
||||||
xssNew := make([]x, 0, len(xss)+2)
|
xssNew := make([]x, 0, len(xss)+2)
|
||||||
var xsPrev x
|
var xsPrev x
|
||||||
|
hasNonEmpty := false
|
||||||
uniqTs := make(map[string]*timeseries, len(xss))
|
uniqTs := make(map[string]*timeseries, len(xss))
|
||||||
for _, xs := range xss {
|
for _, xs := range xss {
|
||||||
ts := xs.ts
|
ts := xs.ts
|
||||||
if isZeroTS(ts) {
|
if isZeroTS(ts) {
|
||||||
// Skip time series with zeros. They are substituted by xssNew below.
|
|
||||||
xsPrev = xs
|
xsPrev = xs
|
||||||
|
|
||||||
|
if uniqTs[xs.endStr] == nil {
|
||||||
|
uniqTs[xs.endStr] = xs.ts
|
||||||
|
xssNew = append(xssNew, x{
|
||||||
|
endStr: xs.endStr,
|
||||||
|
end: xs.end,
|
||||||
|
ts: copyTS(ts, xs.endStr),
|
||||||
|
})
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasNonEmpty = true
|
||||||
if xs.start != xsPrev.end && uniqTs[xs.startStr] == nil {
|
if xs.start != xsPrev.end && uniqTs[xs.startStr] == nil {
|
||||||
uniqTs[xs.startStr] = xs.ts
|
uniqTs[xs.startStr] = xs.ts
|
||||||
xssNew = append(xssNew, x{
|
xssNew = append(xssNew, x{
|
||||||
|
@ -575,6 +586,12 @@ func vmrangeBucketsToLE(tss []*timeseries) []*timeseries {
|
||||||
}
|
}
|
||||||
xsPrev = xs
|
xsPrev = xs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !hasNonEmpty {
|
||||||
|
xssNew = []x{}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if !math.IsInf(xsPrev.end, 1) && !isZeroTS(xsPrev.ts) {
|
if !math.IsInf(xsPrev.end, 1) && !isZeroTS(xsPrev.ts) {
|
||||||
xssNew = append(xssNew, x{
|
xssNew = append(xssNew, x{
|
||||||
endStr: "+Inf",
|
endStr: "+Inf",
|
||||||
|
|
|
@ -78,6 +78,15 @@ foo{le="+Inf"} 1.23 456`,
|
||||||
foo{le="+Inf"} 5.3 0`,
|
foo{le="+Inf"} 5.3 0`,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Adjacent empty vmrange bucket
|
||||||
|
f(
|
||||||
|
`foo{vmrange="7.743e+05...8.799e+05"} 5 123
|
||||||
|
foo{vmrange="6.813e+05...7.743e+05"} 0 123`,
|
||||||
|
`foo{le="7.743e+05"} 0 123
|
||||||
|
foo{le="8.799e+05"} 5 123
|
||||||
|
foo{le="+Inf"} 5 123`,
|
||||||
|
)
|
||||||
|
|
||||||
// Multiple non-empty vmrange buckets
|
// Multiple non-empty vmrange buckets
|
||||||
f(
|
f(
|
||||||
`foo{vmrange="4.084e+02...4.642e+02"} 2 123
|
`foo{vmrange="4.084e+02...4.642e+02"} 2 123
|
||||||
|
|
Loading…
Reference in a new issue