Merge pull request #72 from jacksontj/master

Fixes for crashes with conflicting metric values
This commit is contained in:
Tobias Schmidt 2017-07-18 20:19:59 +02:00 committed by GitHub
commit 8b40f781ef
2 changed files with 50 additions and 27 deletions

View file

@ -69,7 +69,7 @@ func NewCounterContainer() *CounterContainer {
} }
} }
func (c *CounterContainer) Get(metricName string, labels prometheus.Labels) prometheus.Counter { func (c *CounterContainer) Get(metricName string, labels prometheus.Labels) (prometheus.Counter, error) {
hash := hashNameAndLabels(metricName, labels) hash := hashNameAndLabels(metricName, labels)
counter, ok := c.Elements[hash] counter, ok := c.Elements[hash]
if !ok { if !ok {
@ -78,12 +78,12 @@ func (c *CounterContainer) Get(metricName string, labels prometheus.Labels) prom
Help: defaultHelp, Help: defaultHelp,
ConstLabels: labels, ConstLabels: labels,
}) })
c.Elements[hash] = counter
if err := prometheus.Register(counter); err != nil { if err := prometheus.Register(counter); err != nil {
log.Fatalf(regErrF, metricName, err) return nil, err
} }
c.Elements[hash] = counter
} }
return counter return counter, nil
} }
type GaugeContainer struct { type GaugeContainer struct {
@ -96,7 +96,7 @@ func NewGaugeContainer() *GaugeContainer {
} }
} }
func (c *GaugeContainer) Get(metricName string, labels prometheus.Labels) prometheus.Gauge { func (c *GaugeContainer) Get(metricName string, labels prometheus.Labels) (prometheus.Gauge, error) {
hash := hashNameAndLabels(metricName, labels) hash := hashNameAndLabels(metricName, labels)
gauge, ok := c.Elements[hash] gauge, ok := c.Elements[hash]
if !ok { if !ok {
@ -105,12 +105,12 @@ func (c *GaugeContainer) Get(metricName string, labels prometheus.Labels) promet
Help: defaultHelp, Help: defaultHelp,
ConstLabels: labels, ConstLabels: labels,
}) })
c.Elements[hash] = gauge
if err := prometheus.Register(gauge); err != nil { if err := prometheus.Register(gauge); err != nil {
log.Fatalf(regErrF, metricName, err) return nil, err
} }
c.Elements[hash] = gauge
} }
return gauge return gauge, nil
} }
type SummaryContainer struct { type SummaryContainer struct {
@ -123,7 +123,7 @@ func NewSummaryContainer() *SummaryContainer {
} }
} }
func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels) prometheus.Summary { func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels) (prometheus.Summary, error) {
hash := hashNameAndLabels(metricName, labels) hash := hashNameAndLabels(metricName, labels)
summary, ok := c.Elements[hash] summary, ok := c.Elements[hash]
if !ok { if !ok {
@ -133,12 +133,12 @@ func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels) prom
Help: defaultHelp, Help: defaultHelp,
ConstLabels: labels, ConstLabels: labels,
}) })
c.Elements[hash] = summary
if err := prometheus.Register(summary); err != nil { if err := prometheus.Register(summary); err != nil {
log.Fatalf(regErrF, metricName, err) return nil, err
} }
c.Elements[hash] = summary
} }
return summary return summary, nil
} }
type Event interface { type Event interface {
@ -233,10 +233,6 @@ func (b *Exporter) Listen(e <-chan Events) {
switch ev := event.(type) { switch ev := event.(type) {
case *CounterEvent: case *CounterEvent:
counter := b.Counters.Get(
b.suffix(metricName, "counter"),
prometheusLabels,
)
// We don't accept negative values for counters. Incrementing the counter with a negative number // We don't accept negative values for counters. Incrementing the counter with a negative number
// will cause the exporter to panic. Instead we will warn and continue to the next event. // will cause the exporter to panic. Instead we will warn and continue to the next event.
if event.Value() < 0.0 { if event.Value() < 0.0 {
@ -244,16 +240,26 @@ func (b *Exporter) Listen(e <-chan Events) {
continue continue
} }
counter, err := b.Counters.Get(
b.suffix(metricName, "counter"),
prometheusLabels,
)
if err == nil {
counter.Add(event.Value()) counter.Add(event.Value())
eventStats.WithLabelValues("counter").Inc() eventStats.WithLabelValues("counter").Inc()
} else {
log.Errorf(regErrF, metricName, err)
conflictingEventStats.WithLabelValues("counter").Inc()
}
case *GaugeEvent: case *GaugeEvent:
gauge := b.Gauges.Get( gauge, err := b.Gauges.Get(
b.suffix(metricName, "gauge"), b.suffix(metricName, "gauge"),
prometheusLabels, prometheusLabels,
) )
if err == nil {
if ev.relative { if ev.relative {
gauge.Add(event.Value()) gauge.Add(event.Value())
} else { } else {
@ -261,15 +267,24 @@ func (b *Exporter) Listen(e <-chan Events) {
} }
eventStats.WithLabelValues("gauge").Inc() eventStats.WithLabelValues("gauge").Inc()
} else {
log.Errorf(regErrF, metricName, err)
conflictingEventStats.WithLabelValues("gauge").Inc()
}
case *TimerEvent: case *TimerEvent:
summary := b.Summaries.Get( summary, err := b.Summaries.Get(
b.suffix(metricName, "timer"), b.suffix(metricName, "timer"),
prometheusLabels, prometheusLabels,
) )
if err == nil {
summary.Observe(event.Value()) summary.Observe(event.Value())
eventStats.WithLabelValues("timer").Inc() eventStats.WithLabelValues("timer").Inc()
} else {
log.Errorf(regErrF, metricName, err)
conflictingEventStats.WithLabelValues("timer").Inc()
}
default: default:
log.Errorln("Unsupported event type") log.Errorln("Unsupported event type")

View file

@ -47,6 +47,13 @@ var (
Name: "statsd_exporter_loaded_mappings", Name: "statsd_exporter_loaded_mappings",
Help: "The current number of configured metric mappings.", Help: "The current number of configured metric mappings.",
}) })
conflictingEventStats = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "statsd_exporter_events_conflict_total",
Help: "The total number of StatsD events with conflicting names.",
},
[]string{"type"},
)
) )
func init() { func init() {
@ -54,4 +61,5 @@ func init() {
prometheus.MustRegister(networkStats) prometheus.MustRegister(networkStats)
prometheus.MustRegister(configLoads) prometheus.MustRegister(configLoads)
prometheus.MustRegister(mappingsCount) prometheus.MustRegister(mappingsCount)
prometheus.MustRegister(conflictingEventStats)
} }