diff --git a/CHANGELOG.md b/CHANGELOG.md index e081131e63c..61159e50f13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ * [BUGFIX] Query Frontend: If 'LogQueriesLongerThan' is set to < 0, log all queries as described in the docs. #4633 * [BUGFIX] Distributor: update defaultReplicationStrategy to not fail with extend-write when a single instance is unhealthy. #4636 * [BUGFIX] Distributor: Fix race condition on `/series` introduced by #4683. #4716 +* [BUGFIX] Distributor: Fix a memory leak in distributor due to the cluster label. #4739 ## 1.11.0 2021-11-25 diff --git a/pkg/distributor/ha_tracker.go b/pkg/distributor/ha_tracker.go index 9bf38c800bd..dd0f74d9c55 100644 --- a/pkg/distributor/ha_tracker.go +++ b/pkg/distributor/ha_tracker.go @@ -471,7 +471,9 @@ func findHALabels(replicaLabel, clusterLabel string, labels []cortexpb.LabelAdap replica = pair.Value } if pair.Name == clusterLabel { - cluster = pair.Value + // cluster label is unmarshalled into yoloString, which retains original remote write request body in memory. + // Hence, we clone the yoloString to allow the request body to be garbage collected. + cluster = util.StringsClone(pair.Value) } } diff --git a/pkg/util/strings.go b/pkg/util/strings.go index e4c93bc07a8..e7f7c3aceb4 100644 --- a/pkg/util/strings.go +++ b/pkg/util/strings.go @@ -1,5 +1,7 @@ package util +import "unsafe" + // StringsContain returns true if the search value is within the list of input values. func StringsContain(values []string, search string) bool { for _, v := range values { @@ -19,3 +21,11 @@ func StringsMap(values []string) map[string]bool { } return out } + +// StringsClone returns a copy input s +// see: https://github.com/golang/go/blob/master/src/strings/clone.go +func StringsClone(s string) string { + b := make([]byte, len(s)) + copy(b, s) + return *(*string)(unsafe.Pointer(&b)) +}