diff --git a/exporter.go b/exporter.go index 5175906e..3502cf90 100644 --- a/exporter.go +++ b/exporter.go @@ -218,11 +218,12 @@ func (c *TimerEvent) Labels() map[string]string { return c.labels } type Events []Event type Exporter struct { - Counters *CounterContainer - Gauges *GaugeContainer - Summaries *SummaryContainer - Histograms *HistogramContainer - mapper *metricMapper + Counters *CounterContainer + Gauges *GaugeContainer + Summaries *SummaryContainer + Histograms *HistogramContainer + mapper *metricMapper + dropUnmapped bool } func escapeMetricName(metricName string) string { @@ -257,6 +258,9 @@ func (b *Exporter) Listen(e <-chan Events) { } } else { eventsUnmapped.Inc() + if b.dropUnmapped == true { + continue + } metricName = escapeMetricName(event.MetricName()) } @@ -351,13 +355,14 @@ func (b *Exporter) Listen(e <-chan Events) { } } -func NewExporter(mapper *metricMapper) *Exporter { +func NewExporter(mapper *metricMapper, dropUnmapped bool) *Exporter { return &Exporter{ - Counters: NewCounterContainer(), - Gauges: NewGaugeContainer(), - Summaries: NewSummaryContainer(), - Histograms: NewHistogramContainer(mapper), - mapper: mapper, + Counters: NewCounterContainer(), + Gauges: NewGaugeContainer(), + Summaries: NewSummaryContainer(), + Histograms: NewHistogramContainer(mapper), + mapper: mapper, + dropUnmapped: dropUnmapped, } } diff --git a/exporter_test.go b/exporter_test.go index aa3c60f9..eaaf9be3 100644 --- a/exporter_test.go +++ b/exporter_test.go @@ -44,7 +44,30 @@ func TestNegativeCounter(t *testing.T) { }, } events <- c - ex := NewExporter(&metricMapper{}) + ex := NewExporter(&metricMapper{}, false) + + // Close channel to signify we are done with the listener after a short period. + go func() { + time.Sleep(time.Millisecond * 100) + close(events) + }() + + ex.Listen(events) +} + +// TestDropUnmapped validates that the dropUnmapped global will prevent unmapped +// metrics from being recorded when set true and that they are recorded when set +// false. +func TestDropUnmapped(t *testing.T) { + events := make(chan Events, 1) + c := Events{ + &CounterEvent{ + metricName: "foo", + value: 1, + }, + } + events <- c + ex := NewExporter(&metricMapper{}, true, true) // Close channel to signify we are done with the listener after a short period. go func() { @@ -53,6 +76,21 @@ func TestNegativeCounter(t *testing.T) { }() ex.Listen(events) + if len(ex.Counters.Elements) != 0 { + t.Fatalf("Unmapped metric recorded inspite of dropUnmapped being set true") + } + ex = NewExporter(&metricMapper{}, true, false) + events = make(chan Events, 1) + events <- c + // Close channel to signify we are done with the listener after a short period. + go func() { + time.Sleep(time.Millisecond * 100) + close(events) + }() + ex.Listen(events) + if len(ex.Counters.Elements) != 1 { + t.Fatalf("Unmapped metric not recorded inspite of dropUnmapped being set false") + } } // TestInvalidUtf8InDatadogTagValue validates robustness of exporter listener @@ -60,7 +98,7 @@ func TestNegativeCounter(t *testing.T) { // It sends the same tags first with a valid value, then with an invalid one. // The exporter should not panic, but drop the invalid event func TestInvalidUtf8InDatadogTagValue(t *testing.T) { - ex := NewExporter(&metricMapper{}) + ex := NewExporter(&metricMapper{}, false) for _, l := range []statsDPacketHandler{&StatsDUDPListener{}, &mockStatsDTCPListener{}} { events := make(chan Events, 2) diff --git a/main.go b/main.go index da4dbe4a..55fb43c8 100644 --- a/main.go +++ b/main.go @@ -40,6 +40,7 @@ var ( mappingConfig = flag.String("statsd.mapping-config", "", "Metric mapping configuration file name.") readBuffer = flag.Int("statsd.read-buffer", 0, "Size (in bytes) of the operating system's transmit read buffer associated with the UDP connection. Please make sure the kernel parameters net.core.rmem_max is set to a value greater than the value specified.") showVersion = flag.Bool("version", false, "Print version information.") + dropUnmapped = flag.Bool("statsd.drop-unmapped", false, "Drop statsd metrics which have no matched mapping configured.") ) func serveHTTP() { @@ -194,6 +195,6 @@ func main() { } go watchConfig(*mappingConfig, mapper) } - exporter := NewExporter(mapper) + exporter := NewExporter(mapper, *dropUnmapped) exporter.Listen(events) }