Skip to content

Commit

Permalink
Add name normalizer
Browse files Browse the repository at this point in the history
Signed-off-by: Yuri Shkuro <ys@uber.com>
  • Loading branch information
Yuri Shkuro committed Nov 7, 2017
1 parent 7c1739c commit 7ccca79
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 17 deletions.
42 changes: 28 additions & 14 deletions metrics/prometheus/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package prometheus

import (
"sort"
"strings"
"time"

"github.com/prometheus/client_golang/prometheus"
Expand All @@ -25,10 +26,11 @@ import (

// Factory implements metrics.Factory backed my Prometheus registry.
type Factory struct {
scope string
tags map[string]string
cache *vectorCache
buckets []float64
scope string
tags map[string]string
cache *vectorCache
buckets []float64
normalizer *strings.Replacer
}

// New creates a Factory backed by Prometheus registry.
Expand All @@ -40,15 +42,23 @@ type Factory struct {
// to add a highest bucket with +Inf bound, it will be added
// implicitly. The default value is prometheus.DefBuckets.
func New(registerer prometheus.Registerer, buckets []float64) *Factory {
return newFactory(newVectorCache(registerer), "", nil, buckets)
return newFactory(
&Factory{ // dummy struct to be discarded
cache: newVectorCache(registerer),
buckets: buckets,
normalizer: strings.NewReplacer(".", "_", "-", "_"),
},
"",
nil)
}

func newFactory(cache *vectorCache, scope string, tags map[string]string, buckets []float64) *Factory {
func newFactory(parent *Factory, scope string, tags map[string]string) *Factory {
return &Factory{
cache: cache,
scope: scope,
tags: tags,
buckets: buckets,
cache: parent.cache,
buckets: parent.buckets,
normalizer: parent.normalizer,
scope: scope,
tags: tags,
}
}

Expand Down Expand Up @@ -100,7 +110,7 @@ func (f *Factory) Timer(name string, tags map[string]string) metrics.Timer {

// Namespace implements Namespace of metrics.Factory.
func (f *Factory) Namespace(name string, tags map[string]string) metrics.Factory {
return newFactory(f.cache, f.subScope(name), f.mergeTags(tags), f.buckets)
return newFactory(f, f.subScope(name), f.mergeTags(tags))
}

type counter struct {
Expand Down Expand Up @@ -129,12 +139,16 @@ func (t *timer) Record(v time.Duration) {

func (f *Factory) subScope(name string) string {
if f.scope == "" {
return name
return f.normalize(name)
}
if name == "" {
return f.scope
return f.normalize(f.scope)
}
return f.scope + ":" + name
return f.normalize(f.scope + ":" + name)
}

func (f *Factory) normalize(v string) string {
return f.normalizer.Replace(v)
}

func (f *Factory) mergeTags(tags map[string]string) map[string]string {
Expand Down
7 changes: 4 additions & 3 deletions metrics/prometheus/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,18 @@ func TestTimer(t *testing.T) {
}
}

func TestTimerCustomBuckts(t *testing.T) {
func TestTimerCustomBuckets(t *testing.T) {
registry := prometheus.NewPedanticRegistry()
f1 := New(registry, []float64{1.5})
t1 := f1.Timer("bender:rodriguez", map[string]string{"x": "y"})
// dot and dash in the metric name will be replaced with underscore
t1 := f1.Timer("bender.bending-rodriguez", map[string]string{"x": "y"})
t1.Record(1 * time.Second)
t1.Record(2 * time.Second)

snapshot, err := registry.Gather()
require.NoError(t, err)

m1 := findMetric(t, snapshot, "bender:rodriguez", map[string]string{"x": "y"})
m1 := findMetric(t, snapshot, "bender_bending_rodriguez", map[string]string{"x": "y"})
assert.EqualValues(t, 2, m1.GetHistogram().GetSampleCount(), "%+v", m1)
assert.EqualValues(t, 3, m1.GetHistogram().GetSampleSum(), "%+v", m1)
assert.Len(t, m1.GetHistogram().GetBucket(), 1)
Expand Down

0 comments on commit 7ccca79

Please sign in to comment.