mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
[metricsql] for subqueries fixed behavior of functions that use query time range in their logic (like start
, end
, and running_*
), from now on when using in subqueries they respect time range from query parameters (#5794)
This commit is contained in:
parent
7332431b90
commit
881dffd6a2
3 changed files with 52 additions and 9 deletions
|
@ -111,6 +111,11 @@ type EvalConfig struct {
|
|||
End int64
|
||||
Step int64
|
||||
|
||||
// RealStart contains the original start of the interval when executed in subqueries (because Start can be changed for subqueries)
|
||||
RealStart int64
|
||||
// RealEnd contains the original end of the interval when executed in subqueries (because End can be changed for subqueries)
|
||||
RealEnd int64
|
||||
|
||||
// MaxSeries is the maximum number of time series, which can be scanned by the query.
|
||||
// Zero means 'no limit'
|
||||
MaxSeries int
|
||||
|
@ -152,7 +157,17 @@ type EvalConfig struct {
|
|||
func copyEvalConfig(src *EvalConfig) *EvalConfig {
|
||||
var ec EvalConfig
|
||||
ec.Start = src.Start
|
||||
if ec.RealStart > 0 {
|
||||
ec.RealStart = src.RealStart
|
||||
} else {
|
||||
ec.RealStart = src.Start
|
||||
}
|
||||
ec.End = src.End
|
||||
if ec.RealEnd > 0 {
|
||||
ec.RealEnd = src.RealEnd
|
||||
} else {
|
||||
ec.RealEnd = src.End
|
||||
}
|
||||
ec.Step = src.Step
|
||||
ec.MaxSeries = src.MaxSeries
|
||||
ec.MaxPointsPerSeries = src.MaxPointsPerSeries
|
||||
|
|
|
@ -1248,8 +1248,13 @@ func newTransformFuncRunning(rf func(a, b float64, idx int) float64) transformFu
|
|||
prevValue := values[0]
|
||||
values = values[1:]
|
||||
for i, v := range values {
|
||||
if !math.IsNaN(v) {
|
||||
prevValue = rf(prevValue, v, i+1)
|
||||
if tfa.ec.RealEnd > 0 && ts.Timestamps[i] > tfa.ec.RealEnd {
|
||||
break
|
||||
}
|
||||
if ts.Timestamps[i] >= tfa.ec.RealStart {
|
||||
if !math.IsNaN(v) {
|
||||
prevValue = rf(prevValue, v, i+1)
|
||||
}
|
||||
}
|
||||
values[i] = prevValue
|
||||
}
|
||||
|
@ -1265,7 +1270,7 @@ func newTransformFuncRange(rf func(a, b float64, idx int) float64) transformFunc
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setLastValues(rvs)
|
||||
setLastValues(tfa, rvs)
|
||||
return rvs, nil
|
||||
}
|
||||
}
|
||||
|
@ -1539,7 +1544,7 @@ func transformRangeQuantile(tfa *transformFuncArg) ([]*timeseries, error) {
|
|||
}
|
||||
a.A = values
|
||||
putFloat64s(a)
|
||||
setLastValues(rvs)
|
||||
setLastValues(tfa, rvs)
|
||||
return rvs, nil
|
||||
}
|
||||
|
||||
|
@ -1554,9 +1559,14 @@ func transformRangeFirst(tfa *transformFuncArg) ([]*timeseries, error) {
|
|||
if len(values) == 0 {
|
||||
continue
|
||||
}
|
||||
vFirstSet := false
|
||||
vFirst := values[0]
|
||||
for i, v := range values {
|
||||
if math.IsNaN(v) {
|
||||
if !vFirstSet && ts.Timestamps[i] >= tfa.ec.RealStart {
|
||||
vFirst = v
|
||||
vFirstSet = true
|
||||
}
|
||||
if !vFirstSet && math.IsNaN(v) {
|
||||
continue
|
||||
}
|
||||
values[i] = vFirst
|
||||
|
@ -1571,17 +1581,28 @@ func transformRangeLast(tfa *transformFuncArg) ([]*timeseries, error) {
|
|||
return nil, err
|
||||
}
|
||||
rvs := args[0]
|
||||
setLastValues(rvs)
|
||||
setLastValues(tfa, rvs)
|
||||
return rvs, nil
|
||||
}
|
||||
|
||||
func setLastValues(tss []*timeseries) {
|
||||
func setLastValues(tfa *transformFuncArg, tss []*timeseries) {
|
||||
for _, ts := range tss {
|
||||
values := skipTrailingNaNs(ts.Values)
|
||||
if len(values) == 0 {
|
||||
continue
|
||||
}
|
||||
vLast := values[len(values)-1]
|
||||
if tfa.ec.RealEnd > 0 {
|
||||
for i := len(values) - 1; i >= 0; i-- {
|
||||
if math.IsNaN(values[i]) {
|
||||
continue
|
||||
}
|
||||
if ts.Timestamps[i] > tfa.ec.RealEnd {
|
||||
continue
|
||||
}
|
||||
vLast = values[i]
|
||||
}
|
||||
}
|
||||
for i, v := range values {
|
||||
if math.IsNaN(v) {
|
||||
continue
|
||||
|
@ -2713,11 +2734,17 @@ func transformStep(tfa *transformFuncArg) float64 {
|
|||
}
|
||||
|
||||
func transformStart(tfa *transformFuncArg) float64 {
|
||||
return float64(tfa.ec.Start) / 1e3
|
||||
if tfa.ec.RealStart == 0 {
|
||||
return float64(tfa.ec.Start) / 1e3
|
||||
}
|
||||
return float64(tfa.ec.RealStart) / 1e3
|
||||
}
|
||||
|
||||
func transformEnd(tfa *transformFuncArg) float64 {
|
||||
return float64(tfa.ec.End) / 1e3
|
||||
if tfa.ec.RealEnd == 0 {
|
||||
return float64(tfa.ec.End) / 1e3
|
||||
}
|
||||
return float64(tfa.ec.RealEnd) / 1e3
|
||||
}
|
||||
|
||||
// copyTimeseries returns a copy of tss.
|
||||
|
|
|
@ -41,6 +41,7 @@ See also [LTS releases](https://docs.victoriametrics.com/LTS-releases.html).
|
|||
* BUGFIX: fix the misleading error `0ms is out of allowed range [0 ...` when passing `step=0` to [/api/v1/query](https://docs.victoriametrics.com/keyconcepts/#instant-query)
|
||||
or [/api/v1/query_range](https://docs.victoriametrics.com/keyconcepts/#range-query). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5795).
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/#vmalert): consistently sort groups by name and filename on `/groups` page in UI. This should prevent non-deterministic sorting for groups with identical names.
|
||||
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): For subqueries fix behavior of functions that use query time range in their logic (like `start`, `end`, and `running_*`), from now on when using in subqueries they respect time range from query parameters. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5794) for details.
|
||||
|
||||
## [v1.98.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.98.0)
|
||||
|
||||
|
|
Loading…
Reference in a new issue