Remove vector cleanup from registry

This was attempting to clean up any vectors that no longer have metrics
associated with them.  Unfortunately this isn't really possible because
the prometheus client registry allows the second registration of the
same metric, and then throws an error when gathering the metrics.

Another options would be to unregister the metric with the client
library, but that's not implemented for unchecked collectors.

Unfortunately this means that if we have a lot of metrics with differing
label sets appearing and disappearing, that we'll leak some amount of
memory for vectors that are never used again, but this is the way the
old metric tracking code worked also.

Signed-off-by: Clayton O'Neill <claytono@github.com>
This commit is contained in:
Clayton O'Neill 2019-05-24 08:32:17 -04:00
parent 680eb0e826
commit a241eb0b69
No known key found for this signature in database
GPG key ID: 5017D45C788B5274

View file

@ -78,16 +78,15 @@ type registry struct {
// The below value and label variables are allocated in the registry struct // The below value and label variables are allocated in the registry struct
// so that we don't have to allocate them every time have to compute a label // so that we don't have to allocate them every time have to compute a label
// hash. // hash.
valueBuf, nameBuf bytes.Buffer valueBuf, nameBuf bytes.Buffer
valueHasher, nameHasher hash.Hash64 hasher hash.Hash64
} }
func newRegistry(mapper *mapper.MetricMapper) *registry { func newRegistry(mapper *mapper.MetricMapper) *registry {
return &registry{ return &registry{
metrics: make(map[string]metric), metrics: make(map[string]metric),
mapper: mapper, mapper: mapper,
valueHasher: fnv.New64a(), hasher: fnv.New64a(),
nameHasher: fnv.New64a(),
} }
} }
@ -361,7 +360,7 @@ func (r *registry) getSummary(metricName string, labels prometheus.Labels, help
func (r *registry) removeStaleMetrics() { func (r *registry) removeStaleMetrics() {
now := clock.Now() now := clock.Now()
// delete timeseries with expired ttl // delete timeseries with expired ttl
for metricName, metric := range r.metrics { for _, metric := range r.metrics {
for hash, rm := range metric.metrics { for hash, rm := range metric.metrics {
if rm.ttl == 0 { if rm.ttl == 0 {
continue continue
@ -371,21 +370,13 @@ func (r *registry) removeStaleMetrics() {
metric.vectors[rm.vecKey].refCount-- metric.vectors[rm.vecKey].refCount--
delete(metric.metrics, hash) delete(metric.metrics, hash)
} }
// If no individual instances exist, then delete the entire vector
if metric.vectors[rm.vecKey].refCount == 0 {
delete(r.metrics, metricName)
}
} }
} }
} }
// Calculates a hash of both the label names and the label names + label values. // Calculates a hash of both the label names and the label names and values.
// Note that this function goes to silly lengths to avoid allocating memory.
// This is in the fast path for every metric ingested and allocating and gc'ing
// temporary memory is expensive.
func (r *registry) hashLabels(labels prometheus.Labels) (labelHash, []string) { func (r *registry) hashLabels(labels prometheus.Labels) (labelHash, []string) {
r.nameHasher.Reset() r.hasher.Reset()
r.valueHasher.Reset()
r.nameBuf.Reset() r.nameBuf.Reset()
r.valueBuf.Reset() r.valueBuf.Reset()
labelNames := make([]string, 0, len(labels)) labelNames := make([]string, 0, len(labels))
@ -404,11 +395,13 @@ func (r *registry) hashLabels(labels prometheus.Labels) (labelHash, []string) {
r.nameBuf.WriteByte(model.SeparatorByte) r.nameBuf.WriteByte(model.SeparatorByte)
} }
r.nameHasher.Write(r.nameBuf.Bytes()) lh := labelHash{}
r.valueHasher.Write(r.nameBuf.Bytes()) r.hasher.Write(r.nameBuf.Bytes())
r.valueHasher.Write(r.valueBuf.Bytes()) lh.names = nameHash(r.hasher.Sum64())
return labelHash{ // Now add the values to the names we've already hashed.
names: nameHash(r.nameHasher.Sum64()), r.hasher.Write(r.valueBuf.Bytes())
values: valueHash(r.valueHasher.Sum64())}, labelNames lh.values = valueHash(r.hasher.Sum64())
return lh, labelNames
} }