Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion prometheus/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func NewCounter(opts CounterOpts) Counter {
if opts.now == nil {
opts.now = time.Now
}
result := &counter{desc: desc, labelPairs: desc.constLabelPairs, now: opts.now}
result := &counter{desc: desc, labelPairs: desc.labelPairs, now: opts.now}
result.init(result) // Init self-collection.
result.createdTs = timestamppb.New(opts.now())
return result
Expand Down
42 changes: 34 additions & 8 deletions prometheus/desc.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,16 @@ type Desc struct {
fqName string
// help provides some helpful information about this metric.
help string
// constLabelPairs contains precalculated DTO label pairs based on
// the constant labels.
constLabelPairs []*dto.LabelPair
// variableLabels contains names of labels and normalization function for
// which the metric maintains variable values.
variableLabels *compiledLabels
// variableLabelOrder maps variableLabels indexes to the position in the
// pre-computed labelPairs slice. This allows fast MakeLabelPair function
// that have to place ordered variable label values into pre-sorted labelPairs.
variableLabelOrder []int
// labelPairs contains the sorted DTO label pairs based on the constant labels
// and variable labels
labelPairs []*dto.LabelPair
// id is a hash of the values of the ConstLabels and fqName. This
// must be unique among all registered descriptors and can therefore be
// used as an identifier of the descriptor.
Expand Down Expand Up @@ -160,14 +164,33 @@ func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, const
}
d.dimHash = xxh.Sum64()

d.constLabelPairs = make([]*dto.LabelPair, 0, len(constLabels))
d.labelPairs = make([]*dto.LabelPair, 0, len(constLabels)+len(d.variableLabels.names))
for n, v := range constLabels {
d.constLabelPairs = append(d.constLabelPairs, &dto.LabelPair{
d.labelPairs = append(d.labelPairs, &dto.LabelPair{
Name: proto.String(n),
Value: proto.String(v),
})
}
sort.Sort(internal.LabelPairSorter(d.constLabelPairs))
for _, labelName := range d.variableLabels.names {
d.labelPairs = append(d.labelPairs, &dto.LabelPair{
Name: proto.String(labelName),
})
}
sort.Sort(internal.LabelPairSorter(d.labelPairs))

d.variableLabelOrder = make([]int, len(d.variableLabels.names))
for outputIndex, pair := range d.labelPairs {
// Constant labels have values variable labels do not.
if pair.Value != nil {
continue
}
for sourceIndex, variableLabel := range d.variableLabels.names {
if variableLabel == pair.GetName() {
d.variableLabelOrder[sourceIndex] = outputIndex
}
}
}

return d
}

Expand All @@ -182,8 +205,11 @@ func NewInvalidDesc(err error) *Desc {
}

func (d *Desc) String() string {
lpStrings := make([]string, 0, len(d.constLabelPairs))
for _, lp := range d.constLabelPairs {
lpStrings := make([]string, 0, len(d.labelPairs))
for _, lp := range d.labelPairs {
if lp.Value == nil {
continue
}
lpStrings = append(
lpStrings,
fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()),
Expand Down
27 changes: 27 additions & 0 deletions prometheus/desc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package prometheus

import (
"fmt"
"testing"
)

Expand Down Expand Up @@ -61,3 +62,29 @@ func TestNewInvalidDesc_String(t *testing.T) {
t.Errorf("String: unexpected output: %s", desc.String())
}
}

func BenchmarkNewDesc(b *testing.B) {
for _, bm := range []struct {
labelCount int
descFunc func() *Desc
}{
{
labelCount: 1,
descFunc: new1LabelDescFunc,
},
{
labelCount: 3,
descFunc: new3LabelsDescFunc,
},
{
labelCount: 10,
descFunc: new10LabelsDescFunc,
},
} {
b.Run(fmt.Sprintf("labels=%v", bm.labelCount), func(b *testing.B) {
for i := 0; i < b.N; i++ {
bm.descFunc()
}
})
}
}
2 changes: 1 addition & 1 deletion prometheus/gauge.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func NewGauge(opts GaugeOpts) Gauge {
nil,
opts.ConstLabels,
)
result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
result := &gauge{desc: desc, labelPairs: desc.labelPairs}
result.init(result) // Init self-collection.
return result
}
Expand Down
7 changes: 1 addition & 6 deletions prometheus/histogram.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,12 +537,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, labelValues))
}

for _, n := range desc.variableLabels.names {
if n == bucketLabel {
panic(errBucketLabelNotAllowed)
}
}
for _, lp := range desc.constLabelPairs {
for _, lp := range desc.labelPairs {
if lp.GetName() == bucketLabel {
panic(errBucketLabelNotAllowed)
}
Expand Down
12 changes: 2 additions & 10 deletions prometheus/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -962,21 +962,13 @@ func checkDescConsistency(
}

// Is the desc consistent with the content of the metric?
lpsFromDesc := make([]*dto.LabelPair, len(desc.constLabelPairs), len(dtoMetric.Label))
copy(lpsFromDesc, desc.constLabelPairs)
for _, l := range desc.variableLabels.names {
lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{
Name: proto.String(l),
})
}
if len(lpsFromDesc) != len(dtoMetric.Label) {
if len(desc.labelPairs) != len(dtoMetric.Label) {
return fmt.Errorf(
"labels in collected metric %s %s are inconsistent with descriptor %s",
metricFamily.GetName(), dtoMetric, desc,
)
}
sort.Sort(internal.LabelPairSorter(lpsFromDesc))
for i, lpFromDesc := range lpsFromDesc {
for i, lpFromDesc := range desc.labelPairs {
lpFromMetric := dtoMetric.Label[i]
if lpFromDesc.GetName() != lpFromMetric.GetName() ||
lpFromDesc.Value != nil && lpFromDesc.GetValue() != lpFromMetric.GetValue() {
Expand Down
7 changes: 1 addition & 6 deletions prometheus/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, labelValues))
}

for _, n := range desc.variableLabels.names {
if n == quantileLabel {
panic(errQuantileLabelNotAllowed)
}
}
for _, lp := range desc.constLabelPairs {
for _, lp := range desc.labelPairs {
if lp.GetName() == quantileLabel {
panic(errQuantileLabelNotAllowed)
}
Expand Down
32 changes: 18 additions & 14 deletions prometheus/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@ package prometheus
import (
"errors"
"fmt"
"sort"
"time"
"unicode/utf8"

"github.com/prometheus/client_golang/prometheus/internal"

dto "github.com/prometheus/client_model/go"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
Expand Down Expand Up @@ -215,24 +212,31 @@ func populateMetric(
// This function is only needed for custom Metric implementations. See MetricVec
// example.
func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
totalLen := len(desc.variableLabels.names) + len(desc.constLabelPairs)
if totalLen == 0 {
if len(desc.labelPairs) == 0 {
// Super fast path.
return nil
}
if len(desc.variableLabels.names) == 0 {
// Moderately fast path.
return desc.constLabelPairs
return desc.labelPairs
}
labelPairs := make([]*dto.LabelPair, 0, totalLen)
for i, l := range desc.variableLabels.names {
labelPairs = append(labelPairs, &dto.LabelPair{
Name: proto.String(l),
Value: proto.String(labelValues[i]),
})
labelPairs := make([]*dto.LabelPair, 0, len(desc.labelPairs))
for _, lp := range desc.labelPairs {
var labelToAdd *dto.LabelPair
// Variable labels have no value and need to be inserted with a new dto.LabelPair containing the labelValue.
if lp.Value == nil {
labelToAdd = &dto.LabelPair{
Name: lp.Name,
}
} else {
labelToAdd = lp
}
labelPairs = append(labelPairs, labelToAdd)
}
for i, outputIndex := range desc.variableLabelOrder {
labelPairs[outputIndex].Value = proto.String(labelValues[i])
}
labelPairs = append(labelPairs, desc.constLabelPairs...)
sort.Sort(internal.LabelPairSorter(labelPairs))

return labelPairs
}

Expand Down
Loading
Loading