Skip to content

Commit

Permalink
Move mapper to a package
Browse files Browse the repository at this point in the history
This allows the mapping logic and configuration format to be re-used by
the graphite exporter.

Enables prometheus/graphite_exporter#37, cf. prometheus/graphite_exporter#52 (comment)

Signed-off-by: Matthias Rampke <[email protected]>
  • Loading branch information
Matthias Rampke committed Aug 12, 2018
1 parent 419e27d commit 124c5b8
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 118 deletions.
58 changes: 30 additions & 28 deletions exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"github.com/prometheus/common/model"

"github.com/prometheus/statsd_exporter/mapper"
)

const (
Expand Down Expand Up @@ -117,17 +119,17 @@ func (c *GaugeContainer) Get(metricName string, labels prometheus.Labels, help s

type SummaryContainer struct {
Elements map[uint64]prometheus.Summary
mapper *metricMapper
mapper *mapper.MetricMapper
}

func NewSummaryContainer(mapper *metricMapper) *SummaryContainer {
func NewSummaryContainer(mapper *mapper.MetricMapper) *SummaryContainer {
return &SummaryContainer{
Elements: make(map[uint64]prometheus.Summary),
mapper: mapper,
}
}

func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels, help string, mapping *metricMapping) (prometheus.Summary, error) {
func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels, help string, mapping *mapper.MetricMapping) (prometheus.Summary, error) {
hash := hashNameAndLabels(metricName, labels)
summary, ok := c.Elements[hash]
if !ok {
Expand Down Expand Up @@ -156,17 +158,17 @@ func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels, help

type HistogramContainer struct {
Elements map[uint64]prometheus.Histogram
mapper *metricMapper
mapper *mapper.MetricMapper
}

func NewHistogramContainer(mapper *metricMapper) *HistogramContainer {
func NewHistogramContainer(mapper *mapper.MetricMapper) *HistogramContainer {
return &HistogramContainer{
Elements: make(map[uint64]prometheus.Histogram),
mapper: mapper,
}
}

func (c *HistogramContainer) Get(metricName string, labels prometheus.Labels, help string, mapping *metricMapping) (prometheus.Histogram, error) {
func (c *HistogramContainer) Get(metricName string, labels prometheus.Labels, help string, mapping *mapper.MetricMapping) (prometheus.Histogram, error) {
hash := hashNameAndLabels(metricName, labels)
histogram, ok := c.Elements[hash]
if !ok {
Expand All @@ -193,7 +195,7 @@ type Event interface {
MetricName() string
Value() float64
Labels() map[string]string
MetricType() metricType
MetricType() mapper.MetricType
}

type CounterEvent struct {
Expand All @@ -202,10 +204,10 @@ type CounterEvent struct {
labels map[string]string
}

func (c *CounterEvent) MetricName() string { return c.metricName }
func (c *CounterEvent) Value() float64 { return c.value }
func (c *CounterEvent) Labels() map[string]string { return c.labels }
func (c *CounterEvent) MetricType() metricType { return metricTypeCounter }
func (c *CounterEvent) MetricName() string { return c.metricName }
func (c *CounterEvent) Value() float64 { return c.value }
func (c *CounterEvent) Labels() map[string]string { return c.labels }
func (c *CounterEvent) MetricType() mapper.MetricType { return mapper.MetricTypeCounter }

type GaugeEvent struct {
metricName string
Expand All @@ -214,21 +216,21 @@ type GaugeEvent struct {
labels map[string]string
}

func (g *GaugeEvent) MetricName() string { return g.metricName }
func (g *GaugeEvent) Value() float64 { return g.value }
func (c *GaugeEvent) Labels() map[string]string { return c.labels }
func (c *GaugeEvent) MetricType() metricType { return metricTypeGauge }
func (g *GaugeEvent) MetricName() string { return g.metricName }
func (g *GaugeEvent) Value() float64 { return g.value }
func (c *GaugeEvent) Labels() map[string]string { return c.labels }
func (c *GaugeEvent) MetricType() mapper.MetricType { return mapper.MetricTypeGauge }

type TimerEvent struct {
metricName string
value float64
labels map[string]string
}

func (t *TimerEvent) MetricName() string { return t.metricName }
func (t *TimerEvent) Value() float64 { return t.value }
func (c *TimerEvent) Labels() map[string]string { return c.labels }
func (c *TimerEvent) MetricType() metricType { return metricTypeTimer }
func (t *TimerEvent) MetricName() string { return t.metricName }
func (t *TimerEvent) Value() float64 { return t.value }
func (c *TimerEvent) Labels() map[string]string { return c.labels }
func (c *TimerEvent) MetricType() mapper.MetricType { return mapper.MetricTypeTimer }

type Events []Event

Expand All @@ -237,7 +239,7 @@ type Exporter struct {
Gauges *GaugeContainer
Summaries *SummaryContainer
Histograms *HistogramContainer
mapper *metricMapper
mapper *mapper.MetricMapper
}

func escapeMetricName(metricName string) string {
Expand All @@ -263,12 +265,12 @@ func (b *Exporter) Listen(e <-chan Events) {
metricName := ""
prometheusLabels := event.Labels()

mapping, labels, present := b.mapper.getMapping(event.MetricName(), event.MetricType())
mapping, labels, present := b.mapper.GetMapping(event.MetricName(), event.MetricType())
if mapping == nil {
mapping = &metricMapping{}
mapping = &mapper.MetricMapping{}
}

if mapping.Action == actionTypeDrop {
if mapping.Action == mapper.ActionTypeDrop {
continue
}

Expand Down Expand Up @@ -332,16 +334,16 @@ func (b *Exporter) Listen(e <-chan Events) {
}

case *TimerEvent:
t := timerTypeDefault
t := mapper.TimerTypeDefault
if mapping != nil {
t = mapping.TimerType
}
if t == timerTypeDefault {
if t == mapper.TimerTypeDefault {
t = b.mapper.Defaults.TimerType
}

switch t {
case timerTypeHistogram:
case mapper.TimerTypeHistogram:
histogram, err := b.Histograms.Get(
metricName,
prometheusLabels,
Expand All @@ -356,7 +358,7 @@ func (b *Exporter) Listen(e <-chan Events) {
conflictingEventStats.WithLabelValues("timer").Inc()
}

case timerTypeDefault, timerTypeSummary:
case mapper.TimerTypeDefault, mapper.TimerTypeSummary:
summary, err := b.Summaries.Get(
metricName,
prometheusLabels,
Expand All @@ -383,7 +385,7 @@ func (b *Exporter) Listen(e <-chan Events) {
}
}

func NewExporter(mapper *metricMapper) *Exporter {
func NewExporter(mapper *mapper.MetricMapper) *Exporter {
return &Exporter{
Counters: NewCounterContainer(),
Gauges: NewGaugeContainer(),
Expand Down
10 changes: 6 additions & 4 deletions exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"time"

"github.com/prometheus/client_golang/prometheus"

"github.com/prometheus/statsd_exporter/mapper"
)

// TestNegativeCounter validates when we send a negative
Expand All @@ -44,7 +46,7 @@ func TestNegativeCounter(t *testing.T) {
},
}
events <- c
ex := NewExporter(&metricMapper{})
ex := NewExporter(&mapper.MetricMapper{})

// Close channel to signify we are done with the listener after a short period.
go func() {
Expand All @@ -60,7 +62,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(&mapper.MetricMapper{})
for _, l := range []statsDPacketHandler{&StatsDUDPListener{}, &mockStatsDTCPListener{}} {
events := make(chan Events, 2)

Expand Down Expand Up @@ -96,8 +98,8 @@ func TestHistogramUnits(t *testing.T) {
},
}
events <- c
ex := NewExporter(&metricMapper{})
ex.mapper.Defaults.TimerType = timerTypeHistogram
ex := NewExporter(&mapper.MetricMapper{})
ex.mapper.Defaults.TimerType = mapper.TimerTypeHistogram

// Close channel to signify we are done with the listener after a short period.
go func() {
Expand Down
10 changes: 6 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"github.com/prometheus/common/version"

"github.com/prometheus/statsd_exporter/mapper"
)

func init() {
Expand Down Expand Up @@ -96,7 +98,7 @@ func tcpAddrFromString(addr string) *net.TCPAddr {
}
}

func watchConfig(fileName string, mapper *metricMapper) {
func watchConfig(fileName string, mapper *mapper.MetricMapper) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
Expand All @@ -111,7 +113,7 @@ func watchConfig(fileName string, mapper *metricMapper) {
select {
case ev := <-watcher.Event:
log.Infof("Config file changed (%s), attempting reload", ev)
err = mapper.initFromFile(fileName)
err = mapper.InitFromFile(fileName)
if err != nil {
log.Errorln("Error reloading config:", err)
configLoads.WithLabelValues("failure").Inc()
Expand Down Expand Up @@ -186,9 +188,9 @@ func main() {
go tl.Listen(events)
}

mapper := &metricMapper{}
mapper := &mapper.MetricMapper{}
if *mappingConfig != "" {
err := mapper.initFromFile(*mappingConfig)
err := mapper.InitFromFile(*mappingConfig)
if err != nil {
log.Fatal("Error loading config:", err)
}
Expand Down
22 changes: 11 additions & 11 deletions action.go → mapper/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package main
package mapper

import "fmt"

type actionType string
type ActionType string

const (
actionTypeMap actionType = "map"
actionTypeDrop actionType = "drop"
actionTypeDefault actionType = ""
ActionTypeMap ActionType = "map"
ActionTypeDrop ActionType = "drop"
ActionTypeDefault ActionType = ""
)

func (t *actionType) UnmarshalYAML(unmarshal func(interface{}) error) error {
func (t *ActionType) UnmarshalYAML(unmarshal func(interface{}) error) error {
var v string

if err := unmarshal(&v); err != nil {
return err
}

switch actionType(v) {
case actionTypeDrop:
*t = actionTypeDrop
case actionTypeMap, actionTypeDefault:
*t = actionTypeMap
switch ActionType(v) {
case ActionTypeDrop:
*t = ActionTypeDrop
case ActionTypeMap, ActionTypeDefault:
*t = ActionTypeMap
default:
return fmt.Errorf("invalid action type %q", v)
}
Expand Down
38 changes: 19 additions & 19 deletions mapper.go → mapper/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package main
package mapper

import (
"fmt"
Expand All @@ -34,32 +34,32 @@ var (
)

type mapperConfigDefaults struct {
TimerType timerType `yaml:"timer_type"`
TimerType TimerType `yaml:"timer_type"`
Buckets []float64 `yaml:"buckets"`
Quantiles []metricObjective `yaml:"quantiles"`
MatchType matchType `yaml:"match_type"`
MatchType MatchType `yaml:"match_type"`
}

type metricMapper struct {
type MetricMapper struct {
Defaults mapperConfigDefaults `yaml:"defaults"`
Mappings []metricMapping `yaml:"mappings"`
Mappings []MetricMapping `yaml:"mappings"`
mutex sync.Mutex
}

type matchMetricType string

type metricMapping struct {
type MetricMapping struct {
Match string `yaml:"match"`
Name string `yaml:"name"`
regex *regexp.Regexp
Labels prometheus.Labels `yaml:"labels"`
TimerType timerType `yaml:"timer_type"`
TimerType TimerType `yaml:"timer_type"`
Buckets []float64 `yaml:"buckets"`
Quantiles []metricObjective `yaml:"quantiles"`
MatchType matchType `yaml:"match_type"`
MatchType MatchType `yaml:"match_type"`
HelpText string `yaml:"help"`
Action actionType `yaml:"action"`
MatchMetricType metricType `yaml:"match_metric_type"`
Action ActionType `yaml:"action"`
MatchMetricType MetricType `yaml:"match_metric_type"`
}

type metricObjective struct {
Expand All @@ -73,8 +73,8 @@ var defaultQuantiles = []metricObjective{
{Quantile: 0.99, Error: 0.001},
}

func (m *metricMapper) initFromYAMLString(fileContents string) error {
var n metricMapper
func (m *MetricMapper) InitFromYAMLString(fileContents string) error {
var n MetricMapper

if err := yaml.Unmarshal([]byte(fileContents), &n); err != nil {
return err
Expand All @@ -88,8 +88,8 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
n.Defaults.Quantiles = defaultQuantiles
}

if n.Defaults.MatchType == matchTypeDefault {
n.Defaults.MatchType = matchTypeGlob
if n.Defaults.MatchType == MatchTypeDefault {
n.Defaults.MatchType = MatchTypeGlob
}

for i := range n.Mappings {
Expand All @@ -115,10 +115,10 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
}

if currentMapping.Action == "" {
currentMapping.Action = actionTypeMap
currentMapping.Action = ActionTypeMap
}

if currentMapping.MatchType == matchTypeGlob {
if currentMapping.MatchType == MatchTypeGlob {
if !metricLineRE.MatchString(currentMapping.Match) {
return fmt.Errorf("invalid match: %s", currentMapping.Match)
}
Expand Down Expand Up @@ -164,15 +164,15 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
return nil
}

func (m *metricMapper) initFromFile(fileName string) error {
func (m *MetricMapper) InitFromFile(fileName string) error {
mappingStr, err := ioutil.ReadFile(fileName)
if err != nil {
return err
}
return m.initFromYAMLString(string(mappingStr))
return m.InitFromYAMLString(string(mappingStr))
}

func (m *metricMapper) getMapping(statsdMetric string, statsdMetricType metricType) (*metricMapping, prometheus.Labels, bool) {
func (m *MetricMapper) GetMapping(statsdMetric string, statsdMetricType MetricType) (*MetricMapping, prometheus.Labels, bool) {
m.mutex.Lock()
defer m.mutex.Unlock()

Expand Down
Loading

0 comments on commit 124c5b8

Please sign in to comment.