ronantakizawa/codereview-bench huggingface dataset:
Repository: prometheus/prometheus
File: template/template.go (Go)

Code before:
				v, err := common_templates.ConvertToFloat(i)
				if err != nil {
					return "", err
				}
				return fmt.Sprintf("%.4g%%", v*100), nil
			},
			"humanizeTimestamp": common_templates.HumanizeTimestamp,
			"toTime": func(i interface{}) (*time.Time, error) {
				v, err := common_templates.ConvertToFloat(i)
				if err != nil {
					return nil, err
				}

				return floatToTime(v)
			},
			"toDuration": func(i interface{}) (*time.Duration, error) {
				v, err := common_templates.ConvertToFloat(i)
				if err != nil {
					return nil, err
				}
				d := time.Duration(v * float64(time.Second))
				return &d, nil
			},
			"now": func() float64 {
				now := time.Now()
				return float64(now.Unix()) + float64(now.Nanosecond())/float64(time.Second)
			},
			"pathPrefix": func() string {
				return externalURL.Path
			},
			"externalURL": func() string {
				return externalURL.String()
			},
			"parseDuration": func(d string) (float64, error) {
				v, err := model.ParseDurationAllowNegative(d)
				if err != nil {
					return 0, err
				}
				return float64(time.Duration(v)) / float64(time.Second), nil
			},
		},
		options: options,
	}
}

// AlertTemplateData returns the interface to be used in expanding the template.
func AlertTemplateData(labels, externalLabels map[string]string, externalURL string, smpl promql.Sample) interface{} {
	res := struct {
		Labels         map[string]string
		ExternalLabels map[string]string
		ExternalURL    string

Review comment (suggestion):
With my idea in the other comment thread, this should now look like this:

```suggestion
				return float64(timestamp) / 1000
```

Code after:
				v, err := common_templates.ConvertToFloat(i)
				if err != nil {
					return "", err
				}
				return fmt.Sprintf("%.4g%%", v*100), nil
			},
			"humanizeTimestamp": common_templates.HumanizeTimestamp,
			"toTime": func(i interface{}) (*time.Time, error) {
				v, err := common_templates.ConvertToFloat(i)
				if err != nil {
					return nil, err
				}

				return floatToTime(v)
			},
			"toDuration": func(i interface{}) (*time.Duration, error) {
				v, err := common_templates.ConvertToFloat(i)
				if err != nil {
					return nil, err
				}
				d := time.Duration(v * float64(time.Second))
				return &d, nil
			},
			"now": func() float64 {
				return float64(timestamp) / 1000.0
			},
			"pathPrefix": func() string {
				return externalURL.Path
			},
			"externalURL": func() string {
				return externalURL.String()
			},
			"parseDuration": func(d string) (float64, error) {
				v, err := model.ParseDurationAllowNegative(d)
				if err != nil {
					return 0, err
				}
				return float64(time.Duration(v)) / float64(time.Second), nil
			},
		},
		options: options,
	}
}

// AlertTemplateData returns the interface to be used in expanding the template.
func AlertTemplateData(labels, externalLabels map[string]string, externalURL string, smpl promql.Sample) interface{} {
	res := struct {
		Labels         map[string]string
		ExternalLabels map[string]string
		ExternalURL    string
		Value          interface{}
Repository: prometheus/prometheus
File: web/web.go (Go)

Code before:
	Flags                 map[string]string

	ListenAddresses            []string
	CORSOrigin                 *regexp.Regexp
	ReadTimeout                time.Duration
	MaxConnections             int
	ExternalURL                *url.URL
	RoutePrefix                string
	UseLocalAssets             bool
	UserAssetsPath             string
	ConsoleTemplatesPath       string
	ConsoleLibrariesPath       string
	UseOldUI                   bool
	EnableLifecycle            bool
	EnableAdminAPI             bool
	PageTitle                  string
	RemoteReadSampleLimit      int
	RemoteReadConcurrencyLimit int
	RemoteReadBytesInFrame     int
	EnableRemoteWriteReceiver  bool
	EnableOTLPWriteReceiver    bool
	ConvertOTLPDelta           bool
	NativeOTLPDeltaIngestion   bool
	IsAgent                    bool
	CTZeroIngestionEnabled     bool
	AddTypeAndUnitLabels       bool
	AppName                    string

	AcceptRemoteWriteProtoMsgs []config.RemoteWriteProtoMsg

	Gatherer   prometheus.Gatherer
	Registerer prometheus.Registerer
}

// New initializes a new web Handler.
func New(logger *slog.Logger, o *Options) *Handler {
	if logger == nil {
		logger = promslog.NewNopLogger()
	}

	m := newMetrics(o.Registerer)
	router := route.New().
		WithInstrumentation(m.instrumentHandler).
		WithInstrumentation(setPathWithPrefix(""))

	cwd, err := os.Getwd()
	if err != nil {
		cwd = "<error retrieving current working directory>"
	}

	h := &Handler{

Review comment (suggestion):
To avoid confusion, I think we should be consistent with the scrape configuration parameter name:
```suggestion
	EnableTypeAndUnitLabels       bool
```

Code after:
	Flags                 map[string]string

	ListenAddresses            []string
	CORSOrigin                 *regexp.Regexp
	ReadTimeout                time.Duration
	MaxConnections             int
	ExternalURL                *url.URL
	RoutePrefix                string
	UseLocalAssets             bool
	UserAssetsPath             string
	ConsoleTemplatesPath       string
	ConsoleLibrariesPath       string
	UseOldUI                   bool
	EnableLifecycle            bool
	EnableAdminAPI             bool
	PageTitle                  string
	RemoteReadSampleLimit      int
	RemoteReadConcurrencyLimit int
	RemoteReadBytesInFrame     int
	EnableRemoteWriteReceiver  bool
	EnableOTLPWriteReceiver    bool
	ConvertOTLPDelta           bool
	NativeOTLPDeltaIngestion   bool
	IsAgent                    bool
	CTZeroIngestionEnabled     bool
	EnableTypeAndUnitLabels    bool
	AppName                    string

	AcceptRemoteWriteProtoMsgs []config.RemoteWriteProtoMsg

	Gatherer   prometheus.Gatherer
	Registerer prometheus.Registerer
}

// New initializes a new web Handler.
func New(logger *slog.Logger, o *Options) *Handler {
	if logger == nil {
		logger = promslog.NewNopLogger()
	}

	m := newMetrics(o.Registerer)
	router := route.New().
		WithInstrumentation(m.instrumentHandler).
		WithInstrumentation(setPathWithPrefix(""))

	cwd, err := os.Getwd()
	if err != nil {
		cwd = "<error retrieving current working directory>"
	}

	h := &Handler{
Repository: prometheus/prometheus
File: notifier/manager.go (Go)

Code before:
		}

		if len(ams.cfg.AlertRelabelConfigs) > 0 {
			// We can't use the cached values on the next iteration.
			cachedPayload = nil
		}

		// Being here means len(ams.ams) > 0
		amSetCovered.Store(k, false)
		for _, am := range ams.ams {
			wg.Add(1)

			ctx, cancel := context.WithTimeout(context.Background(), time.Duration(ams.cfg.Timeout))
			defer cancel()

			go func(ctx context.Context, k string, client *http.Client, url string, payload []byte, count int) {
				err := n.sendOne(ctx, client, url, payload)
				if err != nil {
					n.logger.Error("Error sending alerts", "alertmanager", url, "count", count, "err", err)
					n.metrics.errors.WithLabelValues(url).Add(float64(count))
				} else {
					amSetCovered.CompareAndSwap(k, false, true)
				}

				n.metrics.latencySum.WithLabelValues(url).Observe(time.Since(begin).Seconds())
				n.metrics.latencyHist.WithLabelValues(url).Observe(time.Since(begin).Seconds())
				n.metrics.sent.WithLabelValues(url).Add(float64(count))

				wg.Done()
			}(ctx, k, ams.client, am.url().String(), payload, len(amAlerts))
		}

		ams.mtx.RUnlock()
	}

	wg.Wait()

	// Return false if there are any sets which were attempted (e.g. not filtered
	// out) but have no successes.
	allAmSetsCovered := true
	amSetCovered.Range(func(_, value any) bool {
		if !value.(bool) {
			allAmSetsCovered = false
			return false
		}
		return true
	})

	return allAmSetsCovered
}


Review comment (suggestion):
Let's first call the `time.Since(begin).Seconds()` once and then call `Observe` on both metrics with the same value.

Code after:
		}

		if len(ams.cfg.AlertRelabelConfigs) > 0 {
			// We can't use the cached values on the next iteration.
			cachedPayload = nil
		}

		// Being here means len(ams.ams) > 0
		amSetCovered.Store(k, false)
		for _, am := range ams.ams {
			wg.Add(1)

			ctx, cancel := context.WithTimeout(context.Background(), time.Duration(ams.cfg.Timeout))
			defer cancel()

			go func(ctx context.Context, k string, client *http.Client, url string, payload []byte, count int) {
				err := n.sendOne(ctx, client, url, payload)
				if err != nil {
					n.logger.Error("Error sending alerts", "alertmanager", url, "count", count, "err", err)
					n.metrics.errors.WithLabelValues(url).Add(float64(count))
				} else {
					amSetCovered.CompareAndSwap(k, false, true)
				}

				durationSeconds := time.Since(begin).Seconds()
				n.metrics.latencySummary.WithLabelValues(url).Observe(durationSeconds)
				n.metrics.latencyHistogram.WithLabelValues(url).Observe(durationSeconds)
				n.metrics.sent.WithLabelValues(url).Add(float64(count))

				wg.Done()
			}(ctx, k, ams.client, am.url().String(), payload, len(amAlerts))
		}

		ams.mtx.RUnlock()
	}

	wg.Wait()

	// Return false if there are any sets which were attempted (e.g. not filtered
	// out) but have no successes.
	allAmSetsCovered := true
	amSetCovered.Range(func(_, value any) bool {
		if !value.(bool) {
			allAmSetsCovered = false
			return false
		}
		return true
	})

	return allAmSetsCovered
}
Repository: prometheus/prometheus
File: web/api/v1/api_test.go (Go)

Code before:
func assertAPIResponseLength(t *testing.T, got interface{}, expLen int) {
	t.Helper()

	gotLen := reflect.ValueOf(got).Len()
	require.Equal(t, expLen, gotLen, "Response length does not match")
}

func assertAPIResponseMetadataLen(t *testing.T, got interface{}, expLen int) {
	t.Helper()

	var gotLen int
	response := got.(map[string][]metadata.Metadata)
	for _, m := range response {
		gotLen += len(m)
	}

	require.Equal(t, expLen, gotLen, "Amount of metadata in the response does not match")
}

type fakeDB struct {
	err error
}

func (f *fakeDB) CleanTombstones() error { return f.err }

func (f *fakeDB) ListBlockMetas() ([]tsdb.BlockMeta, error) {
	return []tsdb.BlockMeta{
		{
			ULID:    ulid.MustNew(ulid.Now(), nil),
			MinTime: 0,
			MaxTime: 1000,
		},
	}, nil
}
func (f *fakeDB) Delete(context.Context, int64, int64, ...*labels.Matcher) error { return f.err }
func (f *fakeDB) Snapshot(string, bool) error                                    { return f.err }
func (f *fakeDB) Stats(statsByLabelName string, limit int) (_ *tsdb.Stats, retErr error) {
	dbDir, err := os.MkdirTemp("", "tsdb-api-ready")
	if err != nil {
		return nil, err
	}
	defer func() {
		err := os.RemoveAll(dbDir)
		if retErr != nil {
			retErr = err
		}
	}()
	opts := tsdb.DefaultHeadOptions()
	opts.ChunkRange = 1000
	h, _ := tsdb.NewHead(nil, nil, nil, nil, opts, nil)
	return h.Stats(statsByLabelName, limit), nil

Review comment (suggestion):
Let's also add a test to `api_test.go` for the new endpoint I'd say. Should hopefully be pretty simple and not need multiple cases.

Code after:

func assertAPIResponseLength(t *testing.T, got interface{}, expLen int) {
	t.Helper()

	gotLen := reflect.ValueOf(got).Len()
	require.Equal(t, expLen, gotLen, "Response length does not match")
}

func assertAPIResponseMetadataLen(t *testing.T, got interface{}, expLen int) {
	t.Helper()

	var gotLen int
	response := got.(map[string][]metadata.Metadata)
	for _, m := range response {
		gotLen += len(m)
	}

	require.Equal(t, expLen, gotLen, "Amount of metadata in the response does not match")
}

type fakeDB struct {
	err        error
	blockMetas []tsdb.BlockMeta
}

func (f *fakeDB) CleanTombstones() error { return f.err }

func (f *fakeDB) BlockMetas() ([]tsdb.BlockMeta, error) {
	return f.blockMetas, nil
}
func (f *fakeDB) Delete(context.Context, int64, int64, ...*labels.Matcher) error { return f.err }
func (f *fakeDB) Snapshot(string, bool) error                                    { return f.err }
func (f *fakeDB) Stats(statsByLabelName string, limit int) (_ *tsdb.Stats, retErr error) {
	dbDir, err := os.MkdirTemp("", "tsdb-api-ready")
	if err != nil {
		return nil, err
	}
	defer func() {
		err := os.RemoveAll(dbDir)
		if retErr != nil {
			retErr = err
		}
	}()
	opts := tsdb.DefaultHeadOptions()
	opts.ChunkRange = 1000
	h, _ := tsdb.NewHead(nil, nil, nil, nil, opts, nil)
	return h.Stats(statsByLabelName, limit), nil
}

func (f *fakeDB) WALReplayStatus() (tsdb.WALReplayStatus, error) {
	return tsdb.WALReplayStatus{}, nil
Repository: prometheus/prometheus
File: tsdb/db.go (Go)

Code before:
	}
	return nil
}

// StartTime implements the Storage interface.
func (db *DB) StartTime() (int64, error) {
	db.mtx.RLock()
	defer db.mtx.RUnlock()

	if len(db.blocks) > 0 {
		return db.blocks[0].Meta().MinTime, nil
	}
	return db.head.MinTime(), nil
}

// Dir returns the directory of the database.
func (db *DB) Dir() string {
	return db.dir
}

func (db *DB) ListBlockMetas() []BlockMeta {
	db.mtx.RLock()
	defer db.mtx.RUnlock()

	metas := make([]BlockMeta, 0, len(db.blocks))
	for _, b := range db.blocks {
		metas = append(metas, b.Meta())
	}
	return metas
}

func (db *DB) run(ctx context.Context) {
	defer close(db.donec)

	backoff := time.Duration(0)

	for {
		select {
		case <-db.stopc:
			return
		case <-time.After(backoff):
		}

		select {
		case <-time.After(1 * time.Minute):
			db.cmtx.Lock()
			if err := db.reloadBlocks(); err != nil {
				db.logger.Error("reloadBlocks", "err", err)
			}
			db.cmtx.Unlock()


Review comment (suggestion):
```suggestion
	metas := make([]BlockMeta, 0, len(db.blocks))
	for _, b := range db.Blocks() {
```

Code after:
	}
	return nil
}

// StartTime implements the Storage interface.
func (db *DB) StartTime() (int64, error) {
	db.mtx.RLock()
	defer db.mtx.RUnlock()

	if len(db.blocks) > 0 {
		return db.blocks[0].Meta().MinTime, nil
	}
	return db.head.MinTime(), nil
}

// Dir returns the directory of the database.
func (db *DB) Dir() string {
	return db.dir
}

// BlockMetas returns the list of metadata for all blocks.
func (db *DB) BlockMetas() []BlockMeta {
	blocks := db.Blocks()
	metas := make([]BlockMeta, 0, len(blocks))
	for _, b := range blocks {
		metas = append(metas, b.Meta())
	}
	return metas
}

func (db *DB) run(ctx context.Context) {
	defer close(db.donec)

	backoff := time.Duration(0)

	for {
		select {
		case <-db.stopc:
			return
		case <-time.After(backoff):
		}

		select {
		case <-time.After(1 * time.Minute):
			db.cmtx.Lock()
			if err := db.reloadBlocks(); err != nil {
				db.logger.Error("reloadBlocks", "err", err)
			}
			db.cmtx.Unlock()

			select {
Repository: prometheus/prometheus
File: model/labels/labels.go (Go)

Code before:
// WithoutEmpty returns the labelset without empty labels.
// May return the same labelset.
func (ls Labels) WithoutEmpty() Labels {
	for _, v := range ls {
		if v.Value != "" {
			continue
		}
		// Do not copy the slice until it's necessary.
		els := make(Labels, 0, len(ls)-1)
		for _, v := range ls {
			if v.Value != "" {
				els = append(els, v)
			}
		}
		return els
	}
	return ls
}

// ByteSize returns the approximate size of the labels in bytes.
func (ls Labels) ByteSize() int {
	var size = 0
	for _, l := range ls {
		size += len(l.Name) + len(l.Value) + 2*int(unsafe.Sizeof(""))
	}
	size += int(unsafe.Sizeof([]Labels{}))
	return size
}

// Equal returns whether the two label sets are equal.
func Equal(ls, o Labels) bool {
	return slices.Equal(ls, o)
}

// EmptyLabels returns n empty Labels value, for convenience.
func EmptyLabels() Labels {
	return Labels{}
}

// New returns a sorted Labels from the given labels.
// The caller has to guarantee that all label names are unique.
func New(ls ...Label) Labels {
	set := make(Labels, 0, len(ls))
	set = append(set, ls...)
	slices.SortFunc(set, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })

	return set
}

// FromStrings creates new labels from pairs of strings.
func FromStrings(ss ...string) Labels {

Review comment (suggestion):
This is likely good enough:

```suggestion
		size += len(l.Name) + len(l.Value)
	}
```

Code after:
// WithoutEmpty returns the labelset without empty labels.
// May return the same labelset.
func (ls Labels) WithoutEmpty() Labels {
	for _, v := range ls {
		if v.Value != "" {
			continue
		}
		// Do not copy the slice until it's necessary.
		els := make(Labels, 0, len(ls)-1)
		for _, v := range ls {
			if v.Value != "" {
				els = append(els, v)
			}
		}
		return els
	}
	return ls
}

// ByteSize returns the approximate size of the labels in bytes including
// the two string headers size for name and value.
// Slice header size is ignored because it should be amortized to zero.
func (ls Labels) ByteSize() uint64 {
	var size uint64 = 0
	for _, l := range ls {
		size += uint64(len(l.Name)+len(l.Value)) + 2*uint64(unsafe.Sizeof(""))
	}
	return size
}

// Equal returns whether the two label sets are equal.
func Equal(ls, o Labels) bool {
	return slices.Equal(ls, o)
}

// EmptyLabels returns n empty Labels value, for convenience.
func EmptyLabels() Labels {
	return Labels{}
}

// New returns a sorted Labels from the given labels.
// The caller has to guarantee that all label names are unique.
func New(ls ...Label) Labels {
	set := make(Labels, 0, len(ls))
	set = append(set, ls...)
	slices.SortFunc(set, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })

	return set
}

// FromStrings creates new labels from pairs of strings.
Repository: prometheus/prometheus
File: model/labels/labels.go (Go)

Code before:
		}
	}
	return "", false
}

// WithoutEmpty returns the labelset without empty labels.
// May return the same labelset.
func (ls Labels) WithoutEmpty() Labels {
	for _, v := range ls {
		if v.Value != "" {
			continue
		}
		// Do not copy the slice until it's necessary.
		els := make(Labels, 0, len(ls)-1)
		for _, v := range ls {
			if v.Value != "" {
				els = append(els, v)
			}
		}
		return els
	}
	return ls
}

// ByteSize returns the approximate size of the labels in bytes.
// String and slice header size is ignored because it should be amortized to zero.
func (ls Labels) ByteSize() int {
	var size = 0
	for _, l := range ls {
		size += len(l.Name) + len(l.Value)
	}
	return size
}

// Equal returns whether the two label sets are equal.
func Equal(ls, o Labels) bool {
	return slices.Equal(ls, o)
}

// EmptyLabels returns n empty Labels value, for convenience.
func EmptyLabels() Labels {
	return Labels{}
}

// New returns a sorted Labels from the given labels.
// The caller has to guarantee that all label names are unique.
func New(ls ...Label) Labels {
	set := make(Labels, 0, len(ls))
	set = append(set, ls...)
	slices.SortFunc(set, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })


Review comment (suggestion):
I can accept the slice header might be re-used, but the string headers don't exist anywhere except this `Labels`, so should absolutely be counted.

Code after:
		}
	}
	return "", false
}

// WithoutEmpty returns the labelset without empty labels.
// May return the same labelset.
func (ls Labels) WithoutEmpty() Labels {
	for _, v := range ls {
		if v.Value != "" {
			continue
		}
		// Do not copy the slice until it's necessary.
		els := make(Labels, 0, len(ls)-1)
		for _, v := range ls {
			if v.Value != "" {
				els = append(els, v)
			}
		}
		return els
	}
	return ls
}

// ByteSize returns the approximate size of the labels in bytes including
// the two string headers size for name and value.
// Slice header size is ignored because it should be amortized to zero.
func (ls Labels) ByteSize() uint64 {
	var size uint64 = 0
	for _, l := range ls {
		size += uint64(len(l.Name)+len(l.Value)) + 2*uint64(unsafe.Sizeof(""))
	}
	return size
}

// Equal returns whether the two label sets are equal.
func Equal(ls, o Labels) bool {
	return slices.Equal(ls, o)
}

// EmptyLabels returns n empty Labels value, for convenience.
func EmptyLabels() Labels {
	return Labels{}
}

// New returns a sorted Labels from the given labels.
// The caller has to guarantee that all label names are unique.
func New(ls ...Label) Labels {
	set := make(Labels, 0, len(ls))
	set = append(set, ls...)
	slices.SortFunc(set, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })
Repository: prometheus/prometheus
File: model/labels/labels.go (Go)

Code before:
	return "", false
}

// WithoutEmpty returns the labelset without empty labels.
// May return the same labelset.
func (ls Labels) WithoutEmpty() Labels {
	for _, v := range ls {
		if v.Value != "" {
			continue
		}
		// Do not copy the slice until it's necessary.
		els := make(Labels, 0, len(ls)-1)
		for _, v := range ls {
			if v.Value != "" {
				els = append(els, v)
			}
		}
		return els
	}
	return ls
}

// ByteSize returns the approximate size of the labels in bytes including
// the two string headers size for name and value.
// Slice header size is ignored because it should be amortized to zero.
func (ls Labels) ByteSize() int {
	var size = 0
	for _, l := range ls {
		size += len(l.Name) + len(l.Value) + 2*int(unsafe.Sizeof(""))
	}
	return size
}

// Equal returns whether the two label sets are equal.
func Equal(ls, o Labels) bool {
	return slices.Equal(ls, o)
}

// EmptyLabels returns n empty Labels value, for convenience.
func EmptyLabels() Labels {
	return Labels{}
}

// New returns a sorted Labels from the given labels.
// The caller has to guarantee that all label names are unique.
func New(ls ...Label) Labels {
	set := make(Labels, 0, len(ls))
	set = append(set, ls...)
	slices.SortFunc(set, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })

	return set

Review comment (suggestion):
I note the inconsistency with `SizeOfLabels` which returns `uint64`.  The type there was chosen for consistency with the existing `index.Stat` struct.

I can't say this is a huge issue, but worth some consideration.

Code after:
	return "", false
}

// WithoutEmpty returns the labelset without empty labels.
// May return the same labelset.
func (ls Labels) WithoutEmpty() Labels {
	for _, v := range ls {
		if v.Value != "" {
			continue
		}
		// Do not copy the slice until it's necessary.
		els := make(Labels, 0, len(ls)-1)
		for _, v := range ls {
			if v.Value != "" {
				els = append(els, v)
			}
		}
		return els
	}
	return ls
}

// ByteSize returns the approximate size of the labels in bytes including
// the two string headers size for name and value.
// Slice header size is ignored because it should be amortized to zero.
func (ls Labels) ByteSize() uint64 {
	var size uint64 = 0
	for _, l := range ls {
		size += uint64(len(l.Name)+len(l.Value)) + 2*uint64(unsafe.Sizeof(""))
	}
	return size
}

// Equal returns whether the two label sets are equal.
func Equal(ls, o Labels) bool {
	return slices.Equal(ls, o)
}

// EmptyLabels returns n empty Labels value, for convenience.
func EmptyLabels() Labels {
	return Labels{}
}

// New returns a sorted Labels from the given labels.
// The caller has to guarantee that all label names are unique.
func New(ls ...Label) Labels {
	set := make(Labels, 0, len(ls))
	set = append(set, ls...)
	slices.SortFunc(set, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })

	return set