Merge pull request #2869 from Gouthamve/lblspc

parser: Support spaces everywhere
reviewable/pr2906/r1
Fabian Reinartz 8 years ago committed by GitHub
commit ad86c389cb

@ -30,11 +30,13 @@ import (
func (l *lexer) Lex() int { func (l *lexer) Lex() int {
const ( const (
lstateInit = iota lstateInit = iota
lstateName
lstateValue lstateValue
lstateTimestamp lstateTimestamp
lstateLabels lstateLabels
lstateLName lstateLName
lstateLValue lstateLValue
lstateLValueIn
) )
s := lstateInit s := lstateInit
@ -53,7 +55,7 @@ S [a-zA-Z]
L [a-zA-Z_] L [a-zA-Z_]
M [a-zA-Z_:] M [a-zA-Z_:]
%x lstateValue lstateTimestamp lstateLabels lstateLName lstateLValue %x lstateName lstateValue lstateTimestamp lstateLabels lstateLName lstateLValue lstateLValueIn
%yyc c %yyc c
@ -67,23 +69,30 @@ M [a-zA-Z_:]
#[^\r\n]*\n l.mstart = l.i #[^\r\n]*\n l.mstart = l.i
[\r\n \t]+ l.mstart = l.i [\r\n \t]+ l.mstart = l.i
{S}({M}|{D})*\{ s = lstateLabels {S}({M}|{D})* s = lstateName
l.offsets = append(l.offsets, l.i-1)
{S}({M}|{D})* s = lstateValue
l.mend = l.i
l.offsets = append(l.offsets, l.i) l.offsets = append(l.offsets, l.i)
l.mend = l.i
<lstateName>([ \t]*)\{ s = lstateLabels
<lstateName>[ \t]+ s = lstateValue
l.vstart = l.i
<lstateLabels>[ \t]+ <lstateLabels>[ \t]+
<lstateLabels>,?\} s = lstateValue <lstateLabels>,?\} s = lstateValue
l.mend = l.i l.mend = l.i
<lstateLabels>,? s = lstateLName <lstateLabels>(,?[ \t]*) s = lstateLName
l.offsets = append(l.offsets, l.i) l.offsets = append(l.offsets, l.i)
<lstateLName>{S}({L}|{D})*= s = lstateLValue <lstateLName>{S}({L}|{D})* l.offsets = append(l.offsets, l.i)
l.offsets = append(l.offsets, l.i-1) <lstateLName>[ \t]*= s = lstateLValue
<lstateLValue>\"(\\.|[^\\"]|\0)*\" s = lstateLabels <lstateLValue>[ \t]+
if !utf8.Valid(l.b[l.offsets[len(l.offsets)-1]+2:l.i-1]) { <lstateLValue>\" s = lstateLValueIn
l.offsets = append(l.offsets, l.i)
<lstateLValueIn>(\\.|[^\\"]|\0)*\" s = lstateLabels
if !utf8.Valid(l.b[l.offsets[len(l.offsets)-1]:l.i-1]) {
l.err = fmt.Errorf("Invalid UTF-8 label value.") l.err = fmt.Errorf("Invalid UTF-8 label value.")
return -1 return -1
} }

@ -30,11 +30,13 @@ import (
func (l *lexer) Lex() int { func (l *lexer) Lex() int {
const ( const (
lstateInit = iota lstateInit = iota
lstateName
lstateValue lstateValue
lstateTimestamp lstateTimestamp
lstateLabels lstateLabels
lstateLName lstateLName
lstateLValue lstateLValue
lstateLValueIn
) )
s := lstateInit s := lstateInit
@ -54,16 +56,20 @@ yystate0:
panic(fmt.Errorf(`invalid start condition %d`, yyt)) panic(fmt.Errorf(`invalid start condition %d`, yyt))
case 0: // start condition: INITIAL case 0: // start condition: INITIAL
goto yystart1 goto yystart1
case 1: // start condition: lstateValue case 1: // start condition: lstateName
goto yystart8 goto yystart7
case 2: // start condition: lstateTimestamp case 2: // start condition: lstateValue
goto yystart14 goto yystart10
case 3: // start condition: lstateLabels case 3: // start condition: lstateTimestamp
goto yystart19 goto yystart16
case 4: // start condition: lstateLName case 4: // start condition: lstateLabels
goto yystart23 goto yystart21
case 5: // start condition: lstateLValue case 5: // start condition: lstateLName
goto yystart26 goto yystart26
case 6: // start condition: lstateLValue
goto yystart30
case 7: // start condition: lstateLValueIn
goto yystart33
} }
goto yystate0 // silence unused label error goto yystate0 // silence unused label error
@ -116,225 +122,299 @@ yystate6:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule5 goto yyrule4
case c == '{':
goto yystate7
case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
goto yystate6 goto yystate6
} }
goto yystate7 // silence unused label error
yystate7: yystate7:
c = l.next() c = l.next()
goto yyrule4 yystart7:
switch {
default:
goto yyabort
case c == '\t' || c == ' ':
goto yystate8
case c == '{':
goto yystate9
}
goto yystate8 // silence unused label error
yystate8: yystate8:
c = l.next() c = l.next()
yystart8: switch {
default:
goto yyrule6
case c == '\t' || c == ' ':
goto yystate8
case c == '{':
goto yystate9
}
yystate9:
c = l.next()
goto yyrule5
goto yystate10 // silence unused label error
yystate10:
c = l.next()
yystart10:
switch { switch {
default: default:
goto yyabort goto yyabort
case c == 'N': case c == 'N':
goto yystate11 goto yystate13
case c == '\t' || c == ' ': case c == '\t' || c == ' ':
goto yystate10 goto yystate12
case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'M' || c >= 'O' && c <= 'ÿ': case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'M' || c >= 'O' && c <= 'ÿ':
goto yystate9 goto yystate11
} }
yystate9: yystate11:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule13 goto yyrule17
case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'ÿ': case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'ÿ':
goto yystate9 goto yystate11
} }
yystate10: yystate12:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule11 goto yyrule15
case c == '\t' || c == ' ': case c == '\t' || c == ' ':
goto yystate10 goto yystate12
} }
yystate11: yystate13:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule13 goto yyrule17
case c == 'a': case c == 'a':
goto yystate12 goto yystate14
case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= '`' || c >= 'b' && c <= 'ÿ': case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= '`' || c >= 'b' && c <= 'ÿ':
goto yystate9 goto yystate11
} }
yystate12: yystate14:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule13 goto yyrule17
case c == 'N': case c == 'N':
goto yystate13 goto yystate15
case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'M' || c >= 'O' && c <= 'ÿ': case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'M' || c >= 'O' && c <= 'ÿ':
goto yystate9 goto yystate11
} }
yystate13: yystate15:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule12 goto yyrule16
case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'ÿ': case c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c >= '!' && c <= 'ÿ':
goto yystate9 goto yystate11
} }
goto yystate14 // silence unused label error goto yystate16 // silence unused label error
yystate14: yystate16:
c = l.next() c = l.next()
yystart14: yystart16:
switch { switch {
default: default:
goto yyabort goto yyabort
case c == '\n' || c == '\r': case c == '\n' || c == '\r':
goto yystate17 goto yystate19
case c == '\t' || c == ' ': case c == '\t' || c == ' ':
goto yystate16 goto yystate18
case c == '\x00': case c == '\x00':
goto yystate15 goto yystate17
case c >= '0' && c <= '9': case c >= '0' && c <= '9':
goto yystate18 goto yystate20
} }
yystate15: yystate17:
c = l.next() c = l.next()
goto yyrule17 goto yyrule21
yystate16: yystate18:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule14 goto yyrule18
case c == '\t' || c == ' ': case c == '\t' || c == ' ':
goto yystate16 goto yystate18
} }
yystate17: yystate19:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule16 goto yyrule20
case c == '\n' || c == '\r': case c == '\n' || c == '\r':
goto yystate17 goto yystate19
} }
yystate18: yystate20:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule15 goto yyrule19
case c >= '0' && c <= '9': case c >= '0' && c <= '9':
goto yystate18 goto yystate20
} }
goto yystate19 // silence unused label error goto yystate21 // silence unused label error
yystate19: yystate21:
c = l.next() c = l.next()
yystart19: yystart21:
switch { switch {
default: default:
goto yyrule8 goto yyrule9
case c == ',': case c == ',':
goto yystate21 goto yystate23
case c == '\t' || c == ' ': case c == '\t' || c == ' ':
goto yystate20
case c == '}':
goto yystate22 goto yystate22
case c == '}':
goto yystate25
} }
yystate20: yystate22:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule6 goto yyrule7
case c == '\t' || c == ' ': case c == '\t' || c == ' ':
goto yystate20 goto yystate22
} }
yystate21: yystate23:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyrule8 goto yyrule9
case c == '\t' || c == ' ':
goto yystate24
case c == '}': case c == '}':
goto yystate22 goto yystate25
} }
yystate22: yystate24:
c = l.next() c = l.next()
goto yyrule7 switch {
default:
goto yyrule9
case c == '\t' || c == ' ':
goto yystate24
}
goto yystate23 // silence unused label error yystate25:
yystate23: c = l.next()
goto yyrule8
goto yystate26 // silence unused label error
yystate26:
c = l.next() c = l.next()
yystart23: yystart26:
switch { switch {
default: default:
goto yyabort goto yyabort
case c == '=':
goto yystate28
case c == '\t' || c == ' ':
goto yystate27
case c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': case c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z':
goto yystate24 goto yystate29
} }
yystate24: yystate27:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyabort goto yyabort
case c == '=': case c == '=':
goto yystate25 goto yystate28
case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': case c == '\t' || c == ' ':
goto yystate24 goto yystate27
} }
yystate25: yystate28:
c = l.next() c = l.next()
goto yyrule9 goto yyrule11
goto yystate26 // silence unused label error yystate29:
yystate26:
c = l.next() c = l.next()
yystart26: switch {
default:
goto yyrule10
case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
goto yystate29
}
goto yystate30 // silence unused label error
yystate30:
c = l.next()
yystart30:
switch { switch {
default: default:
goto yyabort goto yyabort
case c == '"': case c == '"':
goto yystate27 goto yystate32
case c == '\t' || c == ' ':
goto yystate31
} }
yystate27: yystate31:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yystate27 // c >= '\x00' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ' goto yyrule12
case c == '\t' || c == ' ':
goto yystate31
}
yystate32:
c = l.next()
goto yyrule13
goto yystate33 // silence unused label error
yystate33:
c = l.next()
yystart33:
switch {
default:
goto yystate34 // c >= '\x00' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ'
case c == '"': case c == '"':
goto yystate28 goto yystate35
case c == '\\': case c == '\\':
goto yystate29 goto yystate36
} }
yystate28: yystate34:
c = l.next() c = l.next()
goto yyrule10 switch {
default:
goto yystate34 // c >= '\x00' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ'
case c == '"':
goto yystate35
case c == '\\':
goto yystate36
}
yystate29: yystate35:
c = l.next()
goto yyrule14
yystate36:
c = l.next() c = l.next()
switch { switch {
default: default:
goto yyabort goto yyabort
case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ':
goto yystate27 goto yystate34
} }
yyrule1: // \0 yyrule1: // \0
@ -351,62 +431,80 @@ yyrule3: // [\r\n \t]+
l.mstart = l.i l.mstart = l.i
goto yystate0 goto yystate0
} }
yyrule4: // {S}({M}|{D})*\{ yyrule4: // {S}({M}|{D})*
{
s = lstateName
l.offsets = append(l.offsets, l.i)
l.mend = l.i
goto yystate0
}
yyrule5: // ([ \t]*)\{
{ {
s = lstateLabels s = lstateLabels
l.offsets = append(l.offsets, l.i-1)
goto yystate0 goto yystate0
} }
yyrule5: // {S}({M}|{D})* yyrule6: // [ \t]+
{ {
s = lstateValue s = lstateValue
l.mend = l.i l.vstart = l.i
l.offsets = append(l.offsets, l.i)
goto yystate0 goto yystate0
} }
yyrule6: // [ \t]+ yyrule7: // [ \t]+
goto yystate0 goto yystate0
yyrule7: // ,?\} yyrule8: // ,?\}
{ {
s = lstateValue s = lstateValue
l.mend = l.i l.mend = l.i
goto yystate0 goto yystate0
} }
yyrule8: // ,? yyrule9: // (,?[ \t]*)
{ {
s = lstateLName s = lstateLName
l.offsets = append(l.offsets, l.i) l.offsets = append(l.offsets, l.i)
goto yystate0 goto yystate0
} }
yyrule9: // {S}({L}|{D})*= yyrule10: // {S}({L}|{D})*
{
l.offsets = append(l.offsets, l.i)
goto yystate0
}
yyrule11: // [ \t]*=
{ {
s = lstateLValue s = lstateLValue
l.offsets = append(l.offsets, l.i-1)
goto yystate0 goto yystate0
} }
yyrule10: // \"(\\.|[^\\"]|\0)*\" yyrule12: // [ \t]+
goto yystate0
yyrule13: // \"
{
s = lstateLValueIn
l.offsets = append(l.offsets, l.i)
goto yystate0
}
yyrule14: // (\\.|[^\\"]|\0)*\"
{ {
s = lstateLabels s = lstateLabels
if !utf8.Valid(l.b[l.offsets[len(l.offsets)-1]+2 : l.i-1]) { if !utf8.Valid(l.b[l.offsets[len(l.offsets)-1] : l.i-1]) {
l.err = fmt.Errorf("Invalid UTF-8 label value.") l.err = fmt.Errorf("Invalid UTF-8 label value.")
return -1 return -1
} }
l.offsets = append(l.offsets, l.i-1) l.offsets = append(l.offsets, l.i-1)
goto yystate0 goto yystate0
} }
yyrule11: // [ \t]+ yyrule15: // [ \t]+
{ {
l.vstart = l.i l.vstart = l.i
goto yystate0 goto yystate0
} }
yyrule12: // (NaN) yyrule16: // (NaN)
{ {
l.val = math.Float64frombits(value.NormalNaN) l.val = math.Float64frombits(value.NormalNaN)
s = lstateTimestamp s = lstateTimestamp
goto yystate0 goto yystate0
} }
yyrule13: // [^\n \t\r]+ yyrule17: // [^\n \t\r]+
{ {
// We don't parse strictly correct floats as the conversion // We don't parse strictly correct floats as the conversion
// repeats the effort anyway. // repeats the effort anyway.
@ -417,12 +515,12 @@ yyrule13: // [^\n \t\r]+
s = lstateTimestamp s = lstateTimestamp
goto yystate0 goto yystate0
} }
yyrule14: // [ \t]+ yyrule18: // [ \t]+
{ {
l.tstart = l.i l.tstart = l.i
goto yystate0 goto yystate0
} }
yyrule15: // {D}+ yyrule19: // {D}+
{ {
ts, err := strconv.ParseInt(yoloString(l.b[l.tstart:l.i]), 10, 64) ts, err := strconv.ParseInt(yoloString(l.b[l.tstart:l.i]), 10, 64)
if err != nil { if err != nil {
@ -432,12 +530,12 @@ yyrule15: // {D}+
l.ts = &ts l.ts = &ts
goto yystate0 goto yystate0
} }
yyrule16: // [\r\n]+ yyrule20: // [\r\n]+
{ {
l.nextMstart = l.i l.nextMstart = l.i
return 1 return 1
} }
yyrule17: // \0 yyrule21: // \0
{ {
return 1 return 1

@ -110,12 +110,13 @@ func (p *Parser) Metric(l *labels.Labels) string {
Value: s[:p.l.offsets[0]-p.l.mstart], Value: s[:p.l.offsets[0]-p.l.mstart],
}) })
for i := 1; i < len(p.l.offsets); i += 3 { for i := 1; i < len(p.l.offsets); i += 4 {
a := p.l.offsets[i] - p.l.mstart a := p.l.offsets[i] - p.l.mstart
b := p.l.offsets[i+1] - p.l.mstart b := p.l.offsets[i+1] - p.l.mstart
c := p.l.offsets[i+2] - p.l.mstart c := p.l.offsets[i+2] - p.l.mstart
d := p.l.offsets[i+3] - p.l.mstart
*l = append(*l, labels.Label{Name: s[a:b], Value: s[b+2 : c]}) *l = append(*l, labels.Label{Name: s[a:b], Value: s[c:d]})
} }
sort.Sort((*l)[1:]) sort.Sort((*l)[1:])

@ -33,6 +33,12 @@ func TestParse(t *testing.T) {
go_gc_duration_seconds{quantile="0"} 4.9351e-05 go_gc_duration_seconds{quantile="0"} 4.9351e-05
go_gc_duration_seconds{quantile="0.25",} 7.424100000000001e-05 go_gc_duration_seconds{quantile="0.25",} 7.424100000000001e-05
go_gc_duration_seconds{quantile="0.5",a="b"} 8.3835e-05 go_gc_duration_seconds{quantile="0.5",a="b"} 8.3835e-05
go_gc_duration_seconds{quantile="0.8", a="b"} 8.3835e-05
go_gc_duration_seconds{ quantile="0.9", a="b"} 8.3835e-05
go_gc_duration_seconds{ quantile="1.0", a="b" } 8.3835e-05
go_gc_duration_seconds { quantile="1.0", a="b" } 8.3835e-05
go_gc_duration_seconds { quantile= "1.0", a= "b" } 8.3835e-05
go_gc_duration_seconds { quantile = "1.0", a = "b" } 8.3835e-05
go_gc_duration_seconds_count 99 go_gc_duration_seconds_count 99
some:aggregate:rate5m{a_b="c"} 1 some:aggregate:rate5m{a_b="c"} 1
# HELP go_goroutines Number of goroutines that currently exist. # HELP go_goroutines Number of goroutines that currently exist.
@ -60,6 +66,30 @@ go_goroutines 33 123123`
m: `go_gc_duration_seconds{quantile="0.5",a="b"}`, m: `go_gc_duration_seconds{quantile="0.5",a="b"}`,
v: 8.3835e-05, v: 8.3835e-05,
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.5", "a", "b"), lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.5", "a", "b"),
}, {
m: `go_gc_duration_seconds{quantile="0.8", a="b"}`,
v: 8.3835e-05,
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.8", "a", "b"),
}, {
m: `go_gc_duration_seconds{ quantile="0.9", a="b"}`,
v: 8.3835e-05,
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.9", "a", "b"),
}, {
m: `go_gc_duration_seconds{ quantile="1.0", a="b" }`,
v: 8.3835e-05,
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"),
}, {
m: `go_gc_duration_seconds { quantile="1.0", a="b" }`,
v: 8.3835e-05,
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"),
}, {
m: `go_gc_duration_seconds { quantile= "1.0", a= "b" }`,
v: 8.3835e-05,
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"),
}, {
m: `go_gc_duration_seconds { quantile = "1.0", a = "b" }`,
v: 8.3835e-05,
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"),
}, { }, {
m: `go_gc_duration_seconds_count`, m: `go_gc_duration_seconds_count`,
v: 99, v: 99,
@ -139,6 +169,7 @@ func TestParseErrors(t *testing.T) {
p := New([]byte(c.input)) p := New([]byte(c.input))
for p.Next() { for p.Next() {
} }
require.NotNil(t, p.Err())
require.Equal(t, c.err, p.Err().Error()) require.Equal(t, c.err, p.Err().Error())
} }
} }

Loading…
Cancel
Save