Skip to content

Commit

Permalink
Adding mapping cache
Browse files Browse the repository at this point in the history
Signed-off-by: SpencerMalone <[email protected]>
  • Loading branch information
SpencerMalone committed Apr 15, 2019
1 parent 468c70d commit ae2681e
Show file tree
Hide file tree
Showing 19 changed files with 1,496 additions and 40 deletions.
6 changes: 3 additions & 3 deletions exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ mappings:
name: "histogram_test"
`
testMapper := &mapper.MetricMapper{}
err := testMapper.InitFromYAMLString(config)
err := testMapper.InitFromYAMLString(config, 0)
if err != nil {
t.Fatalf("Config load error: %s %s", config, err)
}
Expand Down Expand Up @@ -180,7 +180,7 @@ mappings:
name: "${1}"
`
testMapper := &mapper.MetricMapper{}
err := testMapper.InitFromYAMLString(config)
err := testMapper.InitFromYAMLString(config, 0)
if err != nil {
t.Fatalf("Config load error: %s %s", config, err)
}
Expand Down Expand Up @@ -338,7 +338,7 @@ mappings:
`
// Create mapper from config and start an Exporter with a synchronous channel
testMapper := &mapper.MetricMapper{}
err := testMapper.InitFromYAMLString(config)
err := testMapper.InitFromYAMLString(config, 0)
if err != nil {
t.Fatalf("Config load error: %s %s", config, err)
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.1
github.com/howeyc/fsnotify v0.0.0-20151003194602-f0c08ee9c607
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/howeyc/fsnotify v0.0.0-20151003194602-f0c08ee9c607 h1:+7wvV++11s0Okyl1dekihkIiCIYDz+Qk2LvxAShINU4=
github.com/howeyc/fsnotify v0.0.0-20151003194602-f0c08ee9c607/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
Expand Down
12 changes: 8 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func tcpAddrFromString(addr string) *net.TCPAddr {
}
}

func watchConfig(fileName string, mapper *mapper.MetricMapper) {
func watchConfig(fileName string, mapper *mapper.MetricMapper, cacheSize int) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
Expand All @@ -103,7 +103,7 @@ func watchConfig(fileName string, mapper *mapper.MetricMapper) {
select {
case ev := <-watcher.Event:
log.Infof("Config file changed (%s), attempting reload", ev)
err = mapper.InitFromFile(fileName)
err = mapper.InitFromFile(fileName, cacheSize)
if err != nil {
log.Errorln("Error reloading config:", err)
configLoads.WithLabelValues("failure").Inc()
Expand Down Expand Up @@ -144,6 +144,8 @@ func main() {
mappingConfig = kingpin.Flag("statsd.mapping-config", "Metric mapping configuration file name.").String()
readBuffer = kingpin.Flag("statsd.read-buffer", "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.").Int()
dumpFSMPath = kingpin.Flag("debug.dump-fsm", "The path to dump internal FSM generated for glob matching as Dot file.").Default("").String()

cacheSize = kingpin.Flag("statsd.cache-size", "Maximum size of your metric mapping cache. Relies on least recently used replacement policy if max size is reached.").Default("1000").Int()
)

log.AddFlags(kingpin.CommandLine)
Expand Down Expand Up @@ -197,7 +199,7 @@ func main() {

mapper := &mapper.MetricMapper{MappingsCount: mappingsCount}
if *mappingConfig != "" {
err := mapper.InitFromFile(*mappingConfig)
err := mapper.InitFromFile(*mappingConfig, *cacheSize)
if err != nil {
log.Fatal("Error loading config:", err)
}
Expand All @@ -207,7 +209,9 @@ func main() {
log.Fatal("Error dumping FSM:", err)
}
}
go watchConfig(*mappingConfig, mapper)
go watchConfig(*mappingConfig, mapper, *cacheSize)
} else {
mapper.InitCache(*cacheSize)
}
exporter := NewExporter(mapper)
exporter.Listen(events)
Expand Down
57 changes: 48 additions & 9 deletions pkg/mapper/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"sync"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"github.com/prometheus/statsd_exporter/pkg/mapper/fsm"
yaml "gopkg.in/yaml.v2"
"time"
Expand Down Expand Up @@ -49,7 +50,9 @@ type MetricMapper struct {
FSM *fsm.FSM
doFSM bool
doRegex bool
mutex sync.Mutex
useCache bool
cache *MetricMapperCache
mutex sync.RWMutex

MappingsCount prometheus.Gauge
}
Expand Down Expand Up @@ -83,7 +86,7 @@ var defaultQuantiles = []metricObjective{
{Quantile: 0.99, Error: 0.001},
}

func (m *MetricMapper) InitFromYAMLString(fileContents string) error {
func (m *MetricMapper) InitFromYAMLString(fileContents string, cacheSize int) error {
var n MetricMapper

if err := yaml.Unmarshal([]byte(fileContents), &n); err != nil {
Expand Down Expand Up @@ -189,6 +192,8 @@ func (m *MetricMapper) InitFromYAMLString(fileContents string) error {

m.Defaults = n.Defaults
m.Mappings = n.Mappings
m.InitCache(cacheSize)

if n.doFSM {
var mappings []string
for _, mapping := range n.Mappings {
Expand All @@ -206,19 +211,42 @@ func (m *MetricMapper) InitFromYAMLString(fileContents string) error {
if m.MappingsCount != nil {
m.MappingsCount.Set(float64(len(n.Mappings)))
}

return nil
}

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

return m.InitFromYAMLString(string(mappingStr), cacheSize)
}

func (m *MetricMapper) InitCache(cacheSize int) {
m.useCache = true
if cacheSize == 0 {
m.useCache = false
} else {
cache, err := NewMetricMapperCache(cacheSize)
if err != nil {
log.Warnf("Unable to setup metric cache. Performance may be negatively impacted. Caused by: %s", err)
m.useCache = false
}

m.cache = cache
}
}

func (m *MetricMapper) GetMapping(statsdMetric string, statsdMetricType MetricType) (*MetricMapping, prometheus.Labels, bool) {
m.mutex.RLock()
defer m.mutex.RUnlock()
if m.useCache {
result, cached := m.cache.Get(statsdMetric)
if cached {
return result.Mapping, result.Labels, result.Matched
}
}
// glob matching
if m.doFSM {
finalState, captures := m.FSM.GetMapping(statsdMetric, string(statsdMetricType))
Expand All @@ -230,17 +258,22 @@ func (m *MetricMapper) GetMapping(statsdMetric string, statsdMetricType MetricTy
for index, formatter := range result.labelFormatters {
labels[result.labelKeys[index]] = formatter.Format(captures)
}

if m.useCache {
m.cache.AddMatch(statsdMetric, result, labels)
}

return result, labels, true
} else if !m.doRegex {
// if there's no regex match type, return immediately
if m.useCache {
m.cache.AddMiss(statsdMetric)
}
return nil, nil, false
}
}

// regex matching
m.mutex.Lock()
defer m.mutex.Unlock()

for _, mapping := range m.Mappings {
// if a rule don't have regex matching type, the regex field is unset
if mapping.regex == nil {
Expand Down Expand Up @@ -268,8 +301,14 @@ func (m *MetricMapper) GetMapping(statsdMetric string, statsdMetricType MetricTy
labels[label] = string(value)
}

if m.useCache {
m.cache.AddMatch(statsdMetric, &mapping, labels)
}

return &mapping, labels, true
}

if m.useCache {
m.cache.AddMiss(statsdMetric)
}
return nil, nil, false
}
Loading

0 comments on commit ae2681e

Please sign in to comment.