Merge pull request #115 from bakins/bakins/match-actions

Add drop action for matches
This commit is contained in:
Matthias Rampke 2018-01-08 18:32:44 +00:00 committed by GitHub
commit 25c9946cf3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 177 additions and 1 deletions

View file

@ -204,6 +204,27 @@ mappings:
job: "${1}_server_other" job: "${1}_server_other"
``` ```
You may also drop metrics by specifying a "drop" action on a match. For example:
```yaml
mappings:
# This metric would match as normal.
- match: test.timing.*.*.*
name: "my_timer"
labels:
provider: "$2"
outcome: "$3"
job: "${1}_server"
# Any metric not matched will be dropped because "." matches all metrics.
- match: .
match_type: regex
action: drop
name: "dropped"
```
You can drop any metric using the normal match syntax.
The default action is "map" which does the normal metrics mapping.
## Using Docker ## Using Docker
You can deploy this exporter using the [prom/statsd-exporter](https://registry.hub.docker.com/u/prom/statsd-exporter/) Docker image. You can deploy this exporter using the [prom/statsd-exporter](https://registry.hub.docker.com/u/prom/statsd-exporter/) Docker image.

42
action.go Normal file
View file

@ -0,0 +1,42 @@
// Copyright 2018 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 main
import "fmt"
type actionType string
const (
actionTypeMap actionType = "map"
actionTypeDrop actionType = "drop"
actionTypeDefault actionType = ""
)
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
default:
return fmt.Errorf("invalid action type %q", v)
}
return nil
}

View file

@ -252,6 +252,11 @@ func (b *Exporter) Listen(e <-chan Events) {
if mapping == nil { if mapping == nil {
mapping = &metricMapping{} mapping = &metricMapping{}
} }
if mapping.Action == actionTypeDrop {
continue
}
if mapping.HelpText == "" { if mapping.HelpText == "" {
help = defaultHelp help = defaultHelp
} else { } else {

View file

@ -54,6 +54,7 @@ type metricMapping struct {
Buckets []float64 `yaml:"buckets"` Buckets []float64 `yaml:"buckets"`
MatchType matchType `yaml:"match_type"` MatchType matchType `yaml:"match_type"`
HelpText string `yaml:"help"` HelpText string `yaml:"help"`
Action actionType `yaml:"action"`
} }
func (m *metricMapper) initFromYAMLString(fileContents string) error { func (m *metricMapper) initFromYAMLString(fileContents string) error {
@ -93,6 +94,10 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
currentMapping.MatchType = n.Defaults.MatchType currentMapping.MatchType = n.Defaults.MatchType
} }
if currentMapping.Action == "" {
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)

View file

@ -360,6 +360,39 @@ mappings:
}, },
}, },
}, },
// Config that drops all.
{
config: `mappings:
- match: .
match_type: regex
name: "drop"
action: drop`,
mappings: mappings{
"test.a": {},
"abc": {},
},
},
// Config that has a catch-all to drop all.
{
config: `mappings:
- match: web.*
name: "web"
labels:
site: "$1"
- match: .
match_type: regex
name: "drop"
action: drop`,
mappings: mappings{
"test.a": {},
"web.localhost": {
name: "web",
labels: map[string]string{
"site": "localhost",
},
},
},
},
} }
mapper := metricMapper{} mapper := metricMapper{}
@ -374,7 +407,7 @@ mappings:
for metric, mapping := range scenario.mappings { for metric, mapping := range scenario.mappings {
m, labels, present := mapper.getMapping(metric) m, labels, present := mapper.getMapping(metric)
if present && 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)
} }
if mapping.notPresent && present { if mapping.notPresent && present {
@ -392,3 +425,73 @@ mappings:
} }
} }
} }
func TestAction(t *testing.T) {
scenarios := []struct {
config string
configBad bool
expectedAction actionType
}{
{
// no action set
config: `---
mappings:
- match: test.*.*
name: "foo"
`,
configBad: false,
expectedAction: actionTypeMap,
},
{
// map action set
config: `---
mappings:
- match: test.*.*
name: "foo"
action: map
`,
configBad: false,
expectedAction: actionTypeMap,
},
{
// drop action set
config: `---
mappings:
- match: test.*.*
name: "foo"
action: drop
`,
configBad: false,
expectedAction: actionTypeDrop,
},
{
// invalid action set
config: `---
mappings:
- match: test.*.*
name: "foo"
action: xyz
`,
configBad: true,
expectedAction: actionTypeDrop,
},
}
for i, scenario := range scenarios {
mapper := metricMapper{}
err := mapper.initFromYAMLString(scenario.config)
if err != nil && !scenario.configBad {
t.Fatalf("%d. Config load error: %s %s", i, scenario.config, err)
}
if err == nil && scenario.configBad {
t.Fatalf("%d. Expected bad config, but loaded ok: %s", i, scenario.config)
}
if !scenario.configBad {
a := mapper.Mappings[0].Action
if scenario.expectedAction != a {
t.Fatalf("%d: Expected action %v, got %v", i, scenario.expectedAction, a)
}
}
}
}