Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
20 changes: 10 additions & 10 deletions prometheus/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,42 @@ import (
)

func BenchmarkCounter(b *testing.B) {
type fns []func(*CounterVec) Counter
type fns []func(CounterVec) Counter

twoConstraint := func(_ string) string {
return "two"
}

deLV := func(m *CounterVec) Counter {
deLV := func(m CounterVec) Counter {
return m.WithLabelValues("eins", "zwei", "drei")
}
frLV := func(m *CounterVec) Counter {
frLV := func(m CounterVec) Counter {
return m.WithLabelValues("une", "deux", "trois")
}
nlLV := func(m *CounterVec) Counter {
nlLV := func(m CounterVec) Counter {
return m.WithLabelValues("een", "twee", "drie")
}

deML := func(m *CounterVec) Counter {
deML := func(m CounterVec) Counter {
return m.With(Labels{"two": "zwei", "one": "eins", "three": "drei"})
}
frML := func(m *CounterVec) Counter {
frML := func(m CounterVec) Counter {
return m.With(Labels{"two": "deux", "one": "une", "three": "trois"})
}
nlML := func(m *CounterVec) Counter {
nlML := func(m CounterVec) Counter {
return m.With(Labels{"two": "twee", "one": "een", "three": "drie"})
}

deLabels := Labels{"two": "zwei", "one": "eins", "three": "drei"}
dePML := func(m *CounterVec) Counter {
dePML := func(m CounterVec) Counter {
return m.With(deLabels)
}
frLabels := Labels{"two": "deux", "one": "une", "three": "trois"}
frPML := func(m *CounterVec) Counter {
frPML := func(m CounterVec) Counter {
return m.With(frLabels)
}
nlLabels := Labels{"two": "twee", "one": "een", "three": "drie"}
nlPML := func(m *CounterVec) Counter {
nlPML := func(m CounterVec) Counter {
return m.With(nlLabels)
}

Expand Down
38 changes: 26 additions & 12 deletions prometheus/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,26 +180,40 @@ func (c *counter) updateExemplar(v float64, l Labels) {
c.exemplar.Store(e)
}

type CounterVec interface {
Delete(Labels) bool
DeleteLabelValues(...string) bool
DeletePartialMatch(Labels) int
GetMetricWith(Labels) (Counter, error)
GetMetricWithLabelValues(...string) (Counter, error)
With(Labels) Counter
WithLabelValues(...string) Counter
CurryWith(Labels) (CounterVec, error)
MustCurryWith(Labels) CounterVec
Reset()
Collector
}

// CounterVec is a Collector that bundles a set of Counters that all share the
// same Desc, but have different values for their variable labels. This is used
// if you want to count the same thing partitioned by various dimensions
// (e.g. number of HTTP requests, partitioned by response code and
// method). Create instances with NewCounterVec.
type CounterVec struct {
*MetricVec
type counterVec struct {
MetricVec
}

// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
// partitioned by the given label names.
func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
func NewCounterVec(opts CounterOpts, labelNames []string) CounterVec {
return V2.NewCounterVec(CounterVecOpts{
CounterOpts: opts,
VariableLabels: UnconstrainedLabels(labelNames),
})
}

// NewCounterVec creates a new CounterVec based on the provided CounterVecOpts.
func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec {
func (v2) NewCounterVec(opts CounterVecOpts) CounterVec {
desc := V2.NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
opts.Help,
Expand All @@ -209,7 +223,7 @@ func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec {
if opts.now == nil {
opts.now = time.Now
}
return &CounterVec{
return &counterVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels.names) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, lvs))
Expand Down Expand Up @@ -245,7 +259,7 @@ func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec {
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
func (v *counterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Counter), err
Expand All @@ -265,7 +279,7 @@ func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
func (v *counterVec) GetMetricWith(labels Labels) (Counter, error) {
metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Counter), err
Expand All @@ -278,7 +292,7 @@ func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
// error allows shortcuts like
//
// myVec.WithLabelValues("404", "GET").Add(42)
func (v *CounterVec) WithLabelValues(lvs ...string) Counter {
func (v *counterVec) WithLabelValues(lvs ...string) Counter {
c, err := v.GetMetricWithLabelValues(lvs...)
if err != nil {
panic(err)
Expand All @@ -290,7 +304,7 @@ func (v *CounterVec) WithLabelValues(lvs ...string) Counter {
// returned an error. Not returning an error allows shortcuts like
//
// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
func (v *CounterVec) With(labels Labels) Counter {
func (v *counterVec) With(labels Labels) Counter {
c, err := v.GetMetricWith(labels)
if err != nil {
panic(err)
Expand All @@ -311,17 +325,17 @@ func (v *CounterVec) With(labels Labels) Counter {
// vectors behave identically in terms of collection. Only one must be
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
func (v *counterVec) CurryWith(labels Labels) (CounterVec, error) {
vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &CounterVec{vec}, err
return &counterVec{vec}, err
}
return nil, err
}

// MustCurryWith works as CurryWith but panics where CurryWith would have
// returned an error.
func (v *CounterVec) MustCurryWith(labels Labels) *CounterVec {
func (v *counterVec) MustCurryWith(labels Labels) CounterVec {
vec, err := v.CurryWith(labels)
if err != nil {
panic(err)
Expand Down
20 changes: 10 additions & 10 deletions prometheus/counter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,41 +320,41 @@ func TestCounterExemplar(t *testing.T) {
func TestCounterVecCreatedTimestampWithDeletes(t *testing.T) {
now := time.Now()

counterVec := NewCounterVec(CounterOpts{
vec := NewCounterVec(CounterOpts{
Name: "test",
Help: "test help",
now: func() time.Time { return now },
}, []string{"label"})

// First use of "With" should populate CT.
counterVec.WithLabelValues("1")
vec.WithLabelValues("1")
expected := map[string]time.Time{"1": now}

now = now.Add(1 * time.Hour)
expectCTsForMetricVecValues(t, counterVec.MetricVec, dto.MetricType_COUNTER, expected)
expectCTsForMetricVecValues(t, vec.(*counterVec).MetricVec, dto.MetricType_COUNTER, expected)

// Two more labels at different times.
counterVec.WithLabelValues("2")
vec.WithLabelValues("2")
expected["2"] = now

now = now.Add(1 * time.Hour)

counterVec.WithLabelValues("3")
vec.WithLabelValues("3")
expected["3"] = now

now = now.Add(1 * time.Hour)
expectCTsForMetricVecValues(t, counterVec.MetricVec, dto.MetricType_COUNTER, expected)
expectCTsForMetricVecValues(t, vec.(*counterVec).MetricVec, dto.MetricType_COUNTER, expected)

// Recreate metric instance should reset created timestamp to now.
counterVec.DeleteLabelValues("1")
counterVec.WithLabelValues("1")
vec.DeleteLabelValues("1")
vec.WithLabelValues("1")
expected["1"] = now

now = now.Add(1 * time.Hour)
expectCTsForMetricVecValues(t, counterVec.MetricVec, dto.MetricType_COUNTER, expected)
expectCTsForMetricVecValues(t, vec.(*counterVec).MetricVec, dto.MetricType_COUNTER, expected)
}

func expectCTsForMetricVecValues(t testing.TB, vec *MetricVec, typ dto.MetricType, ctsPerLabelValue map[string]time.Time) {
func expectCTsForMetricVecValues(t testing.TB, vec MetricVec, typ dto.MetricType, ctsPerLabelValue map[string]time.Time) {
t.Helper()

for val, ct := range ctsPerLabelValue {
Expand Down
2 changes: 1 addition & 1 deletion prometheus/example_metricvec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (i Info) Write(out *dto.Metric) error {
// to do to fully implement a vector for a custom Metric implementation, we do
// it in this example anyway.
type InfoVec struct {
*prometheus.MetricVec
prometheus.MetricVec
}

func NewInfoVec(name, help string, labelNames []string) *InfoVec {
Expand Down
2 changes: 1 addition & 1 deletion prometheus/example_timer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var requestDuration = prometheus.NewHistogram(prometheus.HistogramOpts{

func ExampleTimer() {
// timer times this example function. It uses a Histogram, but a Summary
// would also work, as both implement Observer. Check out
// would also work, as both implement ObserverMethod. Check out
// https://prometheus.io/docs/practices/histograms/ for differences.
timer := prometheus.NewTimer(requestDuration)
defer timer.ObserveDuration()
Expand Down
38 changes: 26 additions & 12 deletions prometheus/gauge.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,28 +143,42 @@ func (g *gauge) Write(out *dto.Metric) error {
// you want to count the same thing partitioned by various dimensions
// (e.g. number of operations queued, partitioned by user and operation
// type). Create instances with NewGaugeVec.
type GaugeVec struct {
*MetricVec
type GaugeVec interface {
Delete(labels Labels) bool
DeleteLabelValues(...string) bool
DeletePartialMatch(Labels) int
GetMetricWith(Labels) (Gauge, error)
GetMetricWithLabelValues(...string) (Gauge, error)
With(Labels) Gauge
WithLabelValues(...string) Gauge
CurryWith(Labels) (GaugeVec, error)
MustCurryWith(Labels) GaugeVec
Reset()
Collector
}

type gaugeVec struct {
MetricVec
}

// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
// partitioned by the given label names.
func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
func NewGaugeVec(opts GaugeOpts, labelNames []string) GaugeVec {
return V2.NewGaugeVec(GaugeVecOpts{
GaugeOpts: opts,
VariableLabels: UnconstrainedLabels(labelNames),
})
}

// NewGaugeVec creates a new GaugeVec based on the provided GaugeVecOpts.
func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec {
func (v2) NewGaugeVec(opts GaugeVecOpts) GaugeVec {
desc := V2.NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
opts.Help,
opts.VariableLabels,
opts.ConstLabels,
)
return &GaugeVec{
return &gaugeVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels.names) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, lvs))
Expand Down Expand Up @@ -199,7 +213,7 @@ func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec {
// an alternative to avoid that type of mistake. For higher label numbers, the
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
func (v *gaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Gauge), err
Expand All @@ -219,7 +233,7 @@ func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
func (v *gaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Gauge), err
Expand All @@ -232,7 +246,7 @@ func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
// error allows shortcuts like
//
// myVec.WithLabelValues("404", "GET").Add(42)
func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge {
func (v *gaugeVec) WithLabelValues(lvs ...string) Gauge {
g, err := v.GetMetricWithLabelValues(lvs...)
if err != nil {
panic(err)
Expand All @@ -244,7 +258,7 @@ func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge {
// returned an error. Not returning an error allows shortcuts like
//
// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
func (v *GaugeVec) With(labels Labels) Gauge {
func (v *gaugeVec) With(labels Labels) Gauge {
g, err := v.GetMetricWith(labels)
if err != nil {
panic(err)
Expand All @@ -265,17 +279,17 @@ func (v *GaugeVec) With(labels Labels) Gauge {
// vectors behave identically in terms of collection. Only one must be
// registered with a given registry (usually the uncurried version). The Reset
// method deletes all metrics, even if called on a curried vector.
func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
func (v *gaugeVec) CurryWith(labels Labels) (GaugeVec, error) {
vec, err := v.MetricVec.CurryWith(labels)
if vec != nil {
return &GaugeVec{vec}, err
return &gaugeVec{vec}, err
}
return nil, err
}

// MustCurryWith works as CurryWith but panics where CurryWith would have
// returned an error.
func (v *GaugeVec) MustCurryWith(labels Labels) *GaugeVec {
func (v *gaugeVec) MustCurryWith(labels Labels) GaugeVec {
vec, err := v.CurryWith(labels)
if err != nil {
panic(err)
Expand Down
14 changes: 7 additions & 7 deletions prometheus/histogram.go
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ func (h *histogram) updateExemplar(v float64, bucket int, l Labels) {
// (e.g. HTTP request latencies, partitioned by status code and method). Create
// instances with NewHistogramVec.
type HistogramVec struct {
*MetricVec
MetricVec
}

// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
Expand Down Expand Up @@ -1222,10 +1222,10 @@ func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec {
// latter has a much more readable (albeit more verbose) syntax, but it comes
// with a performance overhead (for creating and processing the Labels map).
// See also the GaugeVec example.
func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (ObserverMethod, error) {
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
if metric != nil {
return metric.(Observer), err
return metric.(ObserverMethod), err
}
return nil, err
}
Expand All @@ -1242,10 +1242,10 @@ func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error)
// This method is used for the same purpose as
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
// methods.
func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
func (v *HistogramVec) GetMetricWith(labels Labels) (ObserverMethod, error) {
metric, err := v.MetricVec.GetMetricWith(labels)
if metric != nil {
return metric.(Observer), err
return metric.(ObserverMethod), err
}
return nil, err
}
Expand All @@ -1255,7 +1255,7 @@ func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
// error allows shortcuts like
//
// myVec.WithLabelValues("404", "GET").Observe(42.21)
func (v *HistogramVec) WithLabelValues(lvs ...string) Observer {
func (v *HistogramVec) WithLabelValues(lvs ...string) ObserverMethod {
h, err := v.GetMetricWithLabelValues(lvs...)
if err != nil {
panic(err)
Expand All @@ -1267,7 +1267,7 @@ func (v *HistogramVec) WithLabelValues(lvs ...string) Observer {
// returned an error. Not returning an error allows shortcuts like
//
// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21)
func (v *HistogramVec) With(labels Labels) Observer {
func (v *HistogramVec) With(labels Labels) ObserverMethod {
h, err := v.GetMetricWith(labels)
if err != nil {
panic(err)
Expand Down
Loading
Loading