nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: census-instrumentation/opencensus-go
Pull request #345 (2018-01-23 03:12:34)

Exporters expect view tags to be sorted
I noticed tags coming through incorrectly from the Prometheus exporter. That exporter (and possibly others) [expect view tags to be sorted](https://github.com/census-instrumentation/opencensus-go/blob/7a9460ceb1a16caeaedb3d40fcc77176ea9713b2/exporter/stats/prometheus/prometheus.go#L249) since the [collector seems to explicitly sort them in rows](https://github.com/census-instrumentation/opencensus-go/blob/7635ef593d5ab616c7708ba9fe28bb4465d2878e/stats/collector.go#L86)

I could do this from the exporter itself, but I don't think there is any downside to doing it here, keeping the exporter assumption intact. 

kyledj: Updated

Patch:
diff --git a/stats/view.go b/stats/view.go
index 6b51df3..0b374b4 100644
--- a/stats/view.go
+++ b/stats/view.go
@@ -19,6 +19,7 @@ import (
 	"bytes"
 	"fmt"
 	"reflect"
+	"sort"
 	"sync/atomic"
 	"time"
 
@@ -58,10 +59,16 @@ func NewView(name, description string, keys []tag.Key, measure Measure, agg Aggr
 	if err := checkViewName(name); err != nil {
 		return nil, err
 	}
+	var ks []tag.Key
+	if len(keys) > 0 {
+		ks = make([]tag.Key, len(keys))
+		copy(ks, keys)
+		sort.Slice(ks, func(i, j int) bool { return ks[i].Name() < ks[j].Name() })
+	}
 	return &View{
 		name:        name,
 		description: description,
-		tagKeys:     keys,
+		tagKeys:     ks,
 		m:           measure,
 		collector:   &collector{make(map[string]aggregator), agg, window},
 	}, nil


Test patch:
diff --git a/stats/view_test.go b/stats/view_test.go
index 8698b8a..d032c07 100644
--- a/stats/view_test.go
+++ b/stats/view_test.go
@@ -815,6 +815,30 @@ func Test_View_MeasureFloat64_AggregationMean_WindowCumulative(t *testing.T) {
 	}
 }
 
+func TestViewSortedKeys(t *testing.T) {
+	k1, _ := tag.NewKey("a")
+	k2, _ := tag.NewKey("b")
+	k3, _ := tag.NewKey("c")
+	ks := []tag.Key{k1, k3, k2}
+
+	v, err := NewView("sort_keys", "desc sort_keys", ks, nil, MeanAggregation{}, Cumulative{})
+	if err != nil {
+		t.Fatalf("NewView() = %v", err)
+	}
+
+	want := []string{"a", "b", "c"}
+	vks := v.TagKeys()
+	if len(vks) != len(want) {
+		t.Errorf("Keys = %+v; want %+v", vks, want)
+	}
+
+	for i, v := range want {
+		if got, want := v, vks[i].Name(); got != want {
+			t.Errorf("View name = %q; want %q", got, want)
+		}
+	}
+}
+
 // TODO(songya): add tests for AggregationSum and AggregationMean with Interval Window
 
 // containsRow returns true if rows contain r.