diff --git a/cmd/promtool/rules.go b/cmd/promtool/rules.go index 2b5ed1d78..aedc7bcb9 100644 --- a/cmd/promtool/rules.go +++ b/cmd/promtool/rules.go @@ -163,7 +163,7 @@ func (importer *ruleImporter) importRule(ctx context.Context, ruleExpr, ruleName }) lb.Set(labels.MetricName, ruleName) - lbls := lb.Labels(labels.EmptyLabels()) + lbls := lb.Labels() for _, value := range sample.Values { if err := app.add(ctx, lbls, timestamp.FromTime(value.Timestamp.Time()), float64(value.Value)); err != nil { diff --git a/model/labels/labels.go b/model/labels/labels.go index 8fc401564..e3a478a25 100644 --- a/model/labels/labels.go +++ b/model/labels/labels.go @@ -570,24 +570,18 @@ func contains(s []Label, n string) bool { return false } -// Labels returns the labels from the builder, adding them to res if non-nil. -// Argument res can be the same as b.base, if caller wants to overwrite that slice. +// Labels returns the labels from the builder. // If no modifications were made, the original labels are returned. -func (b *Builder) Labels(res Labels) Labels { +func (b *Builder) Labels() Labels { if len(b.del) == 0 && len(b.add) == 0 { return b.base } - if res == nil { - // In the general case, labels are removed, modified or moved - // rather than added. - res = make(Labels, 0, len(b.base)) - } else { - res = res[:0] + expectedSize := len(b.base) + len(b.add) - len(b.del) + if expectedSize < 1 { + expectedSize = 1 } - // Justification that res can be the same slice as base: in this loop - // we move forward through base, and either skip an element or assign - // it to res at its current position or an earlier position. + res := make(Labels, 0, expectedSize) for _, l := range b.base { if slices.Contains(b.del, l.Name) || contains(b.add, l.Name) { continue diff --git a/model/labels/labels_string.go b/model/labels/labels_string.go index 560b643db..d830d5a43 100644 --- a/model/labels/labels_string.go +++ b/model/labels/labels_string.go @@ -158,7 +158,7 @@ func (ls Labels) MatchLabels(on bool, names ...string) Labels { b.Del(MetricName) b.Del(names...) } - return b.Labels(EmptyLabels()) + return b.Labels() } // Hash returns a hash value for the label set. @@ -624,10 +624,9 @@ func contains(s []Label, n string) bool { return false } -// Labels returns the labels from the builder, adding them to res if non-nil. -// Argument res can be the same as b.base, if caller wants to overwrite that slice. +// Labels returns the labels from the builder. // If no modifications were made, the original labels are returned. -func (b *Builder) Labels(res Labels) Labels { +func (b *Builder) Labels() Labels { if len(b.del) == 0 && len(b.add) == 0 { return b.base } @@ -637,7 +636,7 @@ func (b *Builder) Labels(res Labels) Labels { a, d := 0, 0 bufSize := len(b.base.data) + labelsSize(b.add) - buf := make([]byte, 0, bufSize) // TODO: see if we can re-use the buffer from res. + buf := make([]byte, 0, bufSize) for pos := 0; pos < len(b.base.data); { oldPos := pos var lName string diff --git a/model/labels/labels_test.go b/model/labels/labels_test.go index 588a84b98..9e60c2251 100644 --- a/model/labels/labels_test.go +++ b/model/labels/labels_test.go @@ -596,7 +596,7 @@ func TestBuilder(t *testing.T) { b.Keep(tcase.keep...) } b.Del(tcase.del...) - require.Equal(t, tcase.want, b.Labels(EmptyLabels())) + require.Equal(t, tcase.want, b.Labels()) // Check what happens when we call Range and mutate the builder. b.Range(func(l Label) { @@ -604,7 +604,7 @@ func TestBuilder(t *testing.T) { b.Del(l.Name) } }) - require.Equal(t, tcase.want.BytesWithoutLabels(nil, "aaa", "bbb"), b.Labels(tcase.base).Bytes(nil)) + require.Equal(t, tcase.want.BytesWithoutLabels(nil, "aaa", "bbb"), b.Labels().Bytes(nil)) }) } } @@ -669,7 +669,7 @@ func BenchmarkLabels_Hash(b *testing.B) { // Label ~20B name, 50B value. b.Set(fmt.Sprintf("abcdefghijabcdefghijabcdefghij%d", i), fmt.Sprintf("abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij%d", i)) } - return b.Labels(EmptyLabels()) + return b.Labels() }(), }, { @@ -680,7 +680,7 @@ func BenchmarkLabels_Hash(b *testing.B) { // Label ~50B name, 50B value. b.Set(fmt.Sprintf("abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij%d", i), fmt.Sprintf("abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij%d", i)) } - return b.Labels(EmptyLabels()) + return b.Labels() }(), }, { @@ -729,7 +729,7 @@ func BenchmarkBuilder(b *testing.B) { for _, l := range m { builder.Set(l.Name, l.Value) } - l = builder.Labels(EmptyLabels()) + l = builder.Labels() } require.Equal(b, 9, l.Len()) } diff --git a/model/relabel/relabel.go b/model/relabel/relabel.go index 5ef79b4a7..5027c3963 100644 --- a/model/relabel/relabel.go +++ b/model/relabel/relabel.go @@ -211,7 +211,7 @@ func Process(lbls labels.Labels, cfgs ...*Config) (ret labels.Labels, keep bool) if !ProcessBuilder(lb, cfgs...) { return labels.EmptyLabels(), false } - return lb.Labels(lbls), true + return lb.Labels(), true } // ProcessBuilder is like Process, but the caller passes a labels.Builder diff --git a/notifier/notifier.go b/notifier/notifier.go index 79697d079..c3b2e5c7e 100644 --- a/notifier/notifier.go +++ b/notifier/notifier.go @@ -359,7 +359,7 @@ func (n *Manager) Send(alerts ...*Alert) { } }) - a.Labels = lb.Labels(a.Labels) + a.Labels = lb.Labels() } alerts = n.relabelAlerts(alerts) diff --git a/promql/engine.go b/promql/engine.go index ad30b1550..52278c7a2 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -2192,7 +2192,7 @@ func resultMetric(lhs, rhs labels.Labels, op parser.ItemType, matching *parser.V } } - ret := enh.lb.Labels(labels.EmptyLabels()) + ret := enh.lb.Labels() enh.resultMetric[str] = ret return ret } @@ -2232,7 +2232,7 @@ func (ev *evaluator) VectorscalarBinop(op parser.ItemType, lhs Vector, rhs Scala } func dropMetricName(l labels.Labels) labels.Labels { - return labels.NewBuilder(l).Del(labels.MetricName).Labels(labels.EmptyLabels()) + return labels.NewBuilder(l).Del(labels.MetricName).Labels() } // scalarBinop evaluates a binary operation between two Scalars. @@ -2366,7 +2366,7 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without if op == parser.COUNT_VALUES { enh.resetBuilder(metric) enh.lb.Set(valueLabel, strconv.FormatFloat(s.V, 'f', -1, 64)) - metric = enh.lb.Labels(labels.EmptyLabels()) + metric = enh.lb.Labels() // We've changed the metric so we have to recompute the grouping key. recomputeGroupingKey = true @@ -2388,10 +2388,10 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without if without { enh.lb.Del(grouping...) enh.lb.Del(labels.MetricName) - m = enh.lb.Labels(labels.EmptyLabels()) + m = enh.lb.Labels() } else if len(grouping) > 0 { enh.lb.Keep(grouping...) - m = enh.lb.Labels(labels.EmptyLabels()) + m = enh.lb.Labels() } else { m = labels.EmptyLabels() } diff --git a/promql/functions.go b/promql/functions.go index 3da38ea0f..e1a02ac8e 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -960,7 +960,7 @@ func funcHistogramQuantile(vals []parser.Value, args parser.Expressions, enh *Ev if !ok { sample.Metric = labels.NewBuilder(sample.Metric). Del(excludedLabels...). - Labels(labels.EmptyLabels()) + Labels() mb = &metricWithBuckets{sample.Metric, nil} enh.signatureToMetricWithBuckets[string(enh.lblBuf)] = mb @@ -1080,7 +1080,7 @@ func funcLabelReplace(vals []parser.Value, args parser.Expressions, enh *EvalNod if len(res) > 0 { lb.Set(dst, string(res)) } - outMetric = lb.Labels(labels.EmptyLabels()) + outMetric = lb.Labels() enh.Dmn[h] = outMetric } } @@ -1148,7 +1148,7 @@ func funcLabelJoin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHe lb.Set(dst, strval) } - outMetric = lb.Labels(labels.EmptyLabels()) + outMetric = lb.Labels() enh.Dmn[h] = outMetric } @@ -1414,7 +1414,7 @@ func createLabelsForAbsentFunction(expr parser.Expr) labels.Labels { } } - return b.Labels(labels.EmptyLabels()) + return b.Labels() } func stringFromArg(e parser.Expr) string { diff --git a/promql/parser/generated_parser.y b/promql/parser/generated_parser.y index 461e854ac..b1c604eec 100644 --- a/promql/parser/generated_parser.y +++ b/promql/parser/generated_parser.y @@ -567,7 +567,7 @@ label_matcher : IDENTIFIER match_op STRING */ metric : metric_identifier label_set - { b := labels.NewBuilder($2); b.Set(labels.MetricName, $1.Val); $$ = b.Labels(labels.EmptyLabels()) } + { b := labels.NewBuilder($2); b.Set(labels.MetricName, $1.Val); $$ = b.Labels() } | label_set {$$ = $1} ; diff --git a/promql/parser/generated_parser.y.go b/promql/parser/generated_parser.y.go index 3a0e8bf69..2cf3e06b9 100644 --- a/promql/parser/generated_parser.y.go +++ b/promql/parser/generated_parser.y.go @@ -1494,7 +1494,7 @@ yydefault: { b := labels.NewBuilder(yyDollar[2].labels) b.Set(labels.MetricName, yyDollar[1].item.Val) - yyVAL.labels = b.Labels(labels.EmptyLabels()) + yyVAL.labels = b.Labels() } case 96: yyDollar = yyS[yypt-1 : yypt+1] diff --git a/rules/alerting.go b/rules/alerting.go index 70e2241f7..c793b90cb 100644 --- a/rules/alerting.go +++ b/rules/alerting.go @@ -234,7 +234,7 @@ func (r *AlertingRule) sample(alert *Alert, ts time.Time) promql.Sample { lb.Set(alertStateLabel, alert.State.String()) s := promql.Sample{ - Metric: lb.Labels(labels.EmptyLabels()), + Metric: lb.Labels(), Point: promql.Point{T: timestamp.FromTime(ts), V: 1}, } return s @@ -252,7 +252,7 @@ func (r *AlertingRule) forStateSample(alert *Alert, ts time.Time, v float64) pro lb.Set(labels.AlertName, r.name) s := promql.Sample{ - Metric: lb.Labels(labels.EmptyLabels()), + Metric: lb.Labels(), Point: promql.Point{T: timestamp.FromTime(ts), V: v}, } return s @@ -381,7 +381,7 @@ func (r *AlertingRule) Eval(ctx context.Context, ts time.Time, query QueryFunc, }) annotations := sb.Labels() - lbs := lb.Labels(labels.EmptyLabels()) + lbs := lb.Labels() h := lbs.Hash() resultFPs[h] = struct{}{} diff --git a/rules/recording.go b/rules/recording.go index a07c779bb..b6a886cdd 100644 --- a/rules/recording.go +++ b/rules/recording.go @@ -93,7 +93,7 @@ func (rule *RecordingRule) Eval(ctx context.Context, ts time.Time, query QueryFu lb.Set(l.Name, l.Value) }) - sample.Metric = lb.Labels(sample.Metric) + sample.Metric = lb.Labels() } // Check that the rule does not produce identical metrics after applying diff --git a/scrape/scrape.go b/scrape/scrape.go index 01c66ca81..f38527ff3 100644 --- a/scrape/scrape.go +++ b/scrape/scrape.go @@ -692,7 +692,7 @@ func mutateSampleLabels(lset labels.Labels, target *Target, honor bool, rc []*re } } - res := lb.Labels(labels.EmptyLabels()) + res := lb.Labels() if len(rc) > 0 { res, _ = relabel.Process(res, rc...) @@ -726,7 +726,7 @@ func mutateReportSampleLabels(lset labels.Labels, target *Target) labels.Labels lb.Set(l.Name, l.Value) }) - return lb.Labels(labels.EmptyLabels()) + return lb.Labels() } // appender returns an appender for ingested samples from the target. diff --git a/scrape/target.go b/scrape/target.go index 59f6e2873..f250910c1 100644 --- a/scrape/target.go +++ b/scrape/target.go @@ -380,7 +380,7 @@ func PopulateLabels(lb *labels.Builder, cfg *config.ScrapeConfig, noDefaultPort } } - preRelabelLabels := lb.Labels(labels.EmptyLabels()) + preRelabelLabels := lb.Labels() keep := relabel.ProcessBuilder(lb, cfg.RelabelConfigs...) // Check if the target was dropped. @@ -476,7 +476,7 @@ func PopulateLabels(lb *labels.Builder, cfg *config.ScrapeConfig, noDefaultPort lb.Set(model.InstanceLabel, addr) } - res = lb.Labels(labels.EmptyLabels()) + res = lb.Labels() err = res.Validate(func(l labels.Label) error { // Check label values are valid, drop the target if not. if !model.LabelValue(l.Value).IsValid() { diff --git a/scrape/target_test.go b/scrape/target_test.go index 4937359ed..2bc3f000c 100644 --- a/scrape/target_test.go +++ b/scrape/target_test.go @@ -140,7 +140,7 @@ func newTestTarget(targetURL string, deadline time.Duration, lbls labels.Labels) lb.Set(model.AddressLabel, strings.TrimPrefix(targetURL, "http://")) lb.Set(model.MetricsPathLabel, "/metrics") - return &Target{labels: lb.Labels(labels.EmptyLabels())} + return &Target{labels: lb.Labels()} } func TestNewHTTPBearerToken(t *testing.T) { diff --git a/storage/remote/read.go b/storage/remote/read.go index 21524d70d..af61334f4 100644 --- a/storage/remote/read.go +++ b/storage/remote/read.go @@ -278,5 +278,5 @@ func (sf seriesFilter) Labels() labels.Labels { b := labels.NewBuilder(sf.Series.Labels()) // todo: check if this is too inefficient. b.Del(sf.toFilter...) - return b.Labels(labels.EmptyLabels()) + return b.Labels() } diff --git a/tsdb/compact_test.go b/tsdb/compact_test.go index 0a01892d5..1b0684521 100644 --- a/tsdb/compact_test.go +++ b/tsdb/compact_test.go @@ -1575,20 +1575,20 @@ func TestSparseHistogramSpaceSavings(t *testing.T) { for it.Next() { numOldSeriesPerHistogram++ b := it.At() - lbls := labels.NewBuilder(ah.baseLabels).Set("le", fmt.Sprintf("%.16f", b.Upper)).Labels(labels.EmptyLabels()) + lbls := labels.NewBuilder(ah.baseLabels).Set("le", fmt.Sprintf("%.16f", b.Upper)).Labels() refs[itIdx], err = oldApp.Append(refs[itIdx], lbls, ts, float64(b.Count)) require.NoError(t, err) itIdx++ } baseName := ah.baseLabels.Get(labels.MetricName) // _count metric. - countLbls := labels.NewBuilder(ah.baseLabels).Set(labels.MetricName, baseName+"_count").Labels(labels.EmptyLabels()) + countLbls := labels.NewBuilder(ah.baseLabels).Set(labels.MetricName, baseName+"_count").Labels() _, err = oldApp.Append(0, countLbls, ts, float64(h.Count)) require.NoError(t, err) numOldSeriesPerHistogram++ // _sum metric. - sumLbls := labels.NewBuilder(ah.baseLabels).Set(labels.MetricName, baseName+"_sum").Labels(labels.EmptyLabels()) + sumLbls := labels.NewBuilder(ah.baseLabels).Set(labels.MetricName, baseName+"_sum").Labels() _, err = oldApp.Append(0, sumLbls, ts, h.Sum) require.NoError(t, err) numOldSeriesPerHistogram++