Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to uint64 hash for identifier #886

Merged
merged 4 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 52 additions & 37 deletions exporter/collector/internal/datapointstorage/datapointcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
package datapointstorage

import (
"fmt"
"hash"
"hash/fnv"
"sort"
"strings"
"sync"
"time"

Expand All @@ -30,10 +30,10 @@ import (
const gcInterval = 20 * time.Minute

type Cache struct {
numberCache map[string]usedNumberPoint
summaryCache map[string]usedSummaryPoint
histogramCache map[string]usedHistogramPoint
exponentialHistogramCache map[string]usedExponentialHistogramPoint
numberCache map[uint64]usedNumberPoint
summaryCache map[uint64]usedSummaryPoint
histogramCache map[uint64]usedHistogramPoint
exponentialHistogramCache map[uint64]usedExponentialHistogramPoint
numberLock sync.RWMutex
summaryLock sync.RWMutex
histogramLock sync.RWMutex
Expand Down Expand Up @@ -63,10 +63,10 @@ type usedExponentialHistogramPoint struct {
// NewCache instantiates a cache and starts background processes.
func NewCache(shutdown <-chan struct{}) *Cache {
c := &Cache{
numberCache: make(map[string]usedNumberPoint),
summaryCache: make(map[string]usedSummaryPoint),
histogramCache: make(map[string]usedHistogramPoint),
exponentialHistogramCache: make(map[string]usedExponentialHistogramPoint),
numberCache: make(map[uint64]usedNumberPoint),
summaryCache: make(map[uint64]usedSummaryPoint),
histogramCache: make(map[uint64]usedHistogramPoint),
exponentialHistogramCache: make(map[uint64]usedExponentialHistogramPoint),
}
go func() {
ticker := time.NewTicker(gcInterval)
Expand All @@ -79,7 +79,7 @@ func NewCache(shutdown <-chan struct{}) *Cache {

// GetNumberDataPoint retrieves the point associated with the identifier, and whether
// or not it was found.
func (c *Cache) GetNumberDataPoint(identifier string) (pmetric.NumberDataPoint, bool) {
func (c *Cache) GetNumberDataPoint(identifier uint64) (pmetric.NumberDataPoint, bool) {
c.numberLock.RLock()
defer c.numberLock.RUnlock()
point, found := c.numberCache[identifier]
Expand All @@ -90,15 +90,15 @@ func (c *Cache) GetNumberDataPoint(identifier string) (pmetric.NumberDataPoint,
}

// SetNumberDataPoint assigns the point to the identifier in the cache.
func (c *Cache) SetNumberDataPoint(identifier string, point pmetric.NumberDataPoint) {
func (c *Cache) SetNumberDataPoint(identifier uint64, point pmetric.NumberDataPoint) {
c.numberLock.Lock()
defer c.numberLock.Unlock()
c.numberCache[identifier] = usedNumberPoint{point, atomic.NewBool(true)}
}

// GetSummaryDataPoint retrieves the point associated with the identifier, and whether
// or not it was found.
func (c *Cache) GetSummaryDataPoint(identifier string) (pmetric.SummaryDataPoint, bool) {
func (c *Cache) GetSummaryDataPoint(identifier uint64) (pmetric.SummaryDataPoint, bool) {
c.summaryLock.RLock()
defer c.summaryLock.RUnlock()
point, found := c.summaryCache[identifier]
Expand All @@ -109,15 +109,15 @@ func (c *Cache) GetSummaryDataPoint(identifier string) (pmetric.SummaryDataPoint
}

// SetSummaryDataPoint assigns the point to the identifier in the cache.
func (c *Cache) SetSummaryDataPoint(identifier string, point pmetric.SummaryDataPoint) {
func (c *Cache) SetSummaryDataPoint(identifier uint64, point pmetric.SummaryDataPoint) {
c.summaryLock.Lock()
defer c.summaryLock.Unlock()
c.summaryCache[identifier] = usedSummaryPoint{point, atomic.NewBool(true)}
}

// GetHistogramDataPoint retrieves the point associated with the identifier, and whether
// or not it was found.
func (c *Cache) GetHistogramDataPoint(identifier string) (pmetric.HistogramDataPoint, bool) {
func (c *Cache) GetHistogramDataPoint(identifier uint64) (pmetric.HistogramDataPoint, bool) {
c.histogramLock.RLock()
defer c.histogramLock.RUnlock()
point, found := c.histogramCache[identifier]
Expand All @@ -128,15 +128,15 @@ func (c *Cache) GetHistogramDataPoint(identifier string) (pmetric.HistogramDataP
}

// SetHistogramDataPoint assigns the point to the identifier in the cache.
func (c *Cache) SetHistogramDataPoint(identifier string, point pmetric.HistogramDataPoint) {
func (c *Cache) SetHistogramDataPoint(identifier uint64, point pmetric.HistogramDataPoint) {
c.histogramLock.Lock()
defer c.histogramLock.Unlock()
c.histogramCache[identifier] = usedHistogramPoint{point, atomic.NewBool(true)}
}

// GetExponentialHistogramDataPoint retrieves the point associated with the identifier, and whether
// or not it was found.
func (c *Cache) GetExponentialHistogramDataPoint(identifier string) (pmetric.ExponentialHistogramDataPoint, bool) {
func (c *Cache) GetExponentialHistogramDataPoint(identifier uint64) (pmetric.ExponentialHistogramDataPoint, bool) {
c.exponentialHistogramLock.RLock()
defer c.exponentialHistogramLock.RUnlock()
point, found := c.exponentialHistogramCache[identifier]
Expand All @@ -147,7 +147,7 @@ func (c *Cache) GetExponentialHistogramDataPoint(identifier string) (pmetric.Exp
}

// SetExponentialHistogramDataPoint assigns the point to the identifier in the cache.
func (c *Cache) SetExponentialHistogramDataPoint(identifier string, point pmetric.ExponentialHistogramDataPoint) {
func (c *Cache) SetExponentialHistogramDataPoint(identifier uint64, point pmetric.ExponentialHistogramDataPoint) {
c.exponentialHistogramLock.Lock()
defer c.exponentialHistogramLock.Unlock()
c.exponentialHistogramCache[identifier] = usedExponentialHistogramPoint{point, atomic.NewBool(true)}
Expand Down Expand Up @@ -211,28 +211,43 @@ func (c *Cache) gc(shutdown <-chan struct{}, tickerCh <-chan time.Time) bool {
return true
}

// Identifier returns the unique string identifier for a metric.
func Identifier(resource *monitoredrespb.MonitoredResource, extraLabels map[string]string, metric pmetric.Metric, attributes pcommon.Map) string {
var b strings.Builder

// Resource identifiers
if resource != nil {
fmt.Fprintf(&b, "%v", resource.GetLabels())
}

// Instrumentation library labels and additional resource labels
fmt.Fprintf(&b, " - %v", extraLabels)
// Use the same constants as Prometheus uses for hashing:
// https://github.com/prometheus/prometheus/blob/282fb1632ad62a82401a230f486538a72384faf0/model/labels/labels_common.go#L32
var (
dashpole marked this conversation as resolved.
Show resolved Hide resolved
itemSep = []byte{'\xfe'} // Used between identifiers
kvSep = []byte{'\xff'} // Used between map keys and values
)

// Metric identifiers
fmt.Fprintf(&b, " - %s -", metric.Name())
attrsIds := make([]string, 0, attributes.Len())
// Identifier returns the unique string identifier for a metric.
func Identifier(resource *monitoredrespb.MonitoredResource, extraLabels map[string]string, metric pmetric.Metric, attributes pcommon.Map) uint64 {
h := fnv.New64()
h.Write([]byte(resource.GetType()))
h.Write(itemSep)
h.Write([]byte(metric.Name()))
h.Write(itemSep)
attrs := make(map[string]string)
attributes.Range(func(k string, v pcommon.Value) bool {
attrsIds = append(attrsIds, k+"="+v.AsString())
attrs[k] = v.AsString()
dashpole marked this conversation as resolved.
Show resolved Hide resolved
return true
})
if len(attrsIds) > 0 {
sort.Strings(attrsIds)
fmt.Fprint(&b, " "+strings.Join(attrsIds, " "))
hashOfMap(h, extraLabels)
h.Write(itemSep)
hashOfMap(h, attrs)
h.Write(itemSep)
hashOfMap(h, resource.GetLabels())
return h.Sum64()
}

func hashOfMap(h hash.Hash64, m map[string]string) {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, key := range keys {
h.Write([]byte(key))
h.Write(kvSep)
h.Write([]byte(m[key]))
h.Write(kvSep)
}
return b.String()
}
Loading
Loading