[BUGFIX] PromQL: fix slice indexing bug in info function (#17135)
* [BUGFIX] PromQL: fix slice indexing bug in info function --------- Signed-off-by: Linas Medziunas <linas.medziunas@gmail.com> Signed-off-by: Linas Medžiūnas <linasm@users.noreply.github.com> Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
parent
43c1535bdf
commit
5c2e43f09c
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
* [BUGFIX] OTLP receiver: Generate `target_info` samples between the earliest and latest samples per resource. #16737
|
* [BUGFIX] OTLP receiver: Generate `target_info` samples between the earliest and latest samples per resource. #16737
|
||||||
* [BUGFIX] Config: Infer escaping scheme when scrape config validation scheme is set.
|
* [BUGFIX] Config: Infer escaping scheme when scrape config validation scheme is set.
|
||||||
|
* [BUGFIX] PromQL: Fix info function on churning series. #17135
|
||||||
|
|
||||||
## 3.5.0 / 2025-07-14
|
## 3.5.0 / 2025-07-14
|
||||||
|
|
||||||
|
|
|
@ -258,10 +258,10 @@ func (ev *evaluator) combineWithInfoSeries(ctx context.Context, mat, infoMat Mat
|
||||||
baseSigs = append(baseSigs, sigs)
|
baseSigs = append(baseSigs, sigs)
|
||||||
}
|
}
|
||||||
|
|
||||||
infoSigs := make([]string, 0, len(infoMat))
|
infoSigs := make(map[uint64]string, len(infoMat))
|
||||||
for _, s := range infoMat {
|
for _, s := range infoMat {
|
||||||
name := s.Metric.Map()[labels.MetricName]
|
name := s.Metric.Map()[labels.MetricName]
|
||||||
infoSigs = append(infoSigs, sigfs[name](s.Metric))
|
infoSigs[s.Metric.Hash()] = sigfs[name](s.Metric)
|
||||||
}
|
}
|
||||||
|
|
||||||
var warnings annotations.Annotations
|
var warnings annotations.Annotations
|
||||||
|
@ -331,7 +331,7 @@ func (ev *evaluator) combineWithInfoSeries(ctx context.Context, mat, infoMat Mat
|
||||||
|
|
||||||
// combineWithInfoVector combines base and info Vectors.
|
// combineWithInfoVector combines base and info Vectors.
|
||||||
// Base series in ignoreSeries are not combined.
|
// Base series in ignoreSeries are not combined.
|
||||||
func (ev *evaluator) combineWithInfoVector(base, info Vector, ignoreSeries map[int]struct{}, baseSigs []map[string]string, infoSigs []string, enh *EvalNodeHelper, dataLabelMatchers map[string][]*labels.Matcher) (Vector, error) {
|
func (ev *evaluator) combineWithInfoVector(base, info Vector, ignoreSeries map[int]struct{}, baseSigs []map[string]string, infoSigs map[uint64]string, enh *EvalNodeHelper, dataLabelMatchers map[string][]*labels.Matcher) (Vector, error) {
|
||||||
if len(base) == 0 {
|
if len(base) == 0 {
|
||||||
return nil, nil // Short-circuit: nothing is going to match.
|
return nil, nil // Short-circuit: nothing is going to match.
|
||||||
}
|
}
|
||||||
|
@ -343,14 +343,14 @@ func (ev *evaluator) combineWithInfoVector(base, info Vector, ignoreSeries map[i
|
||||||
clear(enh.rightSigs)
|
clear(enh.rightSigs)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, s := range info {
|
for _, s := range info {
|
||||||
if s.H != nil {
|
if s.H != nil {
|
||||||
ev.error(errors.New("info sample should be float"))
|
ev.error(errors.New("info sample should be float"))
|
||||||
}
|
}
|
||||||
// We encode original info sample timestamps via the float value.
|
// We encode original info sample timestamps via the float value.
|
||||||
origT := int64(s.F)
|
origT := int64(s.F)
|
||||||
|
|
||||||
sig := infoSigs[i]
|
sig := infoSigs[s.Metric.Hash()]
|
||||||
if existing, exists := enh.rightSigs[sig]; exists {
|
if existing, exists := enh.rightSigs[sig]; exists {
|
||||||
// We encode original info sample timestamps via the float value.
|
// We encode original info sample timestamps via the float value.
|
||||||
existingOrigT := int64(existing.F)
|
existingOrigT := int64(existing.F)
|
||||||
|
@ -362,8 +362,8 @@ func (ev *evaluator) combineWithInfoVector(base, info Vector, ignoreSeries map[i
|
||||||
enh.rightSigs[sig] = s
|
enh.rightSigs[sig] = s
|
||||||
default:
|
default:
|
||||||
// The two info samples have the same timestamp - conflict.
|
// The two info samples have the same timestamp - conflict.
|
||||||
name := s.Metric.Map()[labels.MetricName]
|
ev.errorf("found duplicate series for info metric: existing %s @ %d, new %s @ %d",
|
||||||
ev.errorf("found duplicate series for info metric %s", name)
|
existing.Metric.String(), existingOrigT, s.Metric.String(), origT)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enh.rightSigs[sig] = s
|
enh.rightSigs[sig] = s
|
||||||
|
|
|
@ -136,5 +136,20 @@ eval range from 1m to 4m step 1m info(metric @ 60)
|
||||||
# offset operator works also with info.
|
# offset operator works also with info.
|
||||||
eval range from 1m to 4m step 1m info(metric offset 1m)
|
eval range from 1m to 4m step 1m info(metric offset 1m)
|
||||||
metric{data="info", instance="a", job="1", label="value"} 0 0 2 3
|
metric{data="info", instance="a", job="1", label="value"} 0 0 2 3
|
||||||
|
|
||||||
|
clear
|
||||||
|
|
||||||
|
load 1m
|
||||||
|
data_metric{instance="a", job="work"} 10 20 30
|
||||||
|
data_metric{instance="b", job="work"} 11 21 31
|
||||||
|
info_metric{instance="b", job="work", state="stopped"} 1 1 _
|
||||||
|
info_metric{instance="b", job="work", state="running"} _ _ 1
|
||||||
|
info_metric{instance="a", job="work", state="running"} 1 1 1
|
||||||
|
|
||||||
|
eval range from 0 to 2m step 1m info(data_metric, {__name__="info_metric"})
|
||||||
|
data_metric{instance="a", job="work", state="running"} 10 20 30
|
||||||
|
data_metric{instance="b", job="work", state="stopped"} 11 21 _
|
||||||
|
data_metric{instance="b", job="work", state="running"} _ _ 31
|
||||||
|
|
||||||
`, engine)
|
`, engine)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue