diff --git a/go.mod b/go.mod index 7c514e8a26..945d0a2116 100644 --- a/go.mod +++ b/go.mod @@ -86,7 +86,7 @@ require ( github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.67.5 - github.com/prometheus/prometheus v0.310.1-0.20260227151745-3b1d65816f22 + github.com/prometheus/prometheus v0.310.1-0.20260302160042-1751685dd4f6 github.com/redis/go-redis/v9 v9.18.0 github.com/segmentio/fasthash v1.0.3 github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c diff --git a/go.sum b/go.sum index 7010a51dad..dd8b12fd77 100644 --- a/go.sum +++ b/go.sum @@ -1043,8 +1043,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= -github.com/prometheus/prometheus v0.310.1-0.20260227151745-3b1d65816f22 h1:25UDT8ndgcAHZTN1SdLtlcnmNEFjMfHIEMTQdim99IU= -github.com/prometheus/prometheus v0.310.1-0.20260227151745-3b1d65816f22/go.mod h1:cwgOGTBad7xXbKQBCJVfHKe6qjW7fHF6f+IQNzzISZ8= +github.com/prometheus/prometheus v0.310.1-0.20260302160042-1751685dd4f6 h1:YeKVdoknWYKHvcrw1/QNrqAnaQdcs1rMbQ9i575HowM= +github.com/prometheus/prometheus v0.310.1-0.20260302160042-1751685dd4f6/go.mod h1:cwgOGTBad7xXbKQBCJVfHKe6qjW7fHF6f+IQNzzISZ8= github.com/prometheus/sigv4 v0.4.1 h1:EIc3j+8NBea9u1iV6O5ZAN8uvPq2xOIUPcqCTivHuXs= github.com/prometheus/sigv4 v0.4.1/go.mod h1:eu+ZbRvsc5TPiHwqh77OWuCnWK73IdkETYY46P4dXOU= github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg= diff --git a/vendor/github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go b/vendor/github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go index 678f287ef5..6bbbafe8ea 100644 --- a/vendor/github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go +++ b/vendor/github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go @@ -194,7 +194,7 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(any) error) error { foundSelectorRoles := make(map[Role]struct{}) allowedSelectors := map[Role][]string{ - RolePod: {string(RolePod)}, + RolePod: {string(RolePod), string(RoleNode)}, RoleService: {string(RoleService)}, RoleEndpointSlice: {string(RolePod), string(RoleService), string(RoleEndpointSlice)}, RoleEndpoint: {string(RolePod), string(RoleService), string(RoleEndpoint)}, diff --git a/vendor/github.com/prometheus/prometheus/discovery/kubernetes/pod.go b/vendor/github.com/prometheus/prometheus/discovery/kubernetes/pod.go index 1fed78b3a7..05b778bb59 100644 --- a/vendor/github.com/prometheus/prometheus/discovery/kubernetes/pod.go +++ b/vendor/github.com/prometheus/prometheus/discovery/kubernetes/pod.go @@ -286,6 +286,19 @@ func (p *Pod) buildPod(pod *apiv1.Pod) *targetgroup.Group { return tg } + // Filter out pods scheduled on nodes that are not in the node store, as + // these were filtered out by node selectors. + if p.withNodeMetadata { + _, exists, err := p.nodeInf.GetStore().GetByKey(pod.Spec.NodeName) + if err != nil { + p.logger.Error("failed to get node from store", "node", pod.Spec.NodeName, "err", err) + return tg + } + if !exists { + return tg + } + } + tg.Labels = podLabels(pod) tg.Labels[namespaceLabel] = lv(pod.Namespace) if p.withNodeMetadata { diff --git a/vendor/github.com/prometheus/prometheus/discovery/manager.go b/vendor/github.com/prometheus/prometheus/discovery/manager.go index 3f2b2db652..9994e0bf74 100644 --- a/vendor/github.com/prometheus/prometheus/discovery/manager.go +++ b/vendor/github.com/prometheus/prometheus/discovery/manager.go @@ -475,6 +475,7 @@ func (m *Manager) allGroups() map[string][]*targetgroup.Group { for setName, v := range n { m.metrics.DiscoveredTargets.WithLabelValues(setName).Set(float64(v)) + m.metrics.LastUpdated.WithLabelValues(setName).SetToCurrentTime() } return tSets diff --git a/vendor/github.com/prometheus/prometheus/discovery/metrics.go b/vendor/github.com/prometheus/prometheus/discovery/metrics.go index 2a3734fb2d..3eefd3d0bb 100644 --- a/vendor/github.com/prometheus/prometheus/discovery/metrics.go +++ b/vendor/github.com/prometheus/prometheus/discovery/metrics.go @@ -26,6 +26,7 @@ type Metrics struct { ReceivedUpdates prometheus.Counter DelayedUpdates prometheus.Counter SentUpdates prometheus.Counter + LastUpdated *prometheus.GaugeVec } func NewManagerMetrics(registerer prometheus.Registerer, sdManagerName string) (*Metrics, error) { @@ -72,12 +73,22 @@ func NewManagerMetrics(registerer prometheus.Registerer, sdManagerName string) ( }, ) + m.LastUpdated = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "prometheus_sd_last_update_timestamp_seconds", + Help: "Timestamp of the last update sent to the SD consumers.", + ConstLabels: prometheus.Labels{"name": sdManagerName}, + }, + []string{"config"}, + ) + metrics := []prometheus.Collector{ m.FailedConfigs, m.DiscoveredTargets, m.ReceivedUpdates, m.DelayedUpdates, m.SentUpdates, + m.LastUpdated, } for _, collector := range metrics { @@ -97,4 +108,5 @@ func (m *Metrics) Unregister(registerer prometheus.Registerer) { registerer.Unregister(m.ReceivedUpdates) registerer.Unregister(m.DelayedUpdates) registerer.Unregister(m.SentUpdates) + registerer.Unregister(m.LastUpdated) } diff --git a/vendor/github.com/prometheus/prometheus/promql/engine.go b/vendor/github.com/prometheus/prometheus/promql/engine.go index 524ad807d1..cbbc27a2de 100644 --- a/vendor/github.com/prometheus/prometheus/promql/engine.go +++ b/vendor/github.com/prometheus/prometheus/promql/engine.go @@ -1965,9 +1965,7 @@ func (ev *evaluator) eval(ctx context.Context, expr parser.Expr) (parser.Value, // Matrix evaluation always returns the evaluation time, // so this function needs special handling when given // a vector selector. - arg := unwrapStepInvariantExpr(e.Args[0]) - vs, ok := arg.(*parser.VectorSelector) - if ok { + if vs, ok := e.Args[0].(*parser.VectorSelector); ok { return ev.rangeEvalTimestampFunctionOverVectorSelector(ctx, vs, call, e) } } @@ -4219,13 +4217,6 @@ func unwrapParenExpr(e *parser.Expr) { } } -func unwrapStepInvariantExpr(e parser.Expr) parser.Expr { - if p, ok := e.(*parser.StepInvariantExpr); ok { - return p.Expr - } - return e -} - // PreprocessExpr wraps all possible step invariant parts of the given expression with // StepInvariantExpr. It also resolves the preprocessors, evaluates duration expressions // into their numeric values and removes superfluous parenthesis on parameters to functions and aggregations. @@ -4284,15 +4275,24 @@ func preprocessExprHelper(expr parser.Expr, start, end time.Time) (isStepInvaria case *parser.Call: _, ok := AtModifierUnsafeFunctions[n.Func.Name] isStepInvariant := !ok + // A special case to allow timestamp() to be wrapped in a step invariant. + // timestamp() is considered AtModifierUnsafe, but it can be safe depending on its arguments. + // ie timestamp(metric @ 1) is step invariant, but timestamp(abs(metric @ 1)) is not. + isTimestampWithAllArgsStepInvariantSafe := n.Func.Name == "timestamp" shouldWrap := make([]bool, len(n.Args)) for i := range n.Args { unwrapParenExpr(&n.Args[i]) var argIsStepInvariant bool argIsStepInvariant, shouldWrap[i] = preprocessExprHelper(n.Args[i], start, end) isStepInvariant = isStepInvariant && argIsStepInvariant + + _, argIsVectorSelector := n.Args[i].(*parser.VectorSelector) + if !argIsStepInvariant || !argIsVectorSelector { + isTimestampWithAllArgsStepInvariantSafe = false + } } - if isStepInvariant { + if isStepInvariant || isTimestampWithAllArgsStepInvariantSafe { // The function and all arguments are step invariant. return true, true } diff --git a/vendor/github.com/prometheus/prometheus/promql/promqltest/testdata/at_modifier.test b/vendor/github.com/prometheus/prometheus/promql/promqltest/testdata/at_modifier.test index 194c877803..65f102d514 100644 --- a/vendor/github.com/prometheus/prometheus/promql/promqltest/testdata/at_modifier.test +++ b/vendor/github.com/prometheus/prometheus/promql/promqltest/testdata/at_modifier.test @@ -255,3 +255,56 @@ eval instant at 1111111s stdvar_over_time({__name__="up"}[1h:1m] @ 1111111) eval instant at 1111111s mad_over_time({__name__="up"}[1h:1m] @ 1111111) clear + +# Additional tests specific to timestamp() and @ modifier usage. +load 10s + metric 0+1x10 + metric_missing 0 _ 2 _ 4 _ 5 _ 6 + +# Return a vector where each sample is set to the metric value at T=11. +# Since T=11 falls within the [10s,20s) scrap window the sample value at T=10s is returned. +eval range from 0 to 60s step 10s metric @ 11 + {__name__="metric"} 1 1 1 1 1 1 1 + +eval range from 0 to 60s step 10s abs(metric @ 11) + {} 1 1 1 1 1 1 1 + +# Return a vector where each sample's value is set to the timestamp of each sample in the given metric series +eval range from 0 to 60s step 10s timestamp(metric) + {} 0 10 20 30 40 50 60 + +# Return a vector where each sample's value is set to the timestamp for the metric's sample used at T=11s. +# The result is 10 since the metric at T=11s falls within the [10s,20s) scrape window. +# The result is the timestamp of the sample at T=10s +eval range from 0 to 60s step 10s timestamp(metric @ 11) + {} 10 10 10 10 10 10 10 + +# As above - illustrating the sample used at the upper end of the [10s,20s) scrape window. +eval range from 0 to 60s step 10s timestamp(metric @ 19) + {} 10 10 10 10 10 10 10 + +# As above - illustrating the transition to the next scrap window. +eval range from 0 to 60s step 10s timestamp(metric @ 20) + {} 20 20 20 20 20 20 20 + +eval range from 0 to 60s step 10s timestamp(metric_missing @ 0) + {} 0 0 0 0 0 0 0 + +# The timestamp of 0 is returned since the sample is missing from the [10s,20s) scrape window. +# As such, the previous sample from T=0s is returned. +eval range from 0 to 60s step 10s timestamp(metric_missing @ 10) + {} 0 0 0 0 0 0 0 + +eval range from 0 to 60s step 10s timestamp(metric_missing @ 20) + {} 20 20 20 20 20 20 20 + +# The timestamps for each step are returned since abs() returns a new vector with new [T,V] samples. +# Each sample in this vector has its value set to the absolute value of the sample value at T=10s, and its timestamp aligned to the step interval. +# This is unlike the above tests where timestamp() is operating on a vector with the original series samples. +eval range from 0 to 60s step 10s timestamp(abs(metric @ 11)) + {} 0 10 20 30 40 50 60 + +eval range from 0 to 60s step 10s timestamp(abs(metric_missing @ 11)) + {} 0 10 20 30 40 50 60 + +clear \ No newline at end of file diff --git a/vendor/modules.txt b/vendor/modules.txt index 02e541039e..d26ede1916 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1868,7 +1868,7 @@ github.com/prometheus/otlptranslator github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util -# github.com/prometheus/prometheus v0.310.1-0.20260227151745-3b1d65816f22 +# github.com/prometheus/prometheus v0.310.1-0.20260302160042-1751685dd4f6 ## explicit; go 1.25.0 github.com/prometheus/prometheus/config github.com/prometheus/prometheus/discovery