fix: native histogram: Simplify and fix addExemplar
mdIdx was redundant when len(exemplars)>1, so got rid of it, rIdx is enough. Don't compare timestamp of incoming exemplar to timestamp of minimal distance exemplar. Most of the time the incoming exemplar will be newer. And if not, the previous code just replaced an exemplar one index after the minimal distance exemplar. Which had an index out of range bug, plus is essentially random. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
This commit is contained in:
parent
dc819ceb1b
commit
dc8e9a4d8a
|
@ -1705,17 +1705,23 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(n.exemplars) == 1 {
|
||||||
|
// When the number of exemplars is 1, then
|
||||||
|
// replace the existing exemplar with the new exemplar.
|
||||||
|
n.exemplars[0] = e
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// From this point on, the number of exemplars is greater than 1.
|
||||||
|
|
||||||
// When the number of exemplars exceeds the limit, remove one exemplar.
|
// When the number of exemplars exceeds the limit, remove one exemplar.
|
||||||
var (
|
var (
|
||||||
rIdx int // The index where to remove the old exemplar.
|
|
||||||
|
|
||||||
ot = time.Now() // Oldest timestamp seen.
|
ot = time.Now() // Oldest timestamp seen.
|
||||||
otIdx = -1 // Index of the exemplar with the oldest timestamp.
|
otIdx = -1 // Index of the exemplar with the oldest timestamp.
|
||||||
|
|
||||||
md = -1.0 // Logarithm of the delta of the closest pair of exemplars.
|
md = -1.0 // Logarithm of the delta of the closest pair of exemplars.
|
||||||
mdIdx = -1 // Index of the older exemplar within the closest pair.
|
rIdx = -1 // Index of the older exemplar within the closest pair and where we need to insert the new exemplar.
|
||||||
cLog float64 // Logarithm of the current exemplar.
|
cLog float64 // Logarithm of the current exemplar.
|
||||||
pLog float64 // Logarithm of the previous exemplar.
|
pLog float64 // Logarithm of the previous exemplar.
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, exemplar := range n.exemplars {
|
for i, exemplar := range n.exemplars {
|
||||||
|
@ -1726,7 +1732,7 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the index at which to insert new the exemplar.
|
// Find the index at which to insert new the exemplar.
|
||||||
if *e.Value <= *exemplar.Value && nIdx == -1 {
|
if nIdx == -1 && *e.Value <= *exemplar.Value {
|
||||||
nIdx = i
|
nIdx = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1738,11 +1744,13 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
|
||||||
}
|
}
|
||||||
diff := math.Abs(cLog - pLog)
|
diff := math.Abs(cLog - pLog)
|
||||||
if md == -1 || diff < md {
|
if md == -1 || diff < md {
|
||||||
|
// The closest exemplar pair is this: |exemplar.[i] - n.exemplars[i-1].Value| is minimal.
|
||||||
|
// Choose the exemplar with the older timestamp for replacement.
|
||||||
md = diff
|
md = diff
|
||||||
if n.exemplars[i].Timestamp.AsTime().Before(n.exemplars[i-1].Timestamp.AsTime()) {
|
if n.exemplars[i].Timestamp.AsTime().Before(n.exemplars[i-1].Timestamp.AsTime()) {
|
||||||
mdIdx = i
|
rIdx = i
|
||||||
} else {
|
} else {
|
||||||
mdIdx = i - 1
|
rIdx = i - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1753,8 +1761,11 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
|
||||||
if nIdx == -1 {
|
if nIdx == -1 {
|
||||||
nIdx = len(n.exemplars)
|
nIdx = len(n.exemplars)
|
||||||
}
|
}
|
||||||
|
// Here, we have the following relationships:
|
||||||
|
// n.exemplars[nIdx-1].Value < e.Value <= n.exemplars[nIdx].Value
|
||||||
|
|
||||||
if otIdx != -1 && e.Timestamp.AsTime().Sub(ot) > n.ttl {
|
if otIdx != -1 && e.Timestamp.AsTime().Sub(ot) > n.ttl {
|
||||||
|
// If the oldest exemplar has expired, then replace it with the new exemplar.
|
||||||
rIdx = otIdx
|
rIdx = otIdx
|
||||||
} else {
|
} else {
|
||||||
// In the previous for loop, when calculating the closest pair of exemplars,
|
// In the previous for loop, when calculating the closest pair of exemplars,
|
||||||
|
@ -1764,23 +1775,22 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
|
||||||
if nIdx > 0 {
|
if nIdx > 0 {
|
||||||
diff := math.Abs(elog - math.Log(n.exemplars[nIdx-1].GetValue()))
|
diff := math.Abs(elog - math.Log(n.exemplars[nIdx-1].GetValue()))
|
||||||
if diff < md {
|
if diff < md {
|
||||||
|
// The closest exemplar pair is this: |e.Value - n.exemplars[nIdx-1].Value| is minimal.
|
||||||
|
// Assume that the exemplar we are inserting has a newer timestamp. This is not always
|
||||||
|
// true, due to concurrency, but it's a good enough approximation.
|
||||||
md = diff
|
md = diff
|
||||||
mdIdx = nIdx
|
rIdx = nIdx - 1
|
||||||
if n.exemplars[nIdx-1].Timestamp.AsTime().Before(e.Timestamp.AsTime()) {
|
|
||||||
mdIdx = nIdx - 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if nIdx < len(n.exemplars) {
|
if nIdx < len(n.exemplars) {
|
||||||
diff := math.Abs(math.Log(n.exemplars[nIdx].GetValue()) - elog)
|
diff := math.Abs(math.Log(n.exemplars[nIdx].GetValue()) - elog)
|
||||||
if diff < md {
|
if diff < md {
|
||||||
mdIdx = nIdx
|
// The closest exemplar pair is this: |n.exemplars[nIdx].Value - e.Value| is minimal.
|
||||||
if n.exemplars[nIdx].Timestamp.AsTime().Before(e.Timestamp.AsTime()) {
|
// Assume that the exemplar we are inserting has a newer timestamp. This is not always
|
||||||
mdIdx = nIdx
|
// true, due to concurrency, but it's a good enough approximation.
|
||||||
}
|
rIdx = nIdx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rIdx = mdIdx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the slice according to rIdx and nIdx.
|
// Adjust the slice according to rIdx and nIdx.
|
||||||
|
|
Loading…
Reference in New Issue