From caaa3de4ff62a117ba286cd1ec19b54a6c84f393 Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Wed, 12 Aug 2015 15:44:42 +0100 Subject: [PATCH] Make HashMod use MD5 instead of FNV MD5 will will distribute the inputs more uniformly over the output space than FNV; leading to more evenly balanced load when using HashMod. --- retrieval/relabel.go | 18 ++++++++++++++---- retrieval/relabel_test.go | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/retrieval/relabel.go b/retrieval/relabel.go index 0b2785f58..9d06bc0d2 100644 --- a/retrieval/relabel.go +++ b/retrieval/relabel.go @@ -1,8 +1,8 @@ package retrieval import ( + "crypto/md5" "fmt" - "hash/fnv" "strings" clientmodel "github.com/prometheus/client_golang/model" @@ -58,12 +58,22 @@ func relabel(labels clientmodel.LabelSet, cfg *config.RelabelConfig) (clientmode labels[cfg.TargetLabel] = clientmodel.LabelValue(res) } case config.RelabelHashMod: - hasher := fnv.New64a() - hasher.Write([]byte(val)) - mod := hasher.Sum64() % cfg.Modulus + mod := sum64(md5.Sum([]byte(val))) % cfg.Modulus labels[cfg.TargetLabel] = clientmodel.LabelValue(fmt.Sprintf("%d", mod)) default: panic(fmt.Errorf("retrieval.relabel: unknown relabel action type %q", cfg.Action)) } return labels, nil } + +// sum64 sums the md5 hash to an uint64. +func sum64(hash [md5.Size]byte) uint64 { + var s uint64 + + for i, b := range hash { + shift := uint64((md5.Size - i - 1) * 8) + + s |= uint64(b) << shift + } + return s +} diff --git a/retrieval/relabel_test.go b/retrieval/relabel_test.go index 455067c83..a788c03d4 100644 --- a/retrieval/relabel_test.go +++ b/retrieval/relabel_test.go @@ -170,7 +170,7 @@ func TestRelabel(t *testing.T) { "a": "foo", "b": "bar", "c": "baz", - "d": "58", + "d": "976", }, }, }