Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GaugeFloat64 API #151

Merged
merged 1 commit into from
May 19, 2023
Merged
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
10 changes: 5 additions & 5 deletions circonus/circonus.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ type Config cgm.Config
// NewCirconusSink - create new metric sink for circonus
//
// one of the following must be supplied:
// - API Token - search for an existing check or create a new check
// - API Token + Check Id - the check identified by check id will be used
// - API Token + Check Submission URL - the check identified by the submission url will be used
// - Check Submission URL - the check identified by the submission url will be used
// metric management will be *disabled*
// - API Token - search for an existing check or create a new check
// - API Token + Check Id - the check identified by check id will be used
// - API Token + Check Submission URL - the check identified by the submission url will be used
// - Check Submission URL - the check identified by the submission url will be used
// metric management will be *disabled*
//
// Note: If submission url is supplied w/o an api token, the public circonus ca cert will be used
// to verify the broker for metrics submission.
Expand Down
12 changes: 12 additions & 0 deletions datadog/dogstatsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ func (s *DogStatsdSink) SetGauge(key []string, val float32) {
s.SetGaugeWithLabels(key, val, nil)
}

func (s *DogStatsdSink) SetPrecisionGauge(key []string, val float64) {
s.SetPrecisionGaugeWithLabels(key, val, nil)
}

func (s *DogStatsdSink) IncrCounter(key []string, val float32) {
s.IncrCounterWithLabels(key, val, nil)
}
Expand All @@ -108,6 +112,14 @@ func (s *DogStatsdSink) SetGaugeWithLabels(key []string, val float32, labels []m
s.client.Gauge(flatKey, float64(val), tags, rate)
}

// The following ...WithLabels methods correspond to Datadog's Tag extension to Statsd.
// http://docs.datadoghq.com/guides/dogstatsd/#tags
func (s *DogStatsdSink) SetPrecisionGaugeWithLabels(key []string, val float64, labels []metrics.Label) {
flatKey, tags := s.getFlatkeyAndCombinedLabels(key, labels)
rate := 1.0
s.client.Gauge(flatKey, val, tags, rate)
}

func (s *DogStatsdSink) IncrCounterWithLabels(key []string, val float32, labels []metrics.Label) {
flatKey, tags := s.getFlatkeyAndCombinedLabels(key, labels)
rate := 1.0
Expand Down
33 changes: 27 additions & 6 deletions inmem.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ type IntervalMetrics struct {
// Gauges maps the key to the last set value
Gauges map[string]GaugeValue

// PrecisionGauges maps the key to the last set value
PrecisionGauges map[string]PrecisionGaugeValue

// Points maps the string to the list of emitted values
// from EmitKey
Points map[string][]float32
Expand All @@ -64,12 +67,13 @@ type IntervalMetrics struct {
// NewIntervalMetrics creates a new IntervalMetrics for a given interval
func NewIntervalMetrics(intv time.Time) *IntervalMetrics {
return &IntervalMetrics{
Interval: intv,
Gauges: make(map[string]GaugeValue),
Points: make(map[string][]float32),
Counters: make(map[string]SampledValue),
Samples: make(map[string]SampledValue),
done: make(chan struct{}),
Interval: intv,
Gauges: make(map[string]GaugeValue),
PrecisionGauges: make(map[string]PrecisionGaugeValue),
Points: make(map[string][]float32),
Counters: make(map[string]SampledValue),
Samples: make(map[string]SampledValue),
done: make(chan struct{}),
}
}

Expand Down Expand Up @@ -174,6 +178,19 @@ func (i *InmemSink) SetGaugeWithLabels(key []string, val float32, labels []Label
intv.Gauges[k] = GaugeValue{Name: name, Value: val, Labels: labels}
}

func (i *InmemSink) SetPrecisionGauge(key []string, val float64) {
i.SetPrecisionGaugeWithLabels(key, val, nil)
}

func (i *InmemSink) SetPrecisionGaugeWithLabels(key []string, val float64, labels []Label) {
k, name := i.flattenKeyLabels(key, labels)
intv := i.getInterval()

intv.Lock()
defer intv.Unlock()
intv.PrecisionGauges[k] = PrecisionGaugeValue{Name: name, Value: val, Labels: labels}
}

func (i *InmemSink) EmitKey(key []string, val float32) {
k := i.flattenKey(key)
intv := i.getInterval()
Expand Down Expand Up @@ -257,6 +274,10 @@ func (i *InmemSink) Data() []*IntervalMetrics {
for k, v := range current.Gauges {
copyCurrent.Gauges[k] = v
}
copyCurrent.PrecisionGauges = make(map[string]PrecisionGaugeValue, len(current.PrecisionGauges))
for k, v := range current.PrecisionGauges {
copyCurrent.PrecisionGauges[k] = v
}
// saved values will be not change, just copy its link
copyCurrent.Points = make(map[string][]float32, len(current.Points))
for k, v := range current.Points {
Expand Down
41 changes: 33 additions & 8 deletions inmem_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (

// MetricsSummary holds a roll-up of metrics info for a given interval
type MetricsSummary struct {
Timestamp string
Gauges []GaugeValue
Points []PointValue
Counters []SampledValue
Samples []SampledValue
Timestamp string
Gauges []GaugeValue
PrecisionGauges []PrecisionGaugeValue
Points []PointValue
Counters []SampledValue
Samples []SampledValue
}

type GaugeValue struct {
Expand All @@ -26,6 +27,15 @@ type GaugeValue struct {
DisplayLabels map[string]string `json:"Labels"`
}

type PrecisionGaugeValue struct {
Name string
Hash string `json:"-"`
Value float64

Labels []Label `json:"-"`
DisplayLabels map[string]string `json:"Labels"`
}

type PointValue struct {
Name string
Points []float32
Expand Down Expand Up @@ -77,9 +87,10 @@ func newMetricSummaryFromInterval(interval *IntervalMetrics) MetricsSummary {
defer interval.RUnlock()

summary := MetricsSummary{
Timestamp: interval.Interval.Round(time.Second).UTC().String(),
Gauges: make([]GaugeValue, 0, len(interval.Gauges)),
Points: make([]PointValue, 0, len(interval.Points)),
Timestamp: interval.Interval.Round(time.Second).UTC().String(),
Gauges: make([]GaugeValue, 0, len(interval.Gauges)),
PrecisionGauges: make([]PrecisionGaugeValue, 0, len(interval.PrecisionGauges)),
Points: make([]PointValue, 0, len(interval.Points)),
}

// Format and sort the output of each metric type, so it gets displayed in a
Expand All @@ -105,6 +116,20 @@ func newMetricSummaryFromInterval(interval *IntervalMetrics) MetricsSummary {
return summary.Gauges[i].Hash < summary.Gauges[j].Hash
})

for hash, value := range interval.PrecisionGauges {
value.Hash = hash
value.DisplayLabels = make(map[string]string)
for _, label := range value.Labels {
value.DisplayLabels[label.Name] = label.Value
}
value.Labels = nil

summary.PrecisionGauges = append(summary.PrecisionGauges, value)
}
sort.Slice(summary.PrecisionGauges, func(i, j int) bool {
return summary.PrecisionGauges[i].Hash < summary.PrecisionGauges[j].Hash
})

summary.Counters = formatSamples(interval.Counters)
summary.Samples = formatSamples(interval.Samples)

Expand Down
4 changes: 4 additions & 0 deletions inmem_signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ func (i *InmemSignal) dumpStats() {
name := i.flattenLabels(val.Name, val.Labels)
fmt.Fprintf(buf, "[%v][G] '%s': %0.3f\n", intv.Interval, name, val.Value)
}
for _, val := range intv.PrecisionGauges {
name := i.flattenLabels(val.Name, val.Labels)
fmt.Fprintf(buf, "[%v][G] '%s': %0.3f\n", intv.Interval, name, val.Value)
}
for name, vals := range intv.Points {
for _, val := range vals {
fmt.Fprintf(buf, "[%v][P] '%s': %0.3f\n", intv.Interval, name, val)
Expand Down
34 changes: 34 additions & 0 deletions metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,40 @@ func (m *Metrics) SetGaugeWithLabels(key []string, val float32, labels []Label)
m.sink.SetGaugeWithLabels(key, val, labelsFiltered)
}

func (m *Metrics) SetPrecisionGauge(key []string, val float64) {
m.SetPrecisionGaugeWithLabels(key, val, nil)
}

func (m *Metrics) SetPrecisionGaugeWithLabels(key []string, val float64, labels []Label) {
if m.HostName != "" {
if m.EnableHostnameLabel {
labels = append(labels, Label{"host", m.HostName})
} else if m.EnableHostname {
key = insert(0, m.HostName, key)
}
}
if m.EnableTypePrefix {
key = insert(0, "gauge", key)
}
if m.ServiceName != "" {
if m.EnableServiceLabel {
labels = append(labels, Label{"service", m.ServiceName})
} else {
key = insert(0, m.ServiceName, key)
}
}
allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return
}
sink, ok := m.sink.(PrecisionGaugeMetricSink)
if !ok {
// Sink does not implement PrecisionGaugeMetricSink.
} else {
sink.SetPrecisionGaugeWithLabels(key, val, labelsFiltered)
}
}

func (m *Metrics) EmitKey(key []string, val float32) {
if m.EnableTypePrefix {
key = insert(0, "kv", key)
Expand Down
55 changes: 55 additions & 0 deletions metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,61 @@ func TestMetrics_SetGauge(t *testing.T) {
}
}

func TestMetrics_SetPrecisionGauge(t *testing.T) {
m, met := mockMetric()
met.SetPrecisionGauge([]string{"key"}, float64(1))
if m.getKeys()[0][0] != "key" {
t.Fatalf("")
}
if m.precisionVals[0] != 1 {
t.Fatalf("")
}

m, met = mockMetric()
labels := []Label{{"a", "b"}}
met.SetPrecisionGaugeWithLabels([]string{"key"}, float64(1), labels)
if m.getKeys()[0][0] != "key" {
t.Fatalf("")
}
if m.precisionVals[0] != 1 {
t.Fatalf("")
}
if !reflect.DeepEqual(m.labels[0], labels) {
t.Fatalf("")
}

m, met = mockMetric()
met.HostName = "test"
met.EnableHostname = true
met.SetPrecisionGauge([]string{"key"}, float64(1))
if m.getKeys()[0][0] != "test" || m.getKeys()[0][1] != "key" {
t.Fatalf("")
}
if m.precisionVals[0] != 1 {
t.Fatalf("")
}

m, met = mockMetric()
met.EnableTypePrefix = true
met.SetPrecisionGauge([]string{"key"}, float64(1))
if m.getKeys()[0][0] != "gauge" || m.getKeys()[0][1] != "key" {
t.Fatalf("")
}
if m.precisionVals[0] != 1 {
t.Fatalf("")
}

m, met = mockMetric()
met.ServiceName = "service"
met.SetPrecisionGauge([]string{"key"}, float64(1))
if m.getKeys()[0][0] != "service" || m.getKeys()[0][1] != "key" {
t.Fatalf("")
}
if m.precisionVals[0] != 1 {
t.Fatalf("")
}
}

func TestMetrics_EmitKey(t *testing.T) {
m, met := mockMetric()
met.EmitKey([]string{"key"}, float32(1))
Expand Down
14 changes: 11 additions & 3 deletions prometheus/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,18 @@ func prometheusLabels(labels []metrics.Label) prometheus.Labels {
}

func (p *PrometheusSink) SetGauge(parts []string, val float32) {
p.SetGaugeWithLabels(parts, val, nil)
p.SetPrecisionGauge(parts, float64(val))
}

func (p *PrometheusSink) SetGaugeWithLabels(parts []string, val float32, labels []metrics.Label) {
p.SetPrecisionGaugeWithLabels(parts, float64(val), labels)
}

func (p *PrometheusSink) SetPrecisionGauge(parts []string, val float64) {
p.SetPrecisionGaugeWithLabels(parts, val, nil)
}

func (p *PrometheusSink) SetPrecisionGaugeWithLabels(parts []string, val float64, labels []metrics.Label) {
key, hash := flattenKey(parts, labels)
pg, ok := p.gauges.Load(hash)

Expand All @@ -285,7 +293,7 @@ func (p *PrometheusSink) SetGaugeWithLabels(parts []string, val float32, labels
// value, but since we're always setting it to time.Now(), it doesn't really matter.
if ok {
localGauge := *pg.(*gauge)
localGauge.Set(float64(val))
localGauge.Set(val)
localGauge.updatedAt = time.Now()
p.gauges.Store(hash, &localGauge)

Expand All @@ -301,7 +309,7 @@ func (p *PrometheusSink) SetGaugeWithLabels(parts []string, val float32, labels
Help: help,
ConstLabels: prometheusLabels(labels),
})
g.Set(float64(val))
g.Set(val)
pg = &gauge{
Gauge: g,
updatedAt: time.Now(),
Expand Down
21 changes: 21 additions & 0 deletions prometheus/prometheus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,27 @@ func TestSetGauge(t *testing.T) {
}
}

func TestSetPrecisionGauge(t *testing.T) {
q := make(chan string)
server := fakeServer(q)
defer server.Close()
u, err := url.Parse(server.URL)
if err != nil {
log.Fatal(err)
}
host := u.Hostname() + ":" + u.Port()
sink, err := NewPrometheusPushSink(host, time.Second, "pushtest")
metricsConf := metrics.DefaultConfig("default")
metricsConf.HostName = MockGetHostname()
metricsConf.EnableHostnameLabel = true
metrics.NewGlobal(metricsConf, sink)
metrics.SetPrecisionGauge([]string{"one", "two"}, 42)
response := <-q
if response != "ok" {
t.Fatal(response)
}
}

func TestDefinitionsWithLabels(t *testing.T) {
gaugeDef := GaugeDefinition{
Name: []string{"my", "test", "gauge"},
Expand Down
Loading