Repository: census-instrumentation/opencensus-go
Pull request #1102 (2019-04-11 14:48:08)

replace missing tag with empty values during metric export.


Patch:
diff --git a/stats/view/view_to_metric.go b/stats/view/view_to_metric.go
index 284299f..557c190 100644
--- a/stats/view/view_to_metric.go
+++ b/stats/view/view_to_metric.go
@@ -91,10 +91,19 @@ func viewToMetricDescriptor(v *View) *metricdata.Descriptor {
 	}
 }
 
-func toLabelValues(row *Row) []metricdata.LabelValue {
+func toLabelValues(row *Row, expectedKeys []string) []metricdata.LabelValue {
 	labelValues := []metricdata.LabelValue{}
+	tagMap := make(map[string]string)
 	for _, tag := range row.Tags {
-		labelValues = append(labelValues, metricdata.NewLabelValue(tag.Value))
+		tagMap[tag.Key.Name()] = tag.Value
+	}
+
+	for _, key := range expectedKeys {
+		if val, ok := tagMap[key]; ok {
+			labelValues = append(labelValues, metricdata.NewLabelValue(val))
+		} else {
+			labelValues = append(labelValues, metricdata.LabelValue{})
+		}
 	}
 	return labelValues
 }
@@ -102,7 +111,7 @@ func toLabelValues(row *Row) []metricdata.LabelValue {
 func rowToTimeseries(v *viewInternal, row *Row, now time.Time, startTime time.Time) *metricdata.TimeSeries {
 	return &metricdata.TimeSeries{
 		Points:      []metricdata.Point{row.Data.toPoint(v.metricDescriptor.Type, now)},
-		LabelValues: toLabelValues(row),
+		LabelValues: toLabelValues(row, v.metricDescriptor.LabelKeys),
 		StartTime:   startTime,
 	}
 }


Test patch:
diff --git a/stats/view/view_to_metric_test.go b/stats/view/view_to_metric_test.go
index d9a5a3d..2f2c723 100644
--- a/stats/view/view_to_metric_test.go
+++ b/stats/view/view_to_metric_test.go
@@ -40,19 +40,21 @@ type testToMetrics struct {
 
 var (
 	// tag objects.
-	tk1         tag.Key
-	tk2         tag.Key
-	tk3         tag.Key
-	tk1v1       tag.Tag
-	tk1v2       tag.Tag
-	tk2v2       tag.Tag
-	tk3v3       tag.Tag
-	tags        []tag.Tag
-	labelValues []metricdata.LabelValue
-	labelKeys   []string
+	tk1   tag.Key
+	tk2   tag.Key
+	tk3   tag.Key
+	tk1v1 tag.Tag
+	tk2v2 tag.Tag
+	tags  []tag.Tag
+
+	labelValues      []metricdata.LabelValue
+	emptyLabelValues []metricdata.LabelValue
+
+	labelKeys []string
 
-	recordsInt64   []recordValWithTag
-	recordsFloat64 []recordValWithTag
+	recordsInt64        []recordValWithTag
+	recordsFloat64      []recordValWithTag
+	recordsFloat64WoTag []recordValWithTag
 
 	// distribution objects.
 	aggDist *Aggregation
@@ -73,6 +75,7 @@ var (
 	viewTypeInt64Sum                    *View
 	viewTypeFloat64LastValue            *View
 	viewTypeInt64LastValue              *View
+	viewRecordWithoutLabel              *View
 	mdTypeFloat64CumulativeDistribution metricdata.Descriptor
 	mdTypeInt64CumulativeDistribution   metricdata.Descriptor
 	mdTypeInt64CumulativeCount          metricdata.Descriptor
@@ -81,6 +84,7 @@ var (
 	mdTypeFloat64CumulativeSum          metricdata.Descriptor
 	mdTypeInt64CumulativeLastValue      metricdata.Descriptor
 	mdTypeFloat64CumulativeLastValue    metricdata.Descriptor
+	mdTypeRecordWithoutLabel            metricdata.Descriptor
 )
 
 const (
@@ -92,9 +96,9 @@ const (
 	nameFloat64SumM1       = "viewToMetricTest_Float64_Sum/m1"
 	nameInt64LastValueM1   = "viewToMetricTest_Int64_LastValue/m1"
 	nameFloat64LastValueM1 = "viewToMetricTest_Float64_LastValue/m1"
+	nameRecordWithoutLabel = "viewToMetricTest_RecordWithoutLabel/m1"
 	v1                     = "v1"
 	v2                     = "v2"
-	v3                     = "v3"
 )
 
 func init() {
@@ -110,15 +114,17 @@ func initTags() {
 	tk2, _ = tag.NewKey("k2")
 	tk3, _ = tag.NewKey("k3")
 	tk1v1 = tag.Tag{Key: tk1, Value: v1}
-	tk1v2 = tag.Tag{Key: tk1, Value: v2}
 	tk2v2 = tag.Tag{Key: tk2, Value: v2}
-	tk3v3 = tag.Tag{Key: tk3, Value: v3}
 
 	tags = []tag.Tag{tk1v1, tk2v2}
 	labelValues = []metricdata.LabelValue{
 		{Value: v1, Present: true},
 		{Value: v2, Present: true},
 	}
+	emptyLabelValues = []metricdata.LabelValue{
+		{Value: "", Present: false},
+		{Value: "", Present: false},
+	}
 	labelKeys = []string{tk1.Name(), tk2.Name()}
 
 	recordsInt64 = []recordValWithTag{
@@ -129,6 +135,10 @@ func initTags() {
 		{tags: tags, value: float64(1.5)},
 		{tags: tags, value: float64(5.4)},
 	}
+	recordsFloat64WoTag = []recordValWithTag{
+		{value: float64(1.5)},
+		{value: float64(5.4)},
+	}
 }
 
 func initAgg() {
@@ -189,6 +199,12 @@ func initViews() {
 		Measure:     stats.Float64(nameFloat64LastValueM1, "", stats.UnitDimensionless),
 		Aggregation: aggL,
 	}
+	viewRecordWithoutLabel = &View{
+		Name:        nameRecordWithoutLabel,
+		TagKeys:     []tag.Key{tk1, tk2},
+		Measure:     stats.Float64(nameRecordWithoutLabel, "", stats.UnitDimensionless),
+		Aggregation: aggL,
+	}
 }
 
 func initMetricDescriptors() {
@@ -225,6 +241,10 @@ func initMetricDescriptors() {
 		Name: nameFloat64LastValueM1, Description: "", Unit: metricdata.UnitDimensionless,
 		Type: metricdata.TypeGaugeFloat64, LabelKeys: labelKeys,
 	}
+	mdTypeRecordWithoutLabel = metricdata.Descriptor{
+		Name: nameRecordWithoutLabel, Description: "", Unit: metricdata.UnitDimensionless,
+		Type: metricdata.TypeGaugeFloat64, LabelKeys: labelKeys,
+	}
 }
 
 func Test_ViewToMetric(t *testing.T) {
@@ -375,6 +395,21 @@ func Test_ViewToMetric(t *testing.T) {
 				},
 			},
 		},
+		{
+			view:        viewRecordWithoutLabel,
+			recordValue: recordsFloat64WoTag,
+			wantMetric: &metricdata.Metric{
+				Descriptor: mdTypeRecordWithoutLabel,
+				TimeSeries: []*metricdata.TimeSeries{
+					{Points: []metricdata.Point{
+						metricdata.NewFloat64Point(now, 5.4),
+					},
+						LabelValues: emptyLabelValues,
+						StartTime:   time.Time{},
+					},
+				},
+			},
+		},
 	}
 
 	wantMetrics := []*metricdata.Metric{}