Skip to content

Commit

Permalink
Merge pull request #73 from AndrewChubatiuk/merge-histograms
Browse files Browse the repository at this point in the history
added function for histograms merge
  • Loading branch information
AndrewChubatiuk committed May 20, 2024
2 parents b6cce23 + e40cfe3 commit a52bdc6
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
32 changes: 27 additions & 5 deletions histogram.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var bucketMultiplier = math.Pow(10, 1.0/bucketsPerDecimal)
// Zero histogram is usable.
type Histogram struct {
// Mu gurantees synchronous update for all the counters and sum.
mu sync.Mutex
mu sync.RWMutex

decimalBuckets [decimalBucketsCount]*[bucketsPerDecimal]uint64

Expand Down Expand Up @@ -109,14 +109,36 @@ func (h *Histogram) Update(v float64) {
h.mu.Unlock()
}

// Merge merges histograms
func (h *Histogram) Merge(b *Histogram) {
h.mu.Lock()
defer h.mu.Unlock()

b.mu.RLock()
defer b.mu.RUnlock()

h.lower += b.lower
h.upper += b.upper
h.sum += b.sum

for i, db := range b.decimalBuckets {
if db == nil {
continue
}
for j := range db {
h.decimalBuckets[i][j] = db[j]
}
}
}

// VisitNonZeroBuckets calls f for all buckets with non-zero counters.
//
// vmrange contains "<start>...<end>" string with bucket bounds. The lower bound
// isn't included in the bucket, while the upper bound is included.
// This is required to be compatible with Prometheus-style histogram buckets
// with `le` (less or equal) labels.
func (h *Histogram) VisitNonZeroBuckets(f func(vmrange string, count uint64)) {
h.mu.Lock()
h.mu.RLock()
if h.lower > 0 {
f(lowerBucketRange, h.lower)
}
Expand All @@ -135,7 +157,7 @@ func (h *Histogram) VisitNonZeroBuckets(f func(vmrange string, count uint64)) {
if h.upper > 0 {
f(upperBucketRange, h.upper)
}
h.mu.Unlock()
h.mu.RUnlock()
}

// NewHistogram creates and returns new histogram with the given name.
Expand Down Expand Up @@ -223,9 +245,9 @@ func (h *Histogram) marshalTo(prefix string, w io.Writer) {
}

func (h *Histogram) getSum() float64 {
h.mu.Lock()
h.mu.RLock()
sum := h.sum
h.mu.Unlock()
h.mu.RUnlock()
return sum
}

Expand Down
29 changes: 29 additions & 0 deletions histogram_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,35 @@ import (
"time"
)

func TestHistogramMerge(t *testing.T) {
name := `TestHistogramMerge`
h := NewHistogram(name)
// Write data to histogram
for i := 98; i < 218; i++ {
h.Update(float64(i))
}

b := NewHistogram("test")
for i := 98; i < 218; i++ {
h.Update(float64(i))
}

h.Merge(b)

// Make sure the histogram prints <prefix>_bucket on marshalTo call
testMarshalTo(t, h, "prefix", `prefix_bucket{vmrange="8.799e+01...1.000e+02"} 6
prefix_bucket{vmrange="1.000e+02...1.136e+02"} 26
prefix_bucket{vmrange="1.136e+02...1.292e+02"} 32
prefix_bucket{vmrange="1.292e+02...1.468e+02"} 34
prefix_bucket{vmrange="1.468e+02...1.668e+02"} 40
prefix_bucket{vmrange="1.668e+02...1.896e+02"} 46
prefix_bucket{vmrange="1.896e+02...2.154e+02"} 52
prefix_bucket{vmrange="2.154e+02...2.448e+02"} 4
prefix_sum 37800
prefix_count 240
`)
}

func TestGetVMRange(t *testing.T) {
f := func(bucketIdx int, vmrangeExpected string) {
t.Helper()
Expand Down

0 comments on commit a52bdc6

Please sign in to comment.