Skip to content

Commit be8a747

Browse files
authored
fix(utf8): Fix multiple metric name inside braces validation (#691)
* Fix multiple metric name inside braces validation Signed-off-by: Federico Torres <federico.torres@grafana.com> --------- Signed-off-by: Federico Torres <federico.torres@grafana.com>
1 parent bf4843e commit be8a747

File tree

2 files changed

+56
-3
lines changed

2 files changed

+56
-3
lines changed

expfmt/text_parse.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ type TextParser struct {
7575
// count and sum of that summary/histogram.
7676
currentIsSummaryCount, currentIsSummarySum bool
7777
currentIsHistogramCount, currentIsHistogramSum bool
78-
currentMetricIsInsideBraces bool
78+
// These indicate if the metric name from the current line being parsed is inside
79+
// braces and if that metric name was found respectively.
80+
currentMetricIsInsideBraces, currentMetricInsideBracesIsPresent bool
7981
}
8082

8183
// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
@@ -147,6 +149,7 @@ func (p *TextParser) reset(in io.Reader) {
147149
func (p *TextParser) startOfLine() stateFn {
148150
p.lineCount++
149151
p.currentMetricIsInsideBraces = false
152+
p.currentMetricInsideBracesIsPresent = false
150153
if p.skipBlankTab(); p.err != nil {
151154
// This is the only place that we expect to see io.EOF,
152155
// which is not an error but the signal that we are done.
@@ -301,17 +304,24 @@ func (p *TextParser) startLabelName() stateFn {
301304
}
302305
if p.currentByte != '=' {
303306
if p.currentMetricIsInsideBraces {
304-
if p.currentMF != nil && p.currentMF.GetName() != p.currentToken.String() {
305-
p.parseError(fmt.Sprintf("multiple metric names %s %s", p.currentMF.GetName(), p.currentToken.String()))
307+
if p.currentMetricInsideBracesIsPresent {
308+
p.parseError(fmt.Sprintf("multiple metric names for metric %q", p.currentMF.GetName()))
306309
return nil
307310
}
308311
switch p.currentByte {
309312
case ',':
310313
p.setOrCreateCurrentMF()
314+
if p.currentMF.Type == nil {
315+
p.currentMF.Type = dto.MetricType_UNTYPED.Enum()
316+
}
311317
p.currentMetric = &dto.Metric{}
318+
p.currentMetricInsideBracesIsPresent = true
312319
return p.startLabelName
313320
case '}':
314321
p.setOrCreateCurrentMF()
322+
if p.currentMF.Type == nil {
323+
p.currentMF.Type = dto.MetricType_UNTYPED.Enum()
324+
}
315325
p.currentMetric = &dto.Metric{}
316326
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
317327
p.currentLabelPairs = nil

expfmt/text_parse_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,49 @@ request_duration_microseconds_count 2693
594594
},
595595
},
596596
},
597+
// 11: Multiple minimal metrics with quoted metric names.
598+
{
599+
in: `
600+
{"name.1"} 1
601+
{"name.2"} 1
602+
{"name.3"} 1
603+
`,
604+
out: []*dto.MetricFamily{
605+
{
606+
Name: proto.String("name.1"),
607+
Type: dto.MetricType_UNTYPED.Enum(),
608+
Metric: []*dto.Metric{
609+
{
610+
Untyped: &dto.Untyped{
611+
Value: proto.Float64(1),
612+
},
613+
},
614+
},
615+
},
616+
{
617+
Name: proto.String("name.2"),
618+
Type: dto.MetricType_UNTYPED.Enum(),
619+
Metric: []*dto.Metric{
620+
{
621+
Untyped: &dto.Untyped{
622+
Value: proto.Float64(1),
623+
},
624+
},
625+
},
626+
},
627+
{
628+
Name: proto.String("name.3"),
629+
Type: dto.MetricType_UNTYPED.Enum(),
630+
Metric: []*dto.Metric{
631+
{
632+
Untyped: &dto.Untyped{
633+
Value: proto.Float64(1),
634+
},
635+
},
636+
},
637+
},
638+
},
639+
},
597640
}
598641

599642
for i, scenario := range scenarios {

0 commit comments

Comments
 (0)