Merge pull request #836 from prometheus/shard

Add 'hashmod' relabel action.
This commit is contained in:
Brian Brazil 2015-06-24 21:40:10 +01:00
commit 52859b8033
6 changed files with 73 additions and 7 deletions

View file

@ -455,9 +455,11 @@ const (
// Performs a regex replacement. // Performs a regex replacement.
RelabelReplace RelabelAction = "replace" RelabelReplace RelabelAction = "replace"
// Drops targets for which the input does not match the regex. // Drops targets for which the input does not match the regex.
RelabelKeep = "keep" RelabelKeep RelabelAction = "keep"
// Drops targets for which the input does match the regex. // Drops targets for which the input does match the regex.
RelabelDrop = "drop" RelabelDrop RelabelAction = "drop"
// Sets a label to the modulus of a hash of labels.
RelabelHashMod RelabelAction = "hashmod"
) )
// UnmarshalYAML implements the yaml.Unmarshaler interface. // UnmarshalYAML implements the yaml.Unmarshaler interface.
@ -467,7 +469,7 @@ func (a *RelabelAction) UnmarshalYAML(unmarshal func(interface{}) error) error {
return err return err
} }
switch act := RelabelAction(strings.ToLower(s)); act { switch act := RelabelAction(strings.ToLower(s)); act {
case RelabelReplace, RelabelKeep, RelabelDrop: case RelabelReplace, RelabelKeep, RelabelDrop, RelabelHashMod:
*a = act *a = act
return nil return nil
} }
@ -482,7 +484,9 @@ type RelabelConfig struct {
// Separator is the string between concatenated values from the source labels. // Separator is the string between concatenated values from the source labels.
Separator string `yaml:"separator,omitempty"` Separator string `yaml:"separator,omitempty"`
// Regex against which the concatenation is matched. // Regex against which the concatenation is matched.
Regex *Regexp `yaml:"regex"` Regex *Regexp `yaml:"regex",omitempty`
// Modulus to take of the hash of concatenated values from the source labels.
Modulus uint64 `yaml:"modulus,omitempty"`
// The label to which the resulting string is written in a replacement. // The label to which the resulting string is written in a replacement.
TargetLabel clientmodel.LabelName `yaml:"target_label,omitempty"` TargetLabel clientmodel.LabelName `yaml:"target_label,omitempty"`
// Replacement is the regex replacement pattern to be used. // Replacement is the regex replacement pattern to be used.
@ -501,9 +505,12 @@ func (c *RelabelConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal((*plain)(c)); err != nil { if err := unmarshal((*plain)(c)); err != nil {
return err return err
} }
if c.Regex == nil { if c.Regex == nil && c.Action != RelabelHashMod {
return fmt.Errorf("relabel configuration requires a regular expression") return fmt.Errorf("relabel configuration requires a regular expression")
} }
if c.Modulus == 0 && c.Action == RelabelHashMod {
return fmt.Errorf("relabel configuration for hashmod requires non-zero modulus")
}
return checkOverflow(c.XXX, "relabel_config") return checkOverflow(c.XXX, "relabel_config")
} }
@ -527,8 +534,11 @@ func (re *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error {
} }
// MarshalYAML implements the yaml.Marshaler interface. // MarshalYAML implements the yaml.Marshaler interface.
func (re Regexp) MarshalYAML() (interface{}, error) { func (re *Regexp) MarshalYAML() (interface{}, error) {
return re.String(), nil if re != nil {
return re.String(), nil
}
return nil, nil
} }
// Duration encapsulates a time.Duration and makes it YAML marshallable. // Duration encapsulates a time.Duration and makes it YAML marshallable.

View file

@ -114,6 +114,19 @@ var expectedConf = &Config{
Separator: ";", Separator: ";",
Action: RelabelDrop, Action: RelabelDrop,
}, },
{
SourceLabels: clientmodel.LabelNames{"__address__"},
TargetLabel: "__hash",
Modulus: 8,
Separator: ";",
Action: RelabelHashMod,
},
{
SourceLabels: clientmodel.LabelNames{"__hash"},
Regex: &Regexp{*regexp.MustCompile("^1$")},
Separator: ";",
Action: RelabelKeep,
},
}, },
MetricRelabelConfigs: []*RelabelConfig{ MetricRelabelConfigs: []*RelabelConfig{
{ {
@ -194,6 +207,9 @@ var expectedErrors = []struct {
}, { }, {
filename: "regex_missing.bad.yml", filename: "regex_missing.bad.yml",
errMsg: "relabel configuration requires a regular expression", errMsg: "relabel configuration requires a regular expression",
}, {
filename: "modulus_missing.bad.yml",
errMsg: "relabel configuration for hashmod requires non-zero modulus",
}, { }, {
filename: "rules.bad.yml", filename: "rules.bad.yml",
errMsg: "invalid rule file path", errMsg: "invalid rule file path",

View file

@ -71,6 +71,13 @@ scrape_configs:
- source_labels: [job] - source_labels: [job]
regex: (.*)some-[regex]$ regex: (.*)some-[regex]$
action: drop action: drop
- source_labels: [__address__]
modulus: 8
target_label: __hash
action: hashmod
- source_labels: [__hash]
regex: ^1$
action: keep
metric_relabel_configs: metric_relabel_configs:
- source_labels: [__name__] - source_labels: [__name__]

View file

@ -0,0 +1,5 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- regex: abcdef
action: hashmod

View file

@ -2,6 +2,7 @@ package retrieval
import ( import (
"fmt" "fmt"
"hash/fnv"
"strings" "strings"
clientmodel "github.com/prometheus/client_golang/model" clientmodel "github.com/prometheus/client_golang/model"
@ -56,6 +57,11 @@ func relabel(labels clientmodel.LabelSet, cfg *config.RelabelConfig) (clientmode
} else { } else {
labels[cfg.TargetLabel] = clientmodel.LabelValue(res) labels[cfg.TargetLabel] = clientmodel.LabelValue(res)
} }
case config.RelabelHashMod:
hasher := fnv.New64a()
hasher.Write([]byte(val))
mod := hasher.Sum64() % cfg.Modulus
labels[cfg.TargetLabel] = clientmodel.LabelValue(fmt.Sprintf("%d", mod))
default: default:
panic(fmt.Errorf("retrieval.relabel: unknown relabel action type %q", cfg.Action)) panic(fmt.Errorf("retrieval.relabel: unknown relabel action type %q", cfg.Action))
} }

View file

@ -151,6 +151,28 @@ func TestRelabel(t *testing.T) {
"a": "boo", "a": "boo",
}, },
}, },
{
input: clientmodel.LabelSet{
"a": "foo",
"b": "bar",
"c": "baz",
},
relabel: []*config.RelabelConfig{
{
SourceLabels: clientmodel.LabelNames{"c"},
TargetLabel: clientmodel.LabelName("d"),
Separator: ";",
Action: config.RelabelHashMod,
Modulus: 1000,
},
},
output: clientmodel.LabelSet{
"a": "foo",
"b": "bar",
"c": "baz",
"d": "58",
},
},
} }
for i, test := range tests { for i, test := range tests {