| 
									
										
										
										
											2024-10-16 20:52:11 +08:00
										 |  |  | // Copyright 2024 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package promql_test | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/promql/promqltest" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The "info" function is experimental. This is why we write those tests here for now instead of promqltest/testdata/info.test.
 | 
					
						
							|  |  |  | func TestInfo(t *testing.T) { | 
					
						
							|  |  |  | 	engine := promqltest.NewTestEngine(t, false, 0, promqltest.DefaultMaxSamplesPerQuery) | 
					
						
							|  |  |  | 	promqltest.RunTest(t, ` | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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", build_data=~".+"}) | 
					
						
							|  |  |  |   build_info{instance="a", job="1", build_data="build"} 1 1 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2025-09-05 20:46:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-16 20:52:11 +08:00
										 |  |  | `, engine) | 
					
						
							|  |  |  | } |