mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
[bugfix] Parse negative value in PromQL (#4564)
* Parse negative value in PromQL * Enforce space between values Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
This commit is contained in:
parent
068eaa5dbf
commit
73db8b8cea
|
@ -143,6 +143,7 @@ const (
|
||||||
itemDuration
|
itemDuration
|
||||||
itemBlank
|
itemBlank
|
||||||
itemTimes
|
itemTimes
|
||||||
|
itemSpace
|
||||||
|
|
||||||
operatorsStart
|
operatorsStart
|
||||||
// Operators.
|
// Operators.
|
||||||
|
@ -247,6 +248,7 @@ var itemTypeStr = map[ItemType]string{
|
||||||
itemSemicolon: ";",
|
itemSemicolon: ";",
|
||||||
itemBlank: "_",
|
itemBlank: "_",
|
||||||
itemTimes: "x",
|
itemTimes: "x",
|
||||||
|
itemSpace: "<space>",
|
||||||
|
|
||||||
itemSUB: "-",
|
itemSUB: "-",
|
||||||
itemADD: "+",
|
itemADD: "+",
|
||||||
|
@ -616,6 +618,7 @@ func lexValueSequence(l *lexer) stateFn {
|
||||||
case r == eof:
|
case r == eof:
|
||||||
return lexStatements
|
return lexStatements
|
||||||
case isSpace(r):
|
case isSpace(r):
|
||||||
|
l.emit(itemSpace)
|
||||||
lexSpace(l)
|
lexSpace(l)
|
||||||
case r == '+':
|
case r == '+':
|
||||||
l.emit(itemADD)
|
l.emit(itemADD)
|
||||||
|
|
|
@ -406,9 +406,13 @@ var tests = []struct {
|
||||||
expected: []item{
|
expected: []item{
|
||||||
{itemLeftBrace, 0, `{`},
|
{itemLeftBrace, 0, `{`},
|
||||||
{itemRightBrace, 1, `}`},
|
{itemRightBrace, 1, `}`},
|
||||||
|
{itemSpace, 2, ` `},
|
||||||
{itemBlank, 3, `_`},
|
{itemBlank, 3, `_`},
|
||||||
|
{itemSpace, 4, ` `},
|
||||||
{itemNumber, 5, `1`},
|
{itemNumber, 5, `1`},
|
||||||
|
{itemSpace, 6, ` `},
|
||||||
{itemTimes, 7, `x`},
|
{itemTimes, 7, `x`},
|
||||||
|
{itemSpace, 8, ` `},
|
||||||
{itemNumber, 9, `.3`},
|
{itemNumber, 9, `.3`},
|
||||||
},
|
},
|
||||||
seriesDesc: true,
|
seriesDesc: true,
|
||||||
|
@ -417,9 +421,12 @@ var tests = []struct {
|
||||||
input: `metric +Inf Inf NaN`,
|
input: `metric +Inf Inf NaN`,
|
||||||
expected: []item{
|
expected: []item{
|
||||||
{itemIdentifier, 0, `metric`},
|
{itemIdentifier, 0, `metric`},
|
||||||
|
{itemSpace, 6, ` `},
|
||||||
{itemADD, 7, `+`},
|
{itemADD, 7, `+`},
|
||||||
{itemNumber, 8, `Inf`},
|
{itemNumber, 8, `Inf`},
|
||||||
|
{itemSpace, 11, ` `},
|
||||||
{itemNumber, 12, `Inf`},
|
{itemNumber, 12, `Inf`},
|
||||||
|
{itemSpace, 15, ` `},
|
||||||
{itemNumber, 16, `NaN`},
|
{itemNumber, 16, `NaN`},
|
||||||
},
|
},
|
||||||
seriesDesc: true,
|
seriesDesc: true,
|
||||||
|
@ -428,6 +435,7 @@ var tests = []struct {
|
||||||
input: `metric 1+1x4`,
|
input: `metric 1+1x4`,
|
||||||
expected: []item{
|
expected: []item{
|
||||||
{itemIdentifier, 0, `metric`},
|
{itemIdentifier, 0, `metric`},
|
||||||
|
{itemSpace, 6, ` `},
|
||||||
{itemNumber, 7, `1`},
|
{itemNumber, 7, `1`},
|
||||||
{itemADD, 8, `+`},
|
{itemADD, 8, `+`},
|
||||||
{itemNumber, 9, `1`},
|
{itemNumber, 9, `1`},
|
||||||
|
|
|
@ -175,6 +175,9 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
|
||||||
|
|
||||||
const ctx = "series values"
|
const ctx = "series values"
|
||||||
for {
|
for {
|
||||||
|
for p.peek().typ == itemSpace {
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
if p.peek().typ == itemEOF {
|
if p.peek().typ == itemEOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -193,6 +196,11 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
|
||||||
for i := uint64(0); i < times; i++ {
|
for i := uint64(0); i < times; i++ {
|
||||||
vals = append(vals, sequenceValue{omitted: true})
|
vals = append(vals, sequenceValue{omitted: true})
|
||||||
}
|
}
|
||||||
|
// This is to ensure that there is a space between this and the next number.
|
||||||
|
// This is especially required if the next number is negative.
|
||||||
|
if t := p.expectOneOf(itemSpace, itemEOF, ctx).typ; t == itemEOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +225,8 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
|
||||||
})
|
})
|
||||||
|
|
||||||
// If there are no offset repetitions specified, proceed with the next value.
|
// If there are no offset repetitions specified, proceed with the next value.
|
||||||
if t := p.peek(); t.typ == itemNumber || t.typ == itemBlank || t.typ == itemIdentifier && t.val == "stale" {
|
if t := p.peek(); t.typ == itemSpace {
|
||||||
|
// This ensures there is a space between every value.
|
||||||
continue
|
continue
|
||||||
} else if t.typ == itemEOF {
|
} else if t.typ == itemEOF {
|
||||||
break
|
break
|
||||||
|
@ -244,6 +253,12 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
|
||||||
value: k,
|
value: k,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// This is to ensure that there is a space between this expanding notation
|
||||||
|
// and the next number. This is especially required if the next number
|
||||||
|
// is negative.
|
||||||
|
if t := p.expectOneOf(itemSpace, itemEOF, ctx).typ; t == itemEOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m, vals, nil
|
return m, vals, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1737,6 +1737,39 @@ var testSeries = []struct {
|
||||||
}, {
|
}, {
|
||||||
input: `my_metric{a="b"} 1 3 _ 5 _a4`,
|
input: `my_metric{a="b"} 1 3 _ 5 _a4`,
|
||||||
fail: true,
|
fail: true,
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} 1 -1`,
|
||||||
|
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
|
||||||
|
expectedValues: newSeq(1, -1),
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} 1 +1`,
|
||||||
|
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
|
||||||
|
expectedValues: newSeq(1, 1),
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} 1 -1 -3-10x4 7 9 +5`,
|
||||||
|
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
|
||||||
|
expectedValues: newSeq(1, -1, -3, -13, -23, -33, -43, 7, 9, 5),
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} 1 +1 +4 -6 -2 8`,
|
||||||
|
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
|
||||||
|
expectedValues: newSeq(1, 1, 4, -6, -2, 8),
|
||||||
|
}, {
|
||||||
|
// Trailing spaces should be correctly handles.
|
||||||
|
input: `my_metric{a="b"} 1 2 3 `,
|
||||||
|
expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"),
|
||||||
|
expectedValues: newSeq(1, 2, 3),
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} -3-3 -3`,
|
||||||
|
fail: true,
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} -3 -3-3`,
|
||||||
|
fail: true,
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} -3 _-2`,
|
||||||
|
fail: true,
|
||||||
|
}, {
|
||||||
|
input: `my_metric{a="b"} -3 3+3x4-4`,
|
||||||
|
fail: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue