@@ -283,7 +283,6 @@ func (r *rootRegistry) Each(f MetricVisitor) {
283283 name = metricWithTags .name
284284 tags = make (Tags , len (metricWithTags .tags ))
285285 copy (tags , metricWithTags .tags )
286- sort .Sort (tags )
287286 } else {
288287 // Metric was added to rcrowley registry outside of our registry.
289288 // This is likely a go runtime metric (nothing else is exposed).
@@ -300,7 +299,7 @@ func (r *rootRegistry) Each(f MetricVisitor) {
300299}
301300
302301func (r * rootRegistry ) Unregister (name string , tags ... Tag ) {
303- metricID := toMetricTagsID (name , tags )
302+ metricID := toMetricTagsID (name , newSortedTags ( tags ) )
304303 r .registry .Unregister (string (metricID ))
305304}
306305
@@ -341,11 +340,12 @@ func DefaultSample() metrics.Sample {
341340}
342341
343342func (r * rootRegistry ) registerMetric (name string , tags Tags ) string {
344- metricID := toMetricTagsID (name , tags )
343+ sortedTags := newSortedTags (tags )
344+ metricID := toMetricTagsID (name , sortedTags )
345345 r .idToMetricMutex .Lock ()
346346 r .idToMetricWithTags [metricID ] = metricWithTags {
347347 name : name ,
348- tags : tags ,
348+ tags : sortedTags ,
349349 }
350350 r .idToMetricMutex .Unlock ()
351351 return string (metricID )
@@ -364,10 +364,9 @@ type metricTagsID string
364364
365365// toMetricTagsID generates the metricTagsID identifier for the metricWithTags. A unique {metricName, set<Tag>} input will
366366// generate a unique output. This implementation tries to minimize memory allocation and runtime.
367+ // The ID is created by adding the tags in the order they are provided (this means that, if the caller wants a specific set of tags to always
368+ // result in the same ID, they must sort the Tags before providing them to this function).
367369func toMetricTagsID (name string , tags Tags ) metricTagsID {
368- // TODO(maybe): Ensure tags is already sorted when it comes in so we can remove this.
369- sort .Sort (tags )
370-
371370 // calculate how large to make our byte buffer below
372371 bufSize := len (name )
373372 for _ , t := range tags {
@@ -382,3 +381,10 @@ func toMetricTagsID(name string, tags Tags) metricTagsID {
382381 }
383382 return metricTagsID (buf .Bytes ())
384383}
384+
385+ // newSortedTags copies the tag slice before sorting so that in-place mutation does not affect the input slice.
386+ func newSortedTags (tags Tags ) Tags {
387+ tagsCopy := append (tags [:0 :0 ], tags ... )
388+ sort .Sort (tagsCopy )
389+ return tagsCopy
390+ }
0 commit comments