forked from mirrors/statsd_exporter
Move mapper to a package
This allows the mapping logic and configuration format to be re-used by the graphite exporter. Enables prometheus/graphite_exporter#37, cf. https://github.com/prometheus/graphite_exporter/pull/52#issuecomment-412324849 Signed-off-by: Matthias Rampke <mr@soundcloud.com>
This commit is contained in:
parent
419e27d284
commit
124c5b88d0
11 changed files with 148 additions and 118 deletions
40
exporter.go
40
exporter.go
|
@ -29,6 +29,8 @@ import (
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
|
||||||
|
"github.com/prometheus/statsd_exporter/mapper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -117,17 +119,17 @@ func (c *GaugeContainer) Get(metricName string, labels prometheus.Labels, help s
|
||||||
|
|
||||||
type SummaryContainer struct {
|
type SummaryContainer struct {
|
||||||
Elements map[uint64]prometheus.Summary
|
Elements map[uint64]prometheus.Summary
|
||||||
mapper *metricMapper
|
mapper *mapper.MetricMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSummaryContainer(mapper *metricMapper) *SummaryContainer {
|
func NewSummaryContainer(mapper *mapper.MetricMapper) *SummaryContainer {
|
||||||
return &SummaryContainer{
|
return &SummaryContainer{
|
||||||
Elements: make(map[uint64]prometheus.Summary),
|
Elements: make(map[uint64]prometheus.Summary),
|
||||||
mapper: mapper,
|
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)
|
hash := hashNameAndLabels(metricName, labels)
|
||||||
summary, ok := c.Elements[hash]
|
summary, ok := c.Elements[hash]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -156,17 +158,17 @@ func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels, help
|
||||||
|
|
||||||
type HistogramContainer struct {
|
type HistogramContainer struct {
|
||||||
Elements map[uint64]prometheus.Histogram
|
Elements map[uint64]prometheus.Histogram
|
||||||
mapper *metricMapper
|
mapper *mapper.MetricMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHistogramContainer(mapper *metricMapper) *HistogramContainer {
|
func NewHistogramContainer(mapper *mapper.MetricMapper) *HistogramContainer {
|
||||||
return &HistogramContainer{
|
return &HistogramContainer{
|
||||||
Elements: make(map[uint64]prometheus.Histogram),
|
Elements: make(map[uint64]prometheus.Histogram),
|
||||||
mapper: mapper,
|
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)
|
hash := hashNameAndLabels(metricName, labels)
|
||||||
histogram, ok := c.Elements[hash]
|
histogram, ok := c.Elements[hash]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -193,7 +195,7 @@ type Event interface {
|
||||||
MetricName() string
|
MetricName() string
|
||||||
Value() float64
|
Value() float64
|
||||||
Labels() map[string]string
|
Labels() map[string]string
|
||||||
MetricType() metricType
|
MetricType() mapper.MetricType
|
||||||
}
|
}
|
||||||
|
|
||||||
type CounterEvent struct {
|
type CounterEvent struct {
|
||||||
|
@ -205,7 +207,7 @@ type CounterEvent struct {
|
||||||
func (c *CounterEvent) MetricName() string { return c.metricName }
|
func (c *CounterEvent) MetricName() string { return c.metricName }
|
||||||
func (c *CounterEvent) Value() float64 { return c.value }
|
func (c *CounterEvent) Value() float64 { return c.value }
|
||||||
func (c *CounterEvent) Labels() map[string]string { return c.labels }
|
func (c *CounterEvent) Labels() map[string]string { return c.labels }
|
||||||
func (c *CounterEvent) MetricType() metricType { return metricTypeCounter }
|
func (c *CounterEvent) MetricType() mapper.MetricType { return mapper.MetricTypeCounter }
|
||||||
|
|
||||||
type GaugeEvent struct {
|
type GaugeEvent struct {
|
||||||
metricName string
|
metricName string
|
||||||
|
@ -217,7 +219,7 @@ type GaugeEvent struct {
|
||||||
func (g *GaugeEvent) MetricName() string { return g.metricName }
|
func (g *GaugeEvent) MetricName() string { return g.metricName }
|
||||||
func (g *GaugeEvent) Value() float64 { return g.value }
|
func (g *GaugeEvent) Value() float64 { return g.value }
|
||||||
func (c *GaugeEvent) Labels() map[string]string { return c.labels }
|
func (c *GaugeEvent) Labels() map[string]string { return c.labels }
|
||||||
func (c *GaugeEvent) MetricType() metricType { return metricTypeGauge }
|
func (c *GaugeEvent) MetricType() mapper.MetricType { return mapper.MetricTypeGauge }
|
||||||
|
|
||||||
type TimerEvent struct {
|
type TimerEvent struct {
|
||||||
metricName string
|
metricName string
|
||||||
|
@ -228,7 +230,7 @@ type TimerEvent struct {
|
||||||
func (t *TimerEvent) MetricName() string { return t.metricName }
|
func (t *TimerEvent) MetricName() string { return t.metricName }
|
||||||
func (t *TimerEvent) Value() float64 { return t.value }
|
func (t *TimerEvent) Value() float64 { return t.value }
|
||||||
func (c *TimerEvent) Labels() map[string]string { return c.labels }
|
func (c *TimerEvent) Labels() map[string]string { return c.labels }
|
||||||
func (c *TimerEvent) MetricType() metricType { return metricTypeTimer }
|
func (c *TimerEvent) MetricType() mapper.MetricType { return mapper.MetricTypeTimer }
|
||||||
|
|
||||||
type Events []Event
|
type Events []Event
|
||||||
|
|
||||||
|
@ -237,7 +239,7 @@ type Exporter struct {
|
||||||
Gauges *GaugeContainer
|
Gauges *GaugeContainer
|
||||||
Summaries *SummaryContainer
|
Summaries *SummaryContainer
|
||||||
Histograms *HistogramContainer
|
Histograms *HistogramContainer
|
||||||
mapper *metricMapper
|
mapper *mapper.MetricMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func escapeMetricName(metricName string) string {
|
func escapeMetricName(metricName string) string {
|
||||||
|
@ -263,12 +265,12 @@ func (b *Exporter) Listen(e <-chan Events) {
|
||||||
metricName := ""
|
metricName := ""
|
||||||
prometheusLabels := event.Labels()
|
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 {
|
if mapping == nil {
|
||||||
mapping = &metricMapping{}
|
mapping = &mapper.MetricMapping{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if mapping.Action == actionTypeDrop {
|
if mapping.Action == mapper.ActionTypeDrop {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,16 +334,16 @@ func (b *Exporter) Listen(e <-chan Events) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case *TimerEvent:
|
case *TimerEvent:
|
||||||
t := timerTypeDefault
|
t := mapper.TimerTypeDefault
|
||||||
if mapping != nil {
|
if mapping != nil {
|
||||||
t = mapping.TimerType
|
t = mapping.TimerType
|
||||||
}
|
}
|
||||||
if t == timerTypeDefault {
|
if t == mapper.TimerTypeDefault {
|
||||||
t = b.mapper.Defaults.TimerType
|
t = b.mapper.Defaults.TimerType
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case timerTypeHistogram:
|
case mapper.TimerTypeHistogram:
|
||||||
histogram, err := b.Histograms.Get(
|
histogram, err := b.Histograms.Get(
|
||||||
metricName,
|
metricName,
|
||||||
prometheusLabels,
|
prometheusLabels,
|
||||||
|
@ -356,7 +358,7 @@ func (b *Exporter) Listen(e <-chan Events) {
|
||||||
conflictingEventStats.WithLabelValues("timer").Inc()
|
conflictingEventStats.WithLabelValues("timer").Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
case timerTypeDefault, timerTypeSummary:
|
case mapper.TimerTypeDefault, mapper.TimerTypeSummary:
|
||||||
summary, err := b.Summaries.Get(
|
summary, err := b.Summaries.Get(
|
||||||
metricName,
|
metricName,
|
||||||
prometheusLabels,
|
prometheusLabels,
|
||||||
|
@ -383,7 +385,7 @@ func (b *Exporter) Listen(e <-chan Events) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExporter(mapper *metricMapper) *Exporter {
|
func NewExporter(mapper *mapper.MetricMapper) *Exporter {
|
||||||
return &Exporter{
|
return &Exporter{
|
||||||
Counters: NewCounterContainer(),
|
Counters: NewCounterContainer(),
|
||||||
Gauges: NewGaugeContainer(),
|
Gauges: NewGaugeContainer(),
|
||||||
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
|
"github.com/prometheus/statsd_exporter/mapper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestNegativeCounter validates when we send a negative
|
// TestNegativeCounter validates when we send a negative
|
||||||
|
@ -44,7 +46,7 @@ func TestNegativeCounter(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
events <- c
|
events <- c
|
||||||
ex := NewExporter(&metricMapper{})
|
ex := NewExporter(&mapper.MetricMapper{})
|
||||||
|
|
||||||
// Close channel to signify we are done with the listener after a short period.
|
// Close channel to signify we are done with the listener after a short period.
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -60,7 +62,7 @@ func TestNegativeCounter(t *testing.T) {
|
||||||
// It sends the same tags first with a valid value, then with an invalid one.
|
// 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
|
// The exporter should not panic, but drop the invalid event
|
||||||
func TestInvalidUtf8InDatadogTagValue(t *testing.T) {
|
func TestInvalidUtf8InDatadogTagValue(t *testing.T) {
|
||||||
ex := NewExporter(&metricMapper{})
|
ex := NewExporter(&mapper.MetricMapper{})
|
||||||
for _, l := range []statsDPacketHandler{&StatsDUDPListener{}, &mockStatsDTCPListener{}} {
|
for _, l := range []statsDPacketHandler{&StatsDUDPListener{}, &mockStatsDTCPListener{}} {
|
||||||
events := make(chan Events, 2)
|
events := make(chan Events, 2)
|
||||||
|
|
||||||
|
@ -96,8 +98,8 @@ func TestHistogramUnits(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
events <- c
|
events <- c
|
||||||
ex := NewExporter(&metricMapper{})
|
ex := NewExporter(&mapper.MetricMapper{})
|
||||||
ex.mapper.Defaults.TimerType = timerTypeHistogram
|
ex.mapper.Defaults.TimerType = mapper.TimerTypeHistogram
|
||||||
|
|
||||||
// Close channel to signify we are done with the listener after a short period.
|
// Close channel to signify we are done with the listener after a short period.
|
||||||
go func() {
|
go func() {
|
||||||
|
|
10
main.go
10
main.go
|
@ -25,6 +25,8 @@ import (
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
"github.com/prometheus/common/version"
|
"github.com/prometheus/common/version"
|
||||||
|
|
||||||
|
"github.com/prometheus/statsd_exporter/mapper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -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()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -111,7 +113,7 @@ func watchConfig(fileName string, mapper *metricMapper) {
|
||||||
select {
|
select {
|
||||||
case ev := <-watcher.Event:
|
case ev := <-watcher.Event:
|
||||||
log.Infof("Config file changed (%s), attempting reload", ev)
|
log.Infof("Config file changed (%s), attempting reload", ev)
|
||||||
err = mapper.initFromFile(fileName)
|
err = mapper.InitFromFile(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("Error reloading config:", err)
|
log.Errorln("Error reloading config:", err)
|
||||||
configLoads.WithLabelValues("failure").Inc()
|
configLoads.WithLabelValues("failure").Inc()
|
||||||
|
@ -186,9 +188,9 @@ func main() {
|
||||||
go tl.Listen(events)
|
go tl.Listen(events)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapper := &metricMapper{}
|
mapper := &mapper.MetricMapper{}
|
||||||
if *mappingConfig != "" {
|
if *mappingConfig != "" {
|
||||||
err := mapper.initFromFile(*mappingConfig)
|
err := mapper.InitFromFile(*mappingConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error loading config:", err)
|
log.Fatal("Error loading config:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,30 +11,30 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package main
|
package mapper
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type actionType string
|
type ActionType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
actionTypeMap actionType = "map"
|
ActionTypeMap ActionType = "map"
|
||||||
actionTypeDrop actionType = "drop"
|
ActionTypeDrop ActionType = "drop"
|
||||||
actionTypeDefault actionType = ""
|
ActionTypeDefault ActionType = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *actionType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (t *ActionType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
var v string
|
var v string
|
||||||
|
|
||||||
if err := unmarshal(&v); err != nil {
|
if err := unmarshal(&v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch actionType(v) {
|
switch ActionType(v) {
|
||||||
case actionTypeDrop:
|
case ActionTypeDrop:
|
||||||
*t = actionTypeDrop
|
*t = ActionTypeDrop
|
||||||
case actionTypeMap, actionTypeDefault:
|
case ActionTypeMap, ActionTypeDefault:
|
||||||
*t = actionTypeMap
|
*t = ActionTypeMap
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid action type %q", v)
|
return fmt.Errorf("invalid action type %q", v)
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package main
|
package mapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -34,32 +34,32 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type mapperConfigDefaults struct {
|
type mapperConfigDefaults struct {
|
||||||
TimerType timerType `yaml:"timer_type"`
|
TimerType TimerType `yaml:"timer_type"`
|
||||||
Buckets []float64 `yaml:"buckets"`
|
Buckets []float64 `yaml:"buckets"`
|
||||||
Quantiles []metricObjective `yaml:"quantiles"`
|
Quantiles []metricObjective `yaml:"quantiles"`
|
||||||
MatchType matchType `yaml:"match_type"`
|
MatchType MatchType `yaml:"match_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type metricMapper struct {
|
type MetricMapper struct {
|
||||||
Defaults mapperConfigDefaults `yaml:"defaults"`
|
Defaults mapperConfigDefaults `yaml:"defaults"`
|
||||||
Mappings []metricMapping `yaml:"mappings"`
|
Mappings []MetricMapping `yaml:"mappings"`
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type matchMetricType string
|
type matchMetricType string
|
||||||
|
|
||||||
type metricMapping struct {
|
type MetricMapping struct {
|
||||||
Match string `yaml:"match"`
|
Match string `yaml:"match"`
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
regex *regexp.Regexp
|
regex *regexp.Regexp
|
||||||
Labels prometheus.Labels `yaml:"labels"`
|
Labels prometheus.Labels `yaml:"labels"`
|
||||||
TimerType timerType `yaml:"timer_type"`
|
TimerType TimerType `yaml:"timer_type"`
|
||||||
Buckets []float64 `yaml:"buckets"`
|
Buckets []float64 `yaml:"buckets"`
|
||||||
Quantiles []metricObjective `yaml:"quantiles"`
|
Quantiles []metricObjective `yaml:"quantiles"`
|
||||||
MatchType matchType `yaml:"match_type"`
|
MatchType MatchType `yaml:"match_type"`
|
||||||
HelpText string `yaml:"help"`
|
HelpText string `yaml:"help"`
|
||||||
Action actionType `yaml:"action"`
|
Action ActionType `yaml:"action"`
|
||||||
MatchMetricType metricType `yaml:"match_metric_type"`
|
MatchMetricType MetricType `yaml:"match_metric_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type metricObjective struct {
|
type metricObjective struct {
|
||||||
|
@ -73,8 +73,8 @@ var defaultQuantiles = []metricObjective{
|
||||||
{Quantile: 0.99, Error: 0.001},
|
{Quantile: 0.99, Error: 0.001},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *metricMapper) initFromYAMLString(fileContents string) error {
|
func (m *MetricMapper) InitFromYAMLString(fileContents string) error {
|
||||||
var n metricMapper
|
var n MetricMapper
|
||||||
|
|
||||||
if err := yaml.Unmarshal([]byte(fileContents), &n); err != nil {
|
if err := yaml.Unmarshal([]byte(fileContents), &n); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -88,8 +88,8 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
|
||||||
n.Defaults.Quantiles = defaultQuantiles
|
n.Defaults.Quantiles = defaultQuantiles
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Defaults.MatchType == matchTypeDefault {
|
if n.Defaults.MatchType == MatchTypeDefault {
|
||||||
n.Defaults.MatchType = matchTypeGlob
|
n.Defaults.MatchType = MatchTypeGlob
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range n.Mappings {
|
for i := range n.Mappings {
|
||||||
|
@ -115,10 +115,10 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentMapping.Action == "" {
|
if currentMapping.Action == "" {
|
||||||
currentMapping.Action = actionTypeMap
|
currentMapping.Action = ActionTypeMap
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentMapping.MatchType == matchTypeGlob {
|
if currentMapping.MatchType == MatchTypeGlob {
|
||||||
if !metricLineRE.MatchString(currentMapping.Match) {
|
if !metricLineRE.MatchString(currentMapping.Match) {
|
||||||
return fmt.Errorf("invalid match: %s", currentMapping.Match)
|
return fmt.Errorf("invalid match: %s", currentMapping.Match)
|
||||||
}
|
}
|
||||||
|
@ -164,15 +164,15 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *metricMapper) initFromFile(fileName string) error {
|
func (m *MetricMapper) InitFromFile(fileName string) error {
|
||||||
mappingStr, err := ioutil.ReadFile(fileName)
|
mappingStr, err := ioutil.ReadFile(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package main
|
package mapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -473,9 +473,9 @@ mappings:
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mapper := metricMapper{}
|
mapper := MetricMapper{}
|
||||||
for i, scenario := range scenarios {
|
for i, scenario := range scenarios {
|
||||||
err := mapper.initFromYAMLString(scenario.config)
|
err := mapper.InitFromYAMLString(scenario.config)
|
||||||
if err != nil && !scenario.configBad {
|
if err != nil && !scenario.configBad {
|
||||||
t.Fatalf("%d. Config load error: %s %s", i, scenario.config, err)
|
t.Fatalf("%d. Config load error: %s %s", i, scenario.config, err)
|
||||||
}
|
}
|
||||||
|
@ -483,9 +483,9 @@ mappings:
|
||||||
t.Fatalf("%d. Expected bad config, but loaded ok: %s", i, scenario.config)
|
t.Fatalf("%d. Expected bad config, but loaded ok: %s", i, scenario.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
var dummyMetricType metricType = ""
|
var dummyMetricType MetricType = ""
|
||||||
for metric, mapping := range scenario.mappings {
|
for metric, mapping := range scenario.mappings {
|
||||||
m, labels, present := mapper.getMapping(metric, dummyMetricType)
|
m, labels, present := mapper.GetMapping(metric, dummyMetricType)
|
||||||
if present && mapping.name != "" && m.Name != mapping.name {
|
if present && mapping.name != "" && m.Name != mapping.name {
|
||||||
t.Fatalf("%d.%q: Expected name %v, got %v", i, metric, m.Name, mapping.name)
|
t.Fatalf("%d.%q: Expected name %v, got %v", i, metric, m.Name, mapping.name)
|
||||||
}
|
}
|
||||||
|
@ -522,7 +522,7 @@ func TestAction(t *testing.T) {
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
config string
|
config string
|
||||||
configBad bool
|
configBad bool
|
||||||
expectedAction actionType
|
expectedAction ActionType
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
// no action set
|
// no action set
|
||||||
|
@ -532,7 +532,7 @@ mappings:
|
||||||
name: "foo"
|
name: "foo"
|
||||||
`,
|
`,
|
||||||
configBad: false,
|
configBad: false,
|
||||||
expectedAction: actionTypeMap,
|
expectedAction: ActionTypeMap,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// map action set
|
// map action set
|
||||||
|
@ -543,7 +543,7 @@ mappings:
|
||||||
action: map
|
action: map
|
||||||
`,
|
`,
|
||||||
configBad: false,
|
configBad: false,
|
||||||
expectedAction: actionTypeMap,
|
expectedAction: ActionTypeMap,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// drop action set
|
// drop action set
|
||||||
|
@ -554,7 +554,7 @@ mappings:
|
||||||
action: drop
|
action: drop
|
||||||
`,
|
`,
|
||||||
configBad: false,
|
configBad: false,
|
||||||
expectedAction: actionTypeDrop,
|
expectedAction: ActionTypeDrop,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// invalid action set
|
// invalid action set
|
||||||
|
@ -565,13 +565,13 @@ mappings:
|
||||||
action: xyz
|
action: xyz
|
||||||
`,
|
`,
|
||||||
configBad: true,
|
configBad: true,
|
||||||
expectedAction: actionTypeDrop,
|
expectedAction: ActionTypeDrop,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, scenario := range scenarios {
|
for i, scenario := range scenarios {
|
||||||
mapper := metricMapper{}
|
mapper := MetricMapper{}
|
||||||
err := mapper.initFromYAMLString(scenario.config)
|
err := mapper.InitFromYAMLString(scenario.config)
|
||||||
if err != nil && !scenario.configBad {
|
if err != nil && !scenario.configBad {
|
||||||
t.Fatalf("%d. Config load error: %s %s", i, scenario.config, err)
|
t.Fatalf("%d. Config load error: %s %s", i, scenario.config, err)
|
||||||
}
|
}
|
|
@ -11,29 +11,29 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package main
|
package mapper
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type matchType string
|
type MatchType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
matchTypeGlob matchType = "glob"
|
MatchTypeGlob MatchType = "glob"
|
||||||
matchTypeRegex matchType = "regex"
|
MatchTypeRegex MatchType = "regex"
|
||||||
matchTypeDefault matchType = ""
|
MatchTypeDefault MatchType = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *matchType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (t *MatchType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
var v string
|
var v string
|
||||||
if err := unmarshal(&v); err != nil {
|
if err := unmarshal(&v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch matchType(v) {
|
switch MatchType(v) {
|
||||||
case matchTypeRegex:
|
case MatchTypeRegex:
|
||||||
*t = matchTypeRegex
|
*t = MatchTypeRegex
|
||||||
case matchTypeGlob, matchTypeDefault:
|
case MatchTypeGlob, MatchTypeDefault:
|
||||||
*t = matchTypeGlob
|
*t = MatchTypeGlob
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid match type %q", v)
|
return fmt.Errorf("invalid match type %q", v)
|
||||||
}
|
}
|
|
@ -11,31 +11,31 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package main
|
package mapper
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type metricType string
|
type MetricType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
metricTypeCounter metricType = "counter"
|
MetricTypeCounter MetricType = "counter"
|
||||||
metricTypeGauge metricType = "gauge"
|
MetricTypeGauge MetricType = "gauge"
|
||||||
metricTypeTimer metricType = "timer"
|
MetricTypeTimer MetricType = "timer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *metricType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (m *MetricType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
var v string
|
var v string
|
||||||
if err := unmarshal(&v); err != nil {
|
if err := unmarshal(&v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch metricType(v) {
|
switch MetricType(v) {
|
||||||
case metricTypeCounter:
|
case MetricTypeCounter:
|
||||||
*m = metricTypeCounter
|
*m = MetricTypeCounter
|
||||||
case metricTypeGauge:
|
case MetricTypeGauge:
|
||||||
*m = metricTypeGauge
|
*m = MetricTypeGauge
|
||||||
case metricTypeTimer:
|
case MetricTypeTimer:
|
||||||
*m = metricTypeTimer
|
*m = MetricTypeTimer
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid metric type '%s'", v)
|
return fmt.Errorf("invalid metric type '%s'", v)
|
||||||
}
|
}
|
29
mapper/telemetry.go
Normal file
29
mapper/telemetry.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2013 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package mapper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mappingsCount = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: "statsd_exporter_loaded_mappings",
|
||||||
|
Help: "The current number of configured metric mappings.",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prometheus.MustRegister(mappingsCount)
|
||||||
|
}
|
|
@ -11,29 +11,29 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package main
|
package mapper
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type timerType string
|
type TimerType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
timerTypeHistogram timerType = "histogram"
|
TimerTypeHistogram TimerType = "histogram"
|
||||||
timerTypeSummary timerType = "summary"
|
TimerTypeSummary TimerType = "summary"
|
||||||
timerTypeDefault timerType = ""
|
TimerTypeDefault TimerType = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *timerType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (t *TimerType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
var v string
|
var v string
|
||||||
if err := unmarshal(&v); err != nil {
|
if err := unmarshal(&v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch timerType(v) {
|
switch TimerType(v) {
|
||||||
case timerTypeHistogram:
|
case TimerTypeHistogram:
|
||||||
*t = timerTypeHistogram
|
*t = TimerTypeHistogram
|
||||||
case timerTypeSummary, timerTypeDefault:
|
case TimerTypeSummary, TimerTypeDefault:
|
||||||
*t = timerTypeSummary
|
*t = TimerTypeSummary
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid timer type '%s'", v)
|
return fmt.Errorf("invalid timer type '%s'", v)
|
||||||
}
|
}
|
|
@ -91,10 +91,6 @@ var (
|
||||||
},
|
},
|
||||||
[]string{"outcome"},
|
[]string{"outcome"},
|
||||||
)
|
)
|
||||||
mappingsCount = prometheus.NewGauge(prometheus.GaugeOpts{
|
|
||||||
Name: "statsd_exporter_loaded_mappings",
|
|
||||||
Help: "The current number of configured metric mappings.",
|
|
||||||
})
|
|
||||||
conflictingEventStats = prometheus.NewCounterVec(
|
conflictingEventStats = prometheus.NewCounterVec(
|
||||||
prometheus.CounterOpts{
|
prometheus.CounterOpts{
|
||||||
Name: "statsd_exporter_events_conflict_total",
|
Name: "statsd_exporter_events_conflict_total",
|
||||||
|
@ -116,6 +112,5 @@ func init() {
|
||||||
prometheus.MustRegister(tagsReceived)
|
prometheus.MustRegister(tagsReceived)
|
||||||
prometheus.MustRegister(tagErrors)
|
prometheus.MustRegister(tagErrors)
|
||||||
prometheus.MustRegister(configLoads)
|
prometheus.MustRegister(configLoads)
|
||||||
prometheus.MustRegister(mappingsCount)
|
|
||||||
prometheus.MustRegister(conflictingEventStats)
|
prometheus.MustRegister(conflictingEventStats)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue