load 5m metric{instance="a", job="1", label="value"} 0 1 2 metric_not_matching_target_info{instance="a", job="2", label="value"} 0 1 2 metric_with_overlapping_label{instance="a", job="1", label="value", data="base"} 0 1 2 target_info{instance="a", job="1", data="info", another_data="another info"} 1 1 1 build_info{instance="a", job="1", build_data="build"} 1 1 1 # Include one info metric data label. eval range from 0m to 10m step 5m info(metric, {data=~".+"}) metric{data="info", instance="a", job="1", label="value"} 0 1 2 # Include all info metric data labels. eval range from 0m to 10m step 5m info(metric) metric{data="info", instance="a", job="1", label="value", another_data="another info"} 0 1 2 # Try including all info metric data labels, but non-matching identifying labels. eval range from 0m to 10m step 5m info(metric_not_matching_target_info) metric_not_matching_target_info{instance="a", job="2", label="value"} 0 1 2 # Try including a certain info metric data label with a non-matching matcher not accepting empty labels. # Metric is ignored, due there being a data label matcher not matching empty labels, # and there being no info series matches. eval range from 0m to 10m step 5m info(metric, {non_existent=~".+"}) # Include a certain info metric data label together with a non-matching matcher accepting empty labels. # Since the non_existent matcher matches empty labels, it's simply ignored when there's no match. # XXX: This case has to include a matcher not matching empty labels, due the PromQL limitation # that vector selectors have to contain at least one matcher not accepting empty labels. # We might need another construct than vector selector to get around this limitation. eval range from 0m to 10m step 5m info(metric, {data=~".+", non_existent=~".*"}) metric{data="info", instance="a", job="1", label="value"} 0 1 2 # Info series data labels overlapping with those of base series are ignored. 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 # Try to include all data labels from a non-existent info metric. eval range from 0m to 10m step 5m info(metric, {__name__="non_existent"}) metric{instance="a", job="1", label="value"} 0 1 2 # Try to include a certain data label from a non-existent info metric. eval range from 0m to 10m step 5m info(metric, {__name__="non_existent", data=~".+"}) # Include data labels from build_info. eval range from 0m to 10m step 5m info(metric, {__name__="build_info"}) metric{instance="a", job="1", label="value", build_data="build"} 0 1 2 # Include data labels from build_info and target_info. eval range from 0m to 10m step 5m info(metric, {__name__=~".+_info"}) metric{instance="a", job="1", label="value", build_data="build", data="info", another_data="another info"} 0 1 2 # Info metrics themselves are ignored when it comes to enriching with info metric data labels. eval range from 0m to 10m step 5m info(build_info, {__name__=~".+_info", another_data=~".+"}) build_info{instance="a", job="1", build_data="build"} 1 1 1 # Info metrics themselves are ignored when it comes to enriching with info metric data labels. eval range from 0m to 10m step 5m info(build_info, {__name__=~".+_info"}) build_info{instance="a", job="1", build_data="build"} 1 1 1 clear load 5m metric{instance="a", job="1", label="value"} 0 1 2 target_info{instance="a", job="1", data="info", another_data="another info"} 1 1 1 build_info{instance="a", job="1", build_data="build"} 1 1 1 target_build{instance="a", job="1", build_data="build"} 1 1 1 # Multiple positive __name__ matchers. eval range from 0m to 10m step 5m info(metric, {__name__=~"target_.+", __name__=~".+_info"}) metric{instance="a", job="1", label="value", data="info", another_data="another info"} 0 1 2 # A positive and a negative __name__ matcher. eval range from 0m to 10m step 5m info(metric, {__name__=~".+_info", __name__!~".*build.*"}) metric{instance="a", job="1", label="value", data="info", another_data="another info"} 0 1 2 clear # Overlapping target_info series. load 5m metric{instance="a", job="1", label="value"} 0 1 2 target_info{instance="a", job="1", data="info", another_data="another info"} 1 1 _ target_info{instance="a", job="1", data="updated info", another_data="another info"} _ _ 1 # Conflicting info series are resolved through picking the latest sample. eval range from 0m to 10m step 5m info(metric) metric{data="info", instance="a", job="1", label="value", another_data="another info"} 0 1 _ metric{data="updated info", instance="a", job="1", label="value", another_data="another info"} _ _ 2 clear # Non-overlapping target_info series. load 5m metric{instance="a", job="1", label="value"} 0 1 2 target_info{instance="a", job="1", data="info"} 1 1 stale target_info{instance="a", job="1", data="updated info"} _ _ 1 # Include info metric data labels from a metric which data labels change over time. eval range from 0m to 10m step 5m info(metric) metric{data="info", instance="a", job="1", label="value"} 0 1 _ metric{data="updated info", instance="a", job="1", label="value"} _ _ 2 clear # Info series selector matches histogram series, info metrics should be float type. load 5m metric{instance="a", job="1", label="value"} 0 1 2 histogram{instance="a", job="1"} {{schema:1 sum:3 count:22 buckets:[5 10 7]}} eval_fail range from 0m to 10m step 5m info(metric, {__name__="histogram"}) clear # Series with skipped scrape. load 1m metric{instance="a", job="1", label="value"} 0 _ 2 3 4 target_info{instance="a", job="1", data="info"} 1 _ 1 1 1 # Lookback works also for the info series. eval range from 1m to 4m step 1m info(metric) metric{data="info", instance="a", job="1", label="value"} 0 2 3 4 # @ operator works also with info. # Note that we pick the timestamp missing a sample, lookback should pick previous sample. eval range from 1m to 4m step 1m info(metric @ 60) metric{data="info", instance="a", job="1", label="value"} 0 0 0 0 # offset operator works also with info. 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 clear # info_metric churn: 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 clear # data_metric churn: load 1m data_metric{instance="a", job="work"} 10 20 stale data_metric{instance="b", job="work"} 11 21 31 data_metric{instance="a", job="work", label="new"} _ _ 30 info_metric{instance="b", job="work", state="stopped"} 1 1 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 _ data_metric{instance="b", job="work", state="stopped"} 11 21 31 data_metric{instance="a", job="work", state="running", label="new"} _ _ 30 eval range from 0 to 2m step 1m info({job="work"}, {__name__="info_metric"}) data_metric{instance="a", job="work", state="running"} 10 20 _ data_metric{instance="b", job="work", state="stopped"} 11 21 31 data_metric{instance="a", job="work", state="running", label="new"} _ _ 30 info_metric{instance="b", job="work", state="stopped"} 1 1 1 info_metric{instance="a", job="work", state="running"} 1 1 1 clear load 1m data_metric{} 1 2 3 eval range from 0 to 2m step 1m info(data_metric, {__name__="info_metric"}) data_metric{} 1 2 3 clear load 1m data_metric{} 1 2 3 data_metric{instance="a"} 4 5 6 eval range from 0 to 2m step 1m info(data_metric, {__name__="info_metric"}) data_metric{} 1 2 3 data_metric{instance="a"} 4 5 6 clear load 1m data_metric{} 1 2 3 data_metric{instance="a"} 4 5 6 data_metric{job="1"} 7 8 9 data_metric{instance="a", job="1"} 10 20 30 eval range from 0 to 2m step 1m info(data_metric, {__name__="info_metric"}) data_metric{} 1 2 3 data_metric{instance="a"} 4 5 6 data_metric{job="1"} 7 8 9 data_metric{instance="a", job="1"} 10 20 30