PromQL: Parse Series descriptions using the generated parser (#6494)

* Use generated parser for series descriptions

Signed-off-by: Tobias Guggenmos <tguggenm@redhat.com>
This commit is contained in:
Tobias Guggenmos 2019-12-21 09:44:12 +01:00 committed by Brian Brazil
parent f363a71ef7
commit 213a8fe89a
3 changed files with 385 additions and 282 deletions

View file

@ -12,13 +12,16 @@
// limitations under the License. // limitations under the License.
%{ %{
package promql package promql
import ( import (
"math"
"sort" "sort"
"strconv"
"github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/pkg/labels"
) "github.com/prometheus/prometheus/pkg/value"
)
%} %}
%union { %union {
@ -29,6 +32,9 @@
label labels.Label label labels.Label
labels labels.Labels labels labels.Labels
strings []string strings []string
series []sequenceValue
uint uint64
float float64
} }
@ -107,9 +113,9 @@
%token startSymbolsStart %token startSymbolsStart
// Start symbols for the generated parser. // Start symbols for the generated parser.
%token START_LABELS %token START_LABELS
%token START_LABEL_SET
%token START_METRIC %token START_METRIC
%token START_GROUPING_LABELS %token START_GROUPING_LABELS
%token START_SERIES_DESCRIPTION
%token startSymbolsEnd %token startSymbolsEnd
%type <matchers> label_matchers label_match_list %type <matchers> label_matchers label_match_list
@ -120,6 +126,9 @@
%type <labels> label_set_list label_set metric %type <labels> label_set_list label_set metric
%type <label> label_set_item %type <label> label_set_item
%type <strings> grouping_labels grouping_label_list %type <strings> grouping_labels grouping_label_list
%type <series> series_values series_item
%type <uint> uint
%type <float> series_value signed_number number
%start start %start start
@ -127,12 +136,12 @@
start : START_LABELS label_matchers start : START_LABELS label_matchers
{yylex.(*parser).generatedParserResult.(*VectorSelector).LabelMatchers = $2} {yylex.(*parser).generatedParserResult.(*VectorSelector).LabelMatchers = $2}
| START_LABEL_SET label_set
{ yylex.(*parser).generatedParserResult = $2 }
| START_METRIC metric | START_METRIC metric
{ yylex.(*parser).generatedParserResult = $2 } { yylex.(*parser).generatedParserResult = $2 }
| START_GROUPING_LABELS grouping_labels | START_GROUPING_LABELS grouping_labels
{ yylex.(*parser).generatedParserResult = $2 } { yylex.(*parser).generatedParserResult = $2 }
| START_SERIES_DESCRIPTION series_description
| start EOF
| error /* If none of the more detailed error messages are triggered, we fall back to this. */ | error /* If none of the more detailed error messages are triggered, we fall back to this. */
{ yylex.(*parser).unexpected("","") } { yylex.(*parser).unexpected("","") }
; ;
@ -181,8 +190,6 @@ metric :
{ $$ = append($2, labels.Label{Name: labels.MetricName, Value: $1.Val}); sort.Sort($$) } { $$ = append($2, labels.Label{Name: labels.MetricName, Value: $1.Val}); sort.Sort($$) }
| label_set | label_set
{$$ = $1} {$$ = $1}
| error
{ yylex.(*parser).errorf("missing metric name or metric selector")}
; ;
metric_identifier metric_identifier
@ -283,4 +290,92 @@ maybe_label :
| BOOL | BOOL
; ;
// The series description grammar is only used inside unit tests.
series_description:
metric series_values
{
yylex.(*parser).generatedParserResult = &seriesDescription{
labels: $1,
values: $2,
}
}
;
series_values :
/*empty*/
{ $$ = []sequenceValue{} }
| series_values SPACE series_item
{ $$ = append($1, $3...) }
| series_values SPACE
{ $$ = $1 }
| error
{ yylex.(*parser).unexpected("series values", "") }
;
series_item :
BLANK
{ $$ = []sequenceValue{{omitted: true}}}
| BLANK TIMES uint
{
$$ = []sequenceValue{}
for i:=uint64(0); i < $3; i++{
$$ = append($$, sequenceValue{omitted: true})
}
}
| series_value
{ $$ = []sequenceValue{{value: $1}}}
| series_value TIMES uint
{
$$ = []sequenceValue{}
for i:=uint64(0); i <= $3; i++{
$$ = append($$, sequenceValue{value: $1})
}
}
| series_value signed_number TIMES uint
{
$$ = []sequenceValue{}
for i:=uint64(0); i <= $4; i++{
$$ = append($$, sequenceValue{value: $1})
$1 += $2
}
}
uint :
NUMBER
{
var err error
$$, err = strconv.ParseUint($1.Val, 10, 64)
if err != nil {
yylex.(*parser).errorf("invalid repitition in series values: %s", err)
}
}
;
signed_number :
ADD number
{ $$ = $2 }
| SUB number
{ $$ = -$2 }
;
series_value :
IDENTIFIER
{
if $1.Val != "stale" {
yylex.(*parser).unexpected("series values", "number or \"stale\"")
}
$$ = math.Float64frombits(value.StaleNaN)
}
| number
{ $$ = $1 }
| signed_number
{ $$ = $1 }
;
number :
NUMBER
{$$ = yylex.(*parser).number($1.Val) }
;
%% %%

View file

@ -8,12 +8,15 @@ import __yyfmt__ "fmt"
//line promql/generated_parser.y:15 //line promql/generated_parser.y:15
import ( import (
"math"
"sort" "sort"
"strconv"
"github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/pkg/value"
) )
//line promql/generated_parser.y:24 //line promql/generated_parser.y:27
type yySymType struct { type yySymType struct {
yys int yys int
node Node node Node
@ -23,6 +26,9 @@ type yySymType struct {
label labels.Label label labels.Label
labels labels.Labels labels labels.Labels
strings []string strings []string
series []sequenceValue
uint uint64
float float64
} }
const ERROR = 57346 const ERROR = 57346
@ -90,9 +96,9 @@ const BOOL = 57407
const keywordsEnd = 57408 const keywordsEnd = 57408
const startSymbolsStart = 57409 const startSymbolsStart = 57409
const START_LABELS = 57410 const START_LABELS = 57410
const START_LABEL_SET = 57411 const START_METRIC = 57411
const START_METRIC = 57412 const START_GROUPING_LABELS = 57412
const START_GROUPING_LABELS = 57413 const START_SERIES_DESCRIPTION = 57413
const startSymbolsEnd = 57414 const startSymbolsEnd = 57414
var yyToknames = [...]string{ var yyToknames = [...]string{
@ -164,9 +170,9 @@ var yyToknames = [...]string{
"keywordsEnd", "keywordsEnd",
"startSymbolsStart", "startSymbolsStart",
"START_LABELS", "START_LABELS",
"START_LABEL_SET",
"START_METRIC", "START_METRIC",
"START_GROUPING_LABELS", "START_GROUPING_LABELS",
"START_SERIES_DESCRIPTION",
"startSymbolsEnd", "startSymbolsEnd",
} }
var yyStatenames = [...]string{} var yyStatenames = [...]string{}
@ -175,100 +181,113 @@ const yyEofCode = 1
const yyErrCode = 2 const yyErrCode = 2
const yyInitialStackSize = 16 const yyInitialStackSize = 16
//line promql/generated_parser.y:286 //line promql/generated_parser.y:382
//line yacctab:1 //line yacctab:1
var yyExca = [...]int{ var yyExca = [...]int{
-1, 1, -1, 1,
1, -1, 1, -1,
-2, 0, -2, 0,
-1, 4, -1, 20,
1, 28, 1, 69,
5, 69,
24, 69,
-2, 0, -2, 0,
} }
const yyPrivate = 57344 const yyPrivate = 57344
const yyLast = 142 const yyLast = 144
var yyAct = [...]int{ var yyAct = [...]int{
35, 27, 33, 63, 22, 36, 37, 6, 84, 83, 104, 94, 95, 36, 34, 23, 66, 29, 37, 38,
79, 75, 1, 29, 10, 70, 31, 8, 28, 73, 6, 88, 79, 107, 100, 99, 93, 98, 97, 105,
17, 11, 72, 80, 74, 68, 82, 78, 69, 38, 96, 15, 9, 87, 83, 75, 14, 13, 61, 96,
39, 40, 19, 25, 34, 64, 65, 12, 62, 18, 15, 91, 39, 40, 41, 98, 97, 10, 67, 68,
20, 66, 67, 41, 42, 43, 44, 45, 46, 47, 86, 82, 7, 20, 69, 70, 42, 43, 44, 45,
48, 49, 50, 51, 71, 7, 52, 53, 0, 54, 46, 47, 48, 49, 50, 51, 52, 74, 73, 53,
55, 56, 57, 58, 35, 77, 0, 0, 61, 36, 54, 19, 55, 56, 57, 58, 59, 36, 71, 81,
37, 81, 32, 2, 3, 4, 5, 85, 59, 24, 1, 72, 37, 38, 64, 33, 2, 3, 4, 5,
29, 60, 24, 0, 23, 28, 0, 23, 0, 76, 85, 78, 89, 31, 62, 18, 92, 63, 30, 76,
26, 14, 21, 38, 39, 40, 16, 15, 0, 0, 12, 90, 17, 84, 77, 101, 39, 40, 41, 102,
10, 0, 0, 0, 0, 0, 0, 41, 42, 43, 103, 106, 26, 60, 32, 16, 27, 35, 108, 11,
44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 0, 54, 55, 56, 57, 58, 9, 0, 52, 65, 21, 53, 54, 8, 55, 56, 57, 58,
0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 59, 25, 31, 25, 0, 0, 24, 30, 24, 0,
0, 30, 0, 80, 28, 22,
} }
var yyPact = [...]int{ var yyPact = [...]int{
5, -1000, 6, 3, 89, 30, -1000, -1000, 80, -1000, 8, 37, 11, 19, 83, 19, -1000, -1000, -1000, 131,
78, -1000, 3, -1000, -1000, -1000, -1000, -1000, 62, -1000, -1000, 10, -1000, -1000, -1000, 130, -1000, 65, -1000, -1000,
66, -1000, -1000, 1, -1000, 13, -1000, -1000, 20, -1000, 26, 72, -1000, -1000, 4, -1000, -1000, 56, -1000, -1000,
-1000, 9, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 23, -1000, 79, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
77, -1000, 8, -1000, -1000, -1000, -1000, -1000, -1000, 11, -12, -1000, -1000, 129, -1000, 22, -1000, -1000, -1000, -1000,
-1000, 7, -1000, -1000, -2, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 81, -1000, 21, -1000, -1000, 1, -1000, 9,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -8, -9, -1000, -1000, -1000, -1000, 0, 0, -1,
-1, -10, -1000, -1000, -1000, -1000, -1000, -1, -1000,
} }
var yyPgo = [...]int{ var yyPgo = [...]int{
0, 55, 40, 4, 38, 37, 2, 34, 33, 128, 0, 125, 122, 5, 121, 109, 4, 107, 106, 90,
21, 1, 20, 16, 12, 37, 7, 105, 104, 103, 91, 0, 86, 2, 1,
70, 61,
} }
var yyR1 = [...]int{ var yyR1 = [...]int{
0, 14, 14, 14, 14, 14, 1, 1, 1, 2, 0, 20, 20, 20, 20, 20, 20, 1, 1, 1,
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
10, 10, 10, 5, 5, 9, 9, 9, 9, 8, 4, 10, 10, 5, 5, 9, 9, 9, 9, 8,
8, 8, 11, 11, 11, 11, 12, 12, 12, 12, 8, 8, 11, 11, 11, 11, 12, 12, 12, 12,
13, 13, 13, 6, 6, 7, 7, 7, 7, 7, 13, 13, 13, 6, 6, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 14,
14, 14, 14, 15, 15, 15, 15, 15, 16, 18,
18, 17, 17, 17, 19,
} }
var yyR2 = [...]int{ var yyR2 = [...]int{
0, 2, 2, 2, 2, 1, 3, 4, 2, 3, 0, 2, 2, 2, 2, 2, 1, 3, 4, 2,
1, 2, 3, 3, 2, 1, 1, 1, 1, 1, 3, 1, 2, 3, 3, 2, 1, 1, 1, 1,
2, 1, 1, 1, 1, 3, 4, 2, 0, 3, 1, 2, 1, 1, 1, 3, 4, 2, 0, 3,
1, 2, 3, 3, 2, 1, 3, 4, 2, 1, 1, 2, 3, 3, 2, 1, 3, 4, 2, 1,
3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0,
3, 2, 1, 1, 3, 1, 3, 4, 1, 2,
2, 1, 1, 1, 1,
} }
var yyChk = [...]int{ var yyChk = [...]int{
-1000, -14, 68, 69, 70, 71, 2, -1, 11, -9, -1000, -20, 68, 69, 70, 71, 2, 5, -1, 11,
11, -10, -5, -9, 2, 8, 7, -12, 9, 2, -10, -5, -9, 8, 7, 11, -12, 9, 2, -21,
-2, 12, -3, 7, 2, -8, 12, -11, 7, 2, -10, -2, 12, -3, 7, 2, -9, -8, 12, -11,
-9, -13, 10, -6, -7, 2, 7, 8, 31, 32, 7, 2, -13, 10, -6, -7, 2, 7, 8, 31,
33, 45, 46, 47, 48, 49, 50, 51, 52, 53, 32, 33, 45, 46, 47, 48, 49, 50, 51, 52,
54, 55, 58, 59, 61, 62, 63, 64, 65, 12, 53, 54, 55, 58, 59, 61, 62, 63, 64, 65,
15, 2, -4, 2, 34, 35, 40, 41, 12, 15, -14, 2, 12, 15, 2, -4, 2, 34, 35, 40,
2, 34, 2, 10, 15, 2, 12, -3, 19, 2, 41, 12, 15, 2, 34, 2, 10, 15, 2, 24,
12, -11, 19, 2, 10, -6, 12, -3, 19, 2, 12, -11, 19, 2, 10, -6,
-15, 22, -17, 7, -19, -18, 20, 27, 26, 23,
23, -18, -19, -19, -16, 20, -16, 23, -16,
} }
var yyDef = [...]int{ var yyDef = [...]int{
0, -2, 0, 28, -2, 0, 5, 1, 0, 2, 0, -2, 0, 28, 0, 28, 6, 5, 1, 0,
0, 3, 28, 21, 22, 23, 24, 4, 0, 39, 2, 28, 22, 23, 24, 0, 3, 0, 39, 4,
0, 8, 10, 0, 15, 0, 27, 30, 0, 35, -2, 0, 9, 11, 0, 16, 21, 0, 27, 30,
20, 0, 38, 41, 43, 44, 45, 46, 47, 48, 0, 35, 0, 38, 41, 43, 44, 45, 46, 47,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
59, 60, 61, 62, 63, 64, 65, 66, 67, 6, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
0, 11, 0, 14, 16, 17, 18, 19, 25, 0, 68, 72, 7, 0, 12, 0, 15, 17, 18, 19,
31, 0, 34, 36, 0, 42, 7, 9, 12, 13, 20, 25, 0, 31, 0, 34, 36, 0, 42, 71,
26, 29, 32, 33, 37, 40, 8, 10, 13, 14, 26, 29, 32, 33, 37, 40,
70, 73, 75, 81, 82, 83, 84, 0, 0, 0,
0, 0, 79, 80, 74, 78, 76, 0, 77,
} }
var yyTok1 = [...]int{ var yyTok1 = [...]int{
@ -628,260 +647,248 @@ yydefault:
case 1: case 1:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:129 //line promql/generated_parser.y:138
{ {
yylex.(*parser).generatedParserResult.(*VectorSelector).LabelMatchers = yyDollar[2].matchers yylex.(*parser).generatedParserResult.(*VectorSelector).LabelMatchers = yyDollar[2].matchers
} }
case 2: case 2:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:131 //line promql/generated_parser.y:140
{ {
yylex.(*parser).generatedParserResult = yyDollar[2].labels yylex.(*parser).generatedParserResult = yyDollar[2].labels
} }
case 3: case 3:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:133 //line promql/generated_parser.y:142
{
yylex.(*parser).generatedParserResult = yyDollar[2].labels
}
case 4:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:135
{ {
yylex.(*parser).generatedParserResult = yyDollar[2].strings yylex.(*parser).generatedParserResult = yyDollar[2].strings
} }
case 5: case 6:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:137 //line promql/generated_parser.y:146
{ {
yylex.(*parser).unexpected("", "") yylex.(*parser).unexpected("", "")
} }
case 6:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:143
{
yyVAL.matchers = yyDollar[2].matchers
}
case 7: case 7:
yyDollar = yyS[yypt-4 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:145 //line promql/generated_parser.y:152
{ {
yyVAL.matchers = yyDollar[2].matchers yyVAL.matchers = yyDollar[2].matchers
} }
case 8: case 8:
yyDollar = yyS[yypt-4 : yypt+1]
//line promql/generated_parser.y:154
{
yyVAL.matchers = yyDollar[2].matchers
}
case 9:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:147 //line promql/generated_parser.y:156
{ {
yyVAL.matchers = []*labels.Matcher{} yyVAL.matchers = []*labels.Matcher{}
} }
case 9:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:153
{
yyVAL.matchers = append(yyDollar[1].matchers, yyDollar[3].matcher)
}
case 10: case 10:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:155
{
yyVAL.matchers = []*labels.Matcher{yyDollar[1].matcher}
}
case 11:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:157
{
yylex.(*parser).unexpected("label matching", "\",\" or \"}\"")
}
case 12:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:162 //line promql/generated_parser.y:162
{ {
yyVAL.matcher = yylex.(*parser).newLabelMatcher(yyDollar[1].item, yyDollar[2].item, yyDollar[3].item) yyVAL.matchers = append(yyDollar[1].matchers, yyDollar[3].matcher)
} }
case 13: case 11:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:164 //line promql/generated_parser.y:164
{ {
yylex.(*parser).unexpected("label matching", "string") yyVAL.matchers = []*labels.Matcher{yyDollar[1].matcher}
} }
case 14: case 12:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:166 //line promql/generated_parser.y:166
{ {
yylex.(*parser).unexpected("label matching", "label matching operator") yylex.(*parser).unexpected("label matching", "\",\" or \"}\"")
}
case 13:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:171
{
yyVAL.matcher = yylex.(*parser).newLabelMatcher(yyDollar[1].item, yyDollar[2].item, yyDollar[3].item)
}
case 14:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:173
{
yylex.(*parser).unexpected("label matching", "string")
} }
case 15: case 15:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:168 //line promql/generated_parser.y:175
{ {
yylex.(*parser).unexpected("label matching", "identifier or \"}\"") yylex.(*parser).unexpected("label matching", "label matching operator")
} }
case 16: case 16:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:172 //line promql/generated_parser.y:177
{ {
yyVAL.item = yyDollar[1].item yylex.(*parser).unexpected("label matching", "identifier or \"}\"")
} }
case 17: case 17:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:173 //line promql/generated_parser.y:181
{ {
yyVAL.item = yyDollar[1].item yyVAL.item = yyDollar[1].item
} }
case 18: case 18:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:174 //line promql/generated_parser.y:182
{ {
yyVAL.item = yyDollar[1].item yyVAL.item = yyDollar[1].item
} }
case 19: case 19:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:175 //line promql/generated_parser.y:183
{ {
yyVAL.item = yyDollar[1].item yyVAL.item = yyDollar[1].item
} }
case 20: case 20:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:184
{
yyVAL.item = yyDollar[1].item
}
case 21:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:181 //line promql/generated_parser.y:190
{ {
yyVAL.labels = append(yyDollar[2].labels, labels.Label{Name: labels.MetricName, Value: yyDollar[1].item.Val}) yyVAL.labels = append(yyDollar[2].labels, labels.Label{Name: labels.MetricName, Value: yyDollar[1].item.Val})
sort.Sort(yyVAL.labels) sort.Sort(yyVAL.labels)
} }
case 21: case 22:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:183 //line promql/generated_parser.y:192
{ {
yyVAL.labels = yyDollar[1].labels yyVAL.labels = yyDollar[1].labels
} }
case 22:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:185
{
yylex.(*parser).errorf("missing metric name or metric selector")
}
case 23: case 23:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:190 //line promql/generated_parser.y:199
{ {
yyVAL.item = yyDollar[1].item yyVAL.item = yyDollar[1].item
} }
case 24: case 24:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:191 //line promql/generated_parser.y:200
{ {
yyVAL.item = yyDollar[1].item yyVAL.item = yyDollar[1].item
} }
case 25: case 25:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:195 //line promql/generated_parser.y:204
{ {
yyVAL.labels = labels.New(yyDollar[2].labels...) yyVAL.labels = labels.New(yyDollar[2].labels...)
} }
case 26: case 26:
yyDollar = yyS[yypt-4 : yypt+1] yyDollar = yyS[yypt-4 : yypt+1]
//line promql/generated_parser.y:197 //line promql/generated_parser.y:206
{ {
yyVAL.labels = labels.New(yyDollar[2].labels...) yyVAL.labels = labels.New(yyDollar[2].labels...)
} }
case 27: case 27:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:199 //line promql/generated_parser.y:208
{ {
yyVAL.labels = labels.New() yyVAL.labels = labels.New()
} }
case 28: case 28:
yyDollar = yyS[yypt-0 : yypt+1] yyDollar = yyS[yypt-0 : yypt+1]
//line promql/generated_parser.y:201 //line promql/generated_parser.y:210
{ {
yyVAL.labels = labels.New() yyVAL.labels = labels.New()
} }
case 29: case 29:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:206 //line promql/generated_parser.y:215
{ {
yyVAL.labels = append(yyDollar[1].labels, yyDollar[3].label) yyVAL.labels = append(yyDollar[1].labels, yyDollar[3].label)
} }
case 30: case 30:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:208 //line promql/generated_parser.y:217
{ {
yyVAL.labels = []labels.Label{yyDollar[1].label} yyVAL.labels = []labels.Label{yyDollar[1].label}
} }
case 31: case 31:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:210 //line promql/generated_parser.y:219
{ {
yylex.(*parser).unexpected("label set", "\",\" or \"}\"") yylex.(*parser).unexpected("label set", "\",\" or \"}\"")
} }
case 32: case 32:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:216 //line promql/generated_parser.y:225
{ {
yyVAL.label = labels.Label{Name: yyDollar[1].item.Val, Value: yylex.(*parser).unquoteString(yyDollar[3].item.Val)} yyVAL.label = labels.Label{Name: yyDollar[1].item.Val, Value: yylex.(*parser).unquoteString(yyDollar[3].item.Val)}
} }
case 33: case 33:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:218 //line promql/generated_parser.y:227
{ {
yylex.(*parser).unexpected("label set", "string") yylex.(*parser).unexpected("label set", "string")
} }
case 34: case 34:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:220 //line promql/generated_parser.y:229
{ {
yylex.(*parser).unexpected("label set", "\"=\"") yylex.(*parser).unexpected("label set", "\"=\"")
} }
case 35: case 35:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:222 //line promql/generated_parser.y:231
{ {
yylex.(*parser).unexpected("label set", "identifier or \"}\"") yylex.(*parser).unexpected("label set", "identifier or \"}\"")
} }
case 36: case 36:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:227 //line promql/generated_parser.y:236
{ {
yyVAL.strings = yyDollar[2].strings yyVAL.strings = yyDollar[2].strings
} }
case 37: case 37:
yyDollar = yyS[yypt-4 : yypt+1] yyDollar = yyS[yypt-4 : yypt+1]
//line promql/generated_parser.y:229 //line promql/generated_parser.y:238
{ {
yyVAL.strings = yyDollar[2].strings yyVAL.strings = yyDollar[2].strings
} }
case 38: case 38:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:231 //line promql/generated_parser.y:240
{ {
yyVAL.strings = []string{} yyVAL.strings = []string{}
} }
case 39: case 39:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:233 //line promql/generated_parser.y:242
{ {
yylex.(*parser).unexpected("grouping opts", "\"(\"") yylex.(*parser).unexpected("grouping opts", "\"(\"")
} }
case 40: case 40:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:239 //line promql/generated_parser.y:248
{ {
yyVAL.strings = append(yyDollar[1].strings, yyDollar[3].item.Val) yyVAL.strings = append(yyDollar[1].strings, yyDollar[3].item.Val)
} }
case 41: case 41:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:241 //line promql/generated_parser.y:250
{ {
yyVAL.strings = []string{yyDollar[1].item.Val} yyVAL.strings = []string{yyDollar[1].item.Val}
} }
case 42: case 42:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:243 //line promql/generated_parser.y:252
{ {
yylex.(*parser).unexpected("grouping opts", "\",\" or \"}\"") yylex.(*parser).unexpected("grouping opts", "\",\" or \"}\"")
} }
case 43: case 43:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:248 //line promql/generated_parser.y:257
{ {
if !isLabel(yyDollar[1].item.Val) { if !isLabel(yyDollar[1].item.Val) {
yylex.(*parser).unexpected("grouping opts", "label") yylex.(*parser).unexpected("grouping opts", "label")
@ -890,10 +897,132 @@ yydefault:
} }
case 44: case 44:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:255 //line promql/generated_parser.y:264
{ {
yylex.(*parser).unexpected("grouping opts", "label") yylex.(*parser).unexpected("grouping opts", "label")
} }
case 68:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:297
{
yylex.(*parser).generatedParserResult = &seriesDescription{
labels: yyDollar[1].labels,
values: yyDollar[2].series,
}
}
case 69:
yyDollar = yyS[yypt-0 : yypt+1]
//line promql/generated_parser.y:307
{
yyVAL.series = []sequenceValue{}
}
case 70:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:309
{
yyVAL.series = append(yyDollar[1].series, yyDollar[3].series...)
}
case 71:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:311
{
yyVAL.series = yyDollar[1].series
}
case 72:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:313
{
yylex.(*parser).unexpected("series values", "")
}
case 73:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:318
{
yyVAL.series = []sequenceValue{{omitted: true}}
}
case 74:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:320
{
yyVAL.series = []sequenceValue{}
for i := uint64(0); i < yyDollar[3].uint; i++ {
yyVAL.series = append(yyVAL.series, sequenceValue{omitted: true})
}
}
case 75:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:327
{
yyVAL.series = []sequenceValue{{value: yyDollar[1].float}}
}
case 76:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/generated_parser.y:329
{
yyVAL.series = []sequenceValue{}
for i := uint64(0); i <= yyDollar[3].uint; i++ {
yyVAL.series = append(yyVAL.series, sequenceValue{value: yyDollar[1].float})
}
}
case 77:
yyDollar = yyS[yypt-4 : yypt+1]
//line promql/generated_parser.y:336
{
yyVAL.series = []sequenceValue{}
for i := uint64(0); i <= yyDollar[4].uint; i++ {
yyVAL.series = append(yyVAL.series, sequenceValue{value: yyDollar[1].float})
yyDollar[1].float += yyDollar[2].float
}
}
case 78:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:345
{
var err error
yyVAL.uint, err = strconv.ParseUint(yyDollar[1].item.Val, 10, 64)
if err != nil {
yylex.(*parser).errorf("invalid repitition in series values: %s", err)
}
}
case 79:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:356
{
yyVAL.float = yyDollar[2].float
}
case 80:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/generated_parser.y:358
{
yyVAL.float = -yyDollar[2].float
}
case 81:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:363
{
if yyDollar[1].item.Val != "stale" {
yylex.(*parser).unexpected("series values", "number or \"stale\"")
}
yyVAL.float = math.Float64frombits(value.StaleNaN)
}
case 82:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:370
{
yyVAL.float = yyDollar[1].float
}
case 83:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:372
{
yyVAL.float = yyDollar[1].float
}
case 84:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/generated_parser.y:379
{
yyVAL.float = yylex.(*parser).number(yyDollar[1].item.Val)
}
} }
goto yystack /* stack new state and value */ goto yystack /* stack new state and value */
} }

View file

@ -15,10 +15,8 @@ package promql
import ( import (
"fmt" "fmt"
"math"
"os" "os"
"runtime" "runtime"
"sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -27,7 +25,6 @@ import (
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/pkg/value"
"github.com/prometheus/prometheus/util/strutil" "github.com/prometheus/prometheus/util/strutil"
) )
@ -131,108 +128,25 @@ func (v sequenceValue) String() string {
return fmt.Sprintf("%f", v.value) return fmt.Sprintf("%f", v.value)
} }
type seriesDescription struct {
labels labels.Labels
values []sequenceValue
}
// parseSeriesDesc parses the description of a time series. // parseSeriesDesc parses the description of a time series.
func parseSeriesDesc(input string) (labels.Labels, []sequenceValue, error) { func parseSeriesDesc(input string) (labels labels.Labels, values []sequenceValue, err error) {
p := newParser(input) p := newParser(input)
p.lex.seriesDesc = true p.lex.seriesDesc = true
return p.parseSeriesDesc()
}
// parseSeriesDesc parses a description of a time series into its metric and value sequence.
func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err error) {
defer p.recover(&err) defer p.recover(&err)
m = p.metric() result := p.parseGenerated(START_SERIES_DESCRIPTION, []ItemType{EOF}).(*seriesDescription)
const ctx = "series values" labels = result.labels
for { values = result.values
for p.peek().Typ == SPACE {
p.next()
}
if p.peek().Typ == EOF {
break
}
// Extract blanks. return
if p.peek().Typ == BLANK {
p.next()
times := uint64(1)
if p.peek().Typ == TIMES {
p.next()
times, err = strconv.ParseUint(p.expect(NUMBER, ctx).Val, 10, 64)
if err != nil {
p.errorf("invalid repetition in %s: %s", ctx, err)
}
}
for i := uint64(0); i < times; i++ {
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(SPACE, EOF, ctx).Typ; t == EOF {
break
}
continue
}
// Extract values.
sign := 1.0
if t := p.peek().Typ; t == SUB || t == ADD {
if p.next().Typ == SUB {
sign = -1
}
}
var k float64
if t := p.peek().Typ; t == NUMBER {
k = sign * p.number(p.expect(NUMBER, ctx).Val)
} else if t == IDENTIFIER && p.peek().Val == "stale" {
p.next()
k = math.Float64frombits(value.StaleNaN)
} else {
p.errorf("expected number or 'stale' in %s but got %s (value: %s)", ctx, t.desc(), p.peek())
}
vals = append(vals, sequenceValue{
value: k,
})
// If there are no offset repetitions specified, proceed with the next value.
if t := p.peek(); t.Typ == SPACE {
// This ensures there is a space between every value.
continue
} else if t.Typ == EOF {
break
} else if t.Typ != ADD && t.Typ != SUB {
p.errorf("expected next value or relative expansion in %s but got %s (value: %s)", ctx, t.desc(), p.peek())
}
// Expand the repeated offsets into values.
sign = 1.0
if p.next().Typ == SUB {
sign = -1.0
}
offset := sign * p.number(p.expect(NUMBER, ctx).Val)
p.expect(TIMES, ctx)
times, err := strconv.ParseUint(p.expect(NUMBER, ctx).Val, 10, 64)
if err != nil {
p.errorf("invalid repetition in %s: %s", ctx, err)
}
for i := uint64(0); i < times; i++ {
k += offset
vals = append(vals, sequenceValue{
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(SPACE, EOF, ctx).Typ; t == EOF {
break
}
}
return m, vals, nil
} }
// typecheck checks correct typing of the parsed statements or expression. // typecheck checks correct typing of the parsed statements or expression.
@ -794,41 +708,6 @@ func (p *parser) call(name string) *Call {
return &Call{Func: fn, Args: args} return &Call{Func: fn, Args: args}
} }
// labelSet parses a set of label matchers
//
// '{' [ <labelname> '=' <match_string>, ... ] '}'
//
func (p *parser) labelSet() labels.Labels {
return p.parseGenerated(START_LABEL_SET, []ItemType{RIGHT_BRACE, EOF}).(labels.Labels)
}
// metric parses a metric.
//
// <label_set>
// <metric_identifier> [<label_set>]
//
func (p *parser) metric() labels.Labels {
name := ""
var m labels.Labels
t := p.peek().Typ
if t == IDENTIFIER || t == METRIC_IDENTIFIER {
name = p.next().Val
t = p.peek().Typ
}
if t != LEFT_BRACE && name == "" {
p.errorf("missing metric name or metric selector")
}
if t == LEFT_BRACE {
m = p.labelSet()
}
if name != "" {
m = append(m, labels.Label{Name: labels.MetricName, Value: name})
sort.Sort(m)
}
return m
}
// offset parses an offset modifier. // offset parses an offset modifier.
// //
// offset <duration> // offset <duration>