mirror of
https://github.com/prometheus/statsd_exporter.git
synced 2024-12-23 14:00:30 +00:00
Added increment/decrement support to Gauges
Now passing the value as a string (with operation prefix) through to build event so that Listen() can modify the gauge metric appropriately
This commit is contained in:
parent
446b7e6d44
commit
7fc8727306
2 changed files with 75 additions and 3 deletions
|
@ -33,6 +33,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 2,
|
||||
valueStr: "2",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
@ -43,6 +44,29 @@ func TestHandlePacket(t *testing.T) {
|
|||
&GaugeEvent{
|
||||
metricName: "foo",
|
||||
value: 3,
|
||||
valueStr: "3",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
name: "simple gauge with sampling",
|
||||
in: "foo:100|g|@0.1",
|
||||
out: Events{
|
||||
&GaugeEvent{
|
||||
metricName: "foo",
|
||||
value: 1000,
|
||||
valueStr: "1000",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
name: "gauge decrement",
|
||||
in: "foo:-10|g",
|
||||
out: Events{
|
||||
&GaugeEvent{
|
||||
metricName: "foo",
|
||||
value: -10,
|
||||
valueStr: "-10",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
@ -53,6 +77,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&TimerEvent{
|
||||
metricName: "foo",
|
||||
value: 200,
|
||||
valueStr: "200",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
@ -63,6 +88,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 100,
|
||||
valueStr: "100",
|
||||
labels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
||||
},
|
||||
},
|
||||
|
@ -73,6 +99,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 100,
|
||||
valueStr: "100",
|
||||
labels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
||||
},
|
||||
},
|
||||
|
@ -83,6 +110,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 100,
|
||||
valueStr: "100",
|
||||
labels: map[string]string{"_09digits": "0", "tag_with_dots": "1"},
|
||||
},
|
||||
},
|
||||
|
@ -93,6 +121,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 100,
|
||||
valueStr: "100",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
@ -103,6 +132,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 100,
|
||||
valueStr: "100",
|
||||
labels: map[string]string{"tag": "value"},
|
||||
},
|
||||
},
|
||||
|
@ -113,6 +143,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 100,
|
||||
valueStr: "100",
|
||||
labels: map[string]string{"tag": "value"},
|
||||
},
|
||||
},
|
||||
|
@ -123,6 +154,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 1000,
|
||||
valueStr: "1000",
|
||||
labels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
||||
},
|
||||
},
|
||||
|
@ -133,6 +165,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 1000,
|
||||
valueStr: "1000",
|
||||
labels: map[string]string{"tag1": "foo:bar"},
|
||||
},
|
||||
},
|
||||
|
@ -149,6 +182,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 200,
|
||||
valueStr: "200",
|
||||
labels: map[string]string{"tag": "value"},
|
||||
},
|
||||
},
|
||||
|
@ -159,31 +193,37 @@ func TestHandlePacket(t *testing.T) {
|
|||
&TimerEvent{
|
||||
metricName: "foo",
|
||||
value: 200,
|
||||
valueStr: "200",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
&TimerEvent{
|
||||
metricName: "foo",
|
||||
value: 300,
|
||||
valueStr: "300",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 50,
|
||||
valueStr: "50",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
&GaugeEvent{
|
||||
metricName: "foo",
|
||||
value: 6,
|
||||
valueStr: "6",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
&CounterEvent{
|
||||
metricName: "bar",
|
||||
value: 1,
|
||||
valueStr: "1",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
&TimerEvent{
|
||||
metricName: "bar",
|
||||
value: 5,
|
||||
valueStr: "5",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
@ -203,6 +243,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 1,
|
||||
valueStr: "1",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
@ -213,6 +254,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "foo",
|
||||
value: 2,
|
||||
valueStr: "2",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
@ -239,6 +281,7 @@ func TestHandlePacket(t *testing.T) {
|
|||
&CounterEvent{
|
||||
metricName: "valid_utf8",
|
||||
value: 1,
|
||||
valueStr: "1",
|
||||
labels: map[string]string{},
|
||||
},
|
||||
},
|
||||
|
|
35
exporter.go
35
exporter.go
|
@ -23,6 +23,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
"math"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/log"
|
||||
|
@ -144,37 +145,44 @@ func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels) prom
|
|||
type Event interface {
|
||||
MetricName() string
|
||||
Value() float64
|
||||
ValueStr() string
|
||||
Labels() map[string]string
|
||||
}
|
||||
|
||||
type CounterEvent struct {
|
||||
metricName string
|
||||
value float64
|
||||
valueStr string
|
||||
labels map[string]string
|
||||
}
|
||||
|
||||
func (c *CounterEvent) MetricName() string { return c.metricName }
|
||||
func (c *CounterEvent) Value() float64 { return c.value }
|
||||
func (c *CounterEvent) ValueStr() string { return c.valueStr }
|
||||
func (c *CounterEvent) Labels() map[string]string { return c.labels }
|
||||
|
||||
type GaugeEvent struct {
|
||||
metricName string
|
||||
value float64
|
||||
valueStr string
|
||||
labels map[string]string
|
||||
}
|
||||
|
||||
func (g *GaugeEvent) MetricName() string { return g.metricName }
|
||||
func (g *GaugeEvent) Value() float64 { return g.value }
|
||||
func (g *GaugeEvent) ValueStr() string { return g.valueStr }
|
||||
func (c *GaugeEvent) Labels() map[string]string { return c.labels }
|
||||
|
||||
type TimerEvent struct {
|
||||
metricName string
|
||||
value float64
|
||||
valueStr string
|
||||
labels map[string]string
|
||||
}
|
||||
|
||||
func (t *TimerEvent) MetricName() string { return t.metricName }
|
||||
func (t *TimerEvent) Value() float64 { return t.value }
|
||||
func (t *TimerEvent) ValueStr() string { return t.valueStr }
|
||||
func (c *TimerEvent) Labels() map[string]string { return c.labels }
|
||||
|
||||
type Events []Event
|
||||
|
@ -252,7 +260,15 @@ func (b *Exporter) Listen(e <-chan Events) {
|
|||
b.suffix(metricName, "gauge"),
|
||||
prometheusLabels,
|
||||
)
|
||||
gauge.Set(event.Value())
|
||||
|
||||
var value = event.ValueStr()
|
||||
if strings.Index(value, "+") == 0 {
|
||||
gauge.Add(event.Value())
|
||||
} else if strings.Index(value, "-") == 0 {
|
||||
gauge.Sub(math.Abs(event.Value()))
|
||||
} else {
|
||||
gauge.Set(event.Value())
|
||||
}
|
||||
|
||||
eventStats.WithLabelValues("gauge").Inc()
|
||||
|
||||
|
@ -287,24 +303,27 @@ type StatsDListener struct {
|
|||
conn *net.UDPConn
|
||||
}
|
||||
|
||||
func buildEvent(statType, metric string, value float64, labels map[string]string) (Event, error) {
|
||||
func buildEvent(statType, metric string, value float64, valueStr string, labels map[string]string) (Event, error) {
|
||||
switch statType {
|
||||
case "c":
|
||||
return &CounterEvent{
|
||||
metricName: metric,
|
||||
value: float64(value),
|
||||
valueStr: valueStr,
|
||||
labels: labels,
|
||||
}, nil
|
||||
case "g":
|
||||
return &GaugeEvent{
|
||||
metricName: metric,
|
||||
value: float64(value),
|
||||
valueStr: valueStr,
|
||||
labels: labels,
|
||||
}, nil
|
||||
case "ms", "h":
|
||||
return &TimerEvent{
|
||||
metricName: metric,
|
||||
value: float64(value),
|
||||
valueStr: valueStr,
|
||||
labels: labels,
|
||||
}, nil
|
||||
case "s":
|
||||
|
@ -375,6 +394,14 @@ func (l *StatsDListener) handlePacket(packet []byte, e chan<- Events) {
|
|||
continue
|
||||
}
|
||||
valueStr, statType := components[0], components[1]
|
||||
|
||||
var prefix = ""
|
||||
if strings.Index(valueStr, "+") == 0 {
|
||||
prefix = "+"
|
||||
} else if strings.Index(valueStr, "-") == 0 {
|
||||
prefix = "-"
|
||||
}
|
||||
|
||||
value, err := strconv.ParseFloat(valueStr, 64)
|
||||
if err != nil {
|
||||
log.Errorf("Bad value %s on line: %s", valueStr, line)
|
||||
|
@ -418,7 +445,9 @@ func (l *StatsDListener) handlePacket(packet []byte, e chan<- Events) {
|
|||
}
|
||||
}
|
||||
|
||||
event, err := buildEvent(statType, metric, value, labels)
|
||||
// convert the (possibly) sampled value to a string and add the operation prefix back on
|
||||
valueStr = prefix + strconv.FormatFloat(math.Abs(value), 'f', -1, 64)
|
||||
event, err := buildEvent(statType, metric, value, valueStr, labels)
|
||||
if err != nil {
|
||||
log.Errorf("Error building event on line %s: %s", line, err)
|
||||
networkStats.WithLabelValues("illegal_event").Inc()
|
||||
|
|
Loading…
Reference in a new issue