mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-01 14:47:38 +00:00
app/vmselect/promql: support composite durations like Prometheus 2.21 does
The following durations are supported now: `1h5m35s` or `1s543ms` See https://github.com/prometheus/prometheus/releases/tag/v2.21.0 and https://github.com/prometheus/prometheus/pull/7713
This commit is contained in:
parent
0e19f35af5
commit
0e533d1a9c
5 changed files with 75 additions and 22 deletions
|
@ -150,7 +150,7 @@ func TestExecSuccess(t *testing.T) {
|
||||||
resultExpected := []netstorage.Result{r}
|
resultExpected := []netstorage.Result{r}
|
||||||
f(q, resultExpected)
|
f(q, resultExpected)
|
||||||
})
|
})
|
||||||
t.Run("time() offset 100s", func(t *testing.T) {
|
t.Run("time() offset 1m40s0ms", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
q := `time() offset 100s`
|
q := `time() offset 100s`
|
||||||
r := netstorage.Result{
|
r := netstorage.Result{
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -8,7 +8,7 @@ require (
|
||||||
// like https://github.com/valyala/fasthttp/commit/996610f021ff45fdc98c2ce7884d5fa4e7f9199b
|
// like https://github.com/valyala/fasthttp/commit/996610f021ff45fdc98c2ce7884d5fa4e7f9199b
|
||||||
github.com/VictoriaMetrics/fasthttp v1.0.5
|
github.com/VictoriaMetrics/fasthttp v1.0.5
|
||||||
github.com/VictoriaMetrics/metrics v1.12.3
|
github.com/VictoriaMetrics/metrics v1.12.3
|
||||||
github.com/VictoriaMetrics/metricsql v0.5.1
|
github.com/VictoriaMetrics/metricsql v0.6.0
|
||||||
github.com/aws/aws-sdk-go v1.34.20
|
github.com/aws/aws-sdk-go v1.34.20
|
||||||
github.com/cespare/xxhash/v2 v2.1.1
|
github.com/cespare/xxhash/v2 v2.1.1
|
||||||
github.com/golang/snappy v0.0.1
|
github.com/golang/snappy v0.0.1
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -58,8 +58,8 @@ github.com/VictoriaMetrics/metrics v1.12.2 h1:SG8iAmqavDNuh7GIdHPoGHUhDL23KeKfvS
|
||||||
github.com/VictoriaMetrics/metrics v1.12.2/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE=
|
github.com/VictoriaMetrics/metrics v1.12.2/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE=
|
||||||
github.com/VictoriaMetrics/metrics v1.12.3 h1:Fe6JHC6MSEKa+BtLhPN8WIvS+HKPzMc2evEpNeCGy7I=
|
github.com/VictoriaMetrics/metrics v1.12.3 h1:Fe6JHC6MSEKa+BtLhPN8WIvS+HKPzMc2evEpNeCGy7I=
|
||||||
github.com/VictoriaMetrics/metrics v1.12.3/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE=
|
github.com/VictoriaMetrics/metrics v1.12.3/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE=
|
||||||
github.com/VictoriaMetrics/metricsql v0.5.1 h1:hG6Nck7R2/amLgHECobSTXsjZ2z9JP5J3W1sYlBoqfU=
|
github.com/VictoriaMetrics/metricsql v0.6.0 h1:JnHUmifuA3fdy1GQrmkZJFO+CwFrhLxKwzMv89wNgJ4=
|
||||||
github.com/VictoriaMetrics/metricsql v0.5.1/go.mod h1:ylO7YITho/Iw6P71oEaGyHbO94bGoGtzWfLGqFhMIg8=
|
github.com/VictoriaMetrics/metricsql v0.6.0/go.mod h1:ylO7YITho/Iw6P71oEaGyHbO94bGoGtzWfLGqFhMIg8=
|
||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
|
|
87
vendor/github.com/VictoriaMetrics/metricsql/lexer.go
generated
vendored
87
vendor/github.com/VictoriaMetrics/metricsql/lexer.go
generated
vendored
|
@ -103,7 +103,7 @@ again:
|
||||||
token = s[:n]
|
token = s[:n]
|
||||||
goto tokenFoundLabel
|
goto tokenFoundLabel
|
||||||
}
|
}
|
||||||
if n := scanDuration(s, false); n > 0 {
|
if n := scanDuration(s); n > 0 {
|
||||||
token = s[:n]
|
token = s[:n]
|
||||||
goto tokenFoundLabel
|
goto tokenFoundLabel
|
||||||
}
|
}
|
||||||
|
@ -393,7 +393,7 @@ func scanSpecialIntegerPrefix(s string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isPositiveDuration(s string) bool {
|
func isPositiveDuration(s string) bool {
|
||||||
n := scanDuration(s, false)
|
n := scanDuration(s)
|
||||||
return n == len(s)
|
return n == len(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,33 +413,57 @@ func PositiveDurationValue(s string, step int64) (int64, error) {
|
||||||
// DurationValue returns the duration in milliseconds for the given s
|
// DurationValue returns the duration in milliseconds for the given s
|
||||||
// and the given step.
|
// and the given step.
|
||||||
//
|
//
|
||||||
|
// Duration in s may be combined, i.e. 2h5m or 2h-5m.
|
||||||
|
//
|
||||||
// The returned duration value can be negative.
|
// The returned duration value can be negative.
|
||||||
func DurationValue(s string, step int64) (int64, error) {
|
func DurationValue(s string, step int64) (int64, error) {
|
||||||
n := scanDuration(s, true)
|
if len(s) == 0 {
|
||||||
if n != len(s) {
|
return 0, fmt.Errorf("duration cannot be empty")
|
||||||
return 0, fmt.Errorf("cannot parse duration %q", s)
|
|
||||||
}
|
}
|
||||||
|
var d int64
|
||||||
|
for len(s) > 0 {
|
||||||
|
n := scanSingleDuration(s, true)
|
||||||
|
if n <= 0 {
|
||||||
|
return 0, fmt.Errorf("cannot parse duration %q", s)
|
||||||
|
}
|
||||||
|
ds := s[:n]
|
||||||
|
s = s[n:]
|
||||||
|
dLocal, err := parseSingleDuration(ds, step)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
d += dLocal
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
f, err := strconv.ParseFloat(s[:len(s)-1], 64)
|
func parseSingleDuration(s string, step int64) (int64, error) {
|
||||||
|
numPart := s[:len(s)-1]
|
||||||
|
if strings.HasSuffix(numPart, "m") {
|
||||||
|
// Duration in ms
|
||||||
|
numPart = numPart[:len(numPart)-1]
|
||||||
|
}
|
||||||
|
f, err := strconv.ParseFloat(numPart, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("cannot parse duration %q: %s", s, err)
|
return 0, fmt.Errorf("cannot parse duration %q: %s", s, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var mp float64
|
var mp float64
|
||||||
switch s[len(s)-1] {
|
switch s[len(numPart):] {
|
||||||
case 's':
|
case "ms":
|
||||||
|
mp = 1e-3
|
||||||
|
case "s":
|
||||||
mp = 1
|
mp = 1
|
||||||
case 'm':
|
case "m":
|
||||||
mp = 60
|
mp = 60
|
||||||
case 'h':
|
case "h":
|
||||||
mp = 60 * 60
|
mp = 60 * 60
|
||||||
case 'd':
|
case "d":
|
||||||
mp = 24 * 60 * 60
|
mp = 24 * 60 * 60
|
||||||
case 'w':
|
case "w":
|
||||||
mp = 7 * 24 * 60 * 60
|
mp = 7 * 24 * 60 * 60
|
||||||
case 'y':
|
case "y":
|
||||||
mp = 365 * 24 * 60 * 60
|
mp = 365 * 24 * 60 * 60
|
||||||
case 'i':
|
case "i":
|
||||||
mp = float64(step) / 1e3
|
mp = float64(step) / 1e3
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("invalid duration suffix in %q", s)
|
return 0, fmt.Errorf("invalid duration suffix in %q", s)
|
||||||
|
@ -447,7 +471,29 @@ func DurationValue(s string, step int64) (int64, error) {
|
||||||
return int64(mp * f * 1e3), nil
|
return int64(mp * f * 1e3), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanDuration(s string, canBeNegative bool) int {
|
// scanDuration scans duration, which must start with positive num.
|
||||||
|
//
|
||||||
|
// I.e. 123h, 3h5m or 3.4d-35.66s
|
||||||
|
func scanDuration(s string) int {
|
||||||
|
// The first part must be non-negative
|
||||||
|
n := scanSingleDuration(s, false)
|
||||||
|
if n <= 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
s = s[n:]
|
||||||
|
i := n
|
||||||
|
for {
|
||||||
|
// Other parts may be negative
|
||||||
|
n := scanSingleDuration(s, true)
|
||||||
|
if n <= 0 {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
s = s[n:]
|
||||||
|
i += n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanSingleDuration(s string, canBeNegative bool) int {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
@ -472,7 +518,14 @@ func scanDuration(s string, canBeNegative bool) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch s[i] {
|
switch s[i] {
|
||||||
case 's', 'm', 'h', 'd', 'w', 'y', 'i':
|
case 'm':
|
||||||
|
if i+1 < len(s) && s[i+1] == 's' {
|
||||||
|
// duration in ms
|
||||||
|
return i + 2
|
||||||
|
}
|
||||||
|
// duration in minutes
|
||||||
|
return i + 1
|
||||||
|
case 's', 'h', 'd', 'w', 'y', 'i':
|
||||||
return i + 1
|
return i + 1
|
||||||
default:
|
default:
|
||||||
return -1
|
return -1
|
||||||
|
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -16,7 +16,7 @@ github.com/VictoriaMetrics/fasthttp/fasthttputil
|
||||||
github.com/VictoriaMetrics/fasthttp/stackless
|
github.com/VictoriaMetrics/fasthttp/stackless
|
||||||
# github.com/VictoriaMetrics/metrics v1.12.3
|
# github.com/VictoriaMetrics/metrics v1.12.3
|
||||||
github.com/VictoriaMetrics/metrics
|
github.com/VictoriaMetrics/metrics
|
||||||
# github.com/VictoriaMetrics/metricsql v0.5.1
|
# github.com/VictoriaMetrics/metricsql v0.6.0
|
||||||
github.com/VictoriaMetrics/metricsql
|
github.com/VictoriaMetrics/metricsql
|
||||||
github.com/VictoriaMetrics/metricsql/binaryop
|
github.com/VictoriaMetrics/metricsql/binaryop
|
||||||
# github.com/aws/aws-sdk-go v1.34.20
|
# github.com/aws/aws-sdk-go v1.34.20
|
||||||
|
|
Loading…
Reference in a new issue