promql: Remove interpolation of vector values.
The current behaviour produces values that are not from rules or scrapes. So if for example I have a boolean 0/1 it can be returned as 0.2344589. This prevents a number of advanced use cases, introduces race conditions and can produce misleading graphs.
This commit is contained in:
parent
25a8bd50a5
commit
fb585e4591
|
@ -723,7 +723,7 @@ func (ev *evaluator) vectorSelector(node *VectorSelector) Vector {
|
||||||
vec := Vector{}
|
vec := Vector{}
|
||||||
for fp, it := range node.iterators {
|
for fp, it := range node.iterators {
|
||||||
sampleCandidates := it.ValueAtTime(ev.Timestamp.Add(-node.Offset))
|
sampleCandidates := it.ValueAtTime(ev.Timestamp.Add(-node.Offset))
|
||||||
samplePair := chooseClosestSample(sampleCandidates, ev.Timestamp.Add(-node.Offset))
|
samplePair := chooseClosestBefore(sampleCandidates, ev.Timestamp.Add(-node.Offset))
|
||||||
if samplePair != nil {
|
if samplePair != nil {
|
||||||
vec = append(vec, &Sample{
|
vec = append(vec, &Sample{
|
||||||
Metric: node.metrics[fp],
|
Metric: node.metrics[fp],
|
||||||
|
@ -1173,67 +1173,21 @@ func shouldDropMetricName(op itemType) bool {
|
||||||
// series is considered stale.
|
// series is considered stale.
|
||||||
var StalenessDelta = 5 * time.Minute
|
var StalenessDelta = 5 * time.Minute
|
||||||
|
|
||||||
// chooseClosestSample chooses the closest sample of a list of samples
|
// chooseClosestBefore chooses the closest sample of a list of samples
|
||||||
// surrounding a given target time. If samples are found both before and after
|
// before or at a given target time.
|
||||||
// the target time, the sample value is interpolated between these. Otherwise,
|
func chooseClosestBefore(samples []model.SamplePair, timestamp model.Time) *model.SamplePair {
|
||||||
// the single closest sample is returned verbatim.
|
|
||||||
func chooseClosestSample(samples []model.SamplePair, timestamp model.Time) *model.SamplePair {
|
|
||||||
var closestBefore *model.SamplePair
|
|
||||||
var closestAfter *model.SamplePair
|
|
||||||
for _, candidate := range samples {
|
for _, candidate := range samples {
|
||||||
delta := candidate.Timestamp.Sub(timestamp)
|
delta := candidate.Timestamp.Sub(timestamp)
|
||||||
// Samples before target time.
|
// Samples before or at target time.
|
||||||
if delta < 0 {
|
if delta <= 0 {
|
||||||
// Ignore samples outside of staleness policy window.
|
// Ignore samples outside of staleness policy window.
|
||||||
if -delta > StalenessDelta {
|
if -delta > StalenessDelta {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Ignore samples that are farther away than what we've seen before.
|
return &candidate
|
||||||
if closestBefore != nil && candidate.Timestamp.Before(closestBefore.Timestamp) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sample := candidate
|
|
||||||
closestBefore = &sample
|
|
||||||
}
|
|
||||||
|
|
||||||
// Samples after target time.
|
|
||||||
if delta >= 0 {
|
|
||||||
// Ignore samples outside of staleness policy window.
|
|
||||||
if delta > StalenessDelta {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Ignore samples that are farther away than samples we've seen before.
|
|
||||||
if closestAfter != nil && candidate.Timestamp.After(closestAfter.Timestamp) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sample := candidate
|
|
||||||
closestAfter = &sample
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
switch {
|
|
||||||
case closestBefore != nil && closestAfter != nil:
|
|
||||||
return interpolateSamples(closestBefore, closestAfter, timestamp)
|
|
||||||
case closestBefore != nil:
|
|
||||||
return closestBefore
|
|
||||||
default:
|
|
||||||
return closestAfter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateSamples interpolates a value at a target time between two
|
|
||||||
// provided sample pairs.
|
|
||||||
func interpolateSamples(first, second *model.SamplePair, timestamp model.Time) *model.SamplePair {
|
|
||||||
dv := second.Value - first.Value
|
|
||||||
dt := second.Timestamp.Sub(first.Timestamp)
|
|
||||||
|
|
||||||
dDt := dv / model.SampleValue(dt)
|
|
||||||
offset := model.SampleValue(timestamp.Sub(first.Timestamp))
|
|
||||||
|
|
||||||
return &model.SamplePair{
|
|
||||||
Value: first.Value + (offset * dDt),
|
|
||||||
Timestamp: timestamp,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A queryGate controls the maximum number of concurrently running and waiting queries.
|
// A queryGate controls the maximum number of concurrently running and waiting queries.
|
||||||
|
|
Loading…
Reference in New Issue