promql: fix info() returning empty when filtering by overlapping labels (#17817)

When filtering by a label that exists on both the input metric and
target_info (e.g., info(metric, {host_name="orbstack"}) where host_name
exists on both), the function incorrectly returned empty results.

The bug was in combineWithInfoVector: when no new labels were added
(because they all overlapped with base metric labels), the code entered
the "no match" filtering block even though an info series WAS matched.

The fix checks len(seenInfoMetrics) == 0 to correctly identify when no
info series matched. If an info series matched (seenInfoMetrics is
non-empty), the series is kept even if no new labels were added.

Fixes #17813

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
Arve Knudsen 2026-01-09 10:04:37 +01:00 committed by GitHub
parent 14de1eb043
commit 16703766f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 3 deletions

View file

@ -424,9 +424,10 @@ func (ev *evaluator) combineWithInfoVector(base, info Vector, ignoreSeries map[u
}
infoLbls := enh.lb.Labels()
if infoLbls.Len() == 0 {
// If there's at least one data label matcher not matching the empty string,
// we have to ignore this series as there are no matching info series.
if len(seenInfoMetrics) == 0 {
// No info series matched this base series. If there's at least one data
// label matcher not matching the empty string, we have to ignore this
// series as there are no matching info series.
allMatchersMatchEmpty := true
for _, ms := range dataLabelMatchers {
for _, m := range ms {

View file

@ -34,6 +34,22 @@ eval range from 0m to 10m step 5m info(metric, {data=~".+", non_existent=~".*"})
eval range from 0m to 10m step 5m info(metric_with_overlapping_label)
metric_with_overlapping_label{data="base", instance="a", job="1", label="value", another_data="another info"} 0 1 2
# Filtering by a label that exists on both base metric and target_info should work.
# This is a regression test for https://github.com/prometheus/prometheus/issues/17813.
# Note: data="base" on base metric, data="info" on target_info - the filter matches target_info.
eval range from 0m to 10m step 5m info(metric_with_overlapping_label, {data="info"})
metric_with_overlapping_label{data="base", instance="a", job="1", label="value"} 0 1 2
# Filtering by a label that exists on both base metric and target_info with regex should work.
eval range from 0m to 10m step 5m info(metric_with_overlapping_label, {data=~".+"})
metric_with_overlapping_label{data="base", instance="a", job="1", label="value"} 0 1 2
# Filtering by a label that exists on both base metric and target_info with same value.
# The selector matches the target_info, and the join succeeds via identifying labels.
# Note: Only the instance label is considered for inclusion, but it already exists on base.
eval range from 0m to 10m step 5m info(metric_with_overlapping_label, {instance="a"})
metric_with_overlapping_label{data="base", instance="a", job="1", label="value"} 0 1 2
# Include data labels from target_info specifically.
eval range from 0m to 10m step 5m info(metric, {__name__="target_info"})
metric{data="info", instance="a", job="1", label="value", another_data="another info"} 0 1 2