Skip to content

Commit

Permalink
Metrics concurrency bug (#318)
Browse files Browse the repository at this point in the history
  • Loading branch information
CoreyCook8 authored Aug 16, 2023
1 parent 5a10d90 commit 36b323d
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
5 changes: 4 additions & 1 deletion metrics/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ func AddTags(ctx context.Context, tags ...Tag) context.Context {
if !ok || container == nil {
container = &tagsContainer{}
}
newTags := make(Tags, len(container.Tags)+len(tags))
copy(newTags, container.Tags)
copy(newTags[len(container.Tags):], tags)
return context.WithValue(ctx, tagsKey, &tagsContainer{
Tags: append(container.Tags, tags...),
Tags: newTags,
})
}

Expand Down
44 changes: 44 additions & 0 deletions metrics/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
package metrics_test

import (
"context"
"os"
"os/exec"
"reflect"
"strings"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -349,3 +351,45 @@ func registryContains(registry metrics.Registry, name string, tags metrics.Tags)
}))
return contains
}

func TestChildRegistry_ConcurrentUpdatesToTagsAreNotCorrupted(t *testing.T) {
ctx := metrics.WithRegistry(context.Background(), metrics.NewRootMetricsRegistry())
ctx = metrics.AddTags(ctx, metrics.MustNewTag("foo", "bar"))
ctx = metrics.AddTags(ctx, metrics.MustNewTag("faz", "baz"))
ctx = metrics.AddTags(ctx, metrics.MustNewTag("whoop", "shoop"))

prefix1 := "foo_bar"
prefix2 := "whoop_shoop"

var goRoutineFinished sync.WaitGroup
goRoutineFinished.Add(2)
go func() {
for i := 0; i < 5000; i++ {
metrics.FromContext(ctx).Gauge(prefix1, metrics.MustNewTag("name", prefix1)).Update(1)
}
goRoutineFinished.Done()
}()
go func() {
for i := 0; i < 5000; i++ {
metrics.FromContext(ctx).Gauge(prefix2, metrics.MustNewTag("name", prefix2)).Update(1)
}
goRoutineFinished.Done()
}()
goRoutineFinished.Wait()
metrics.FromContext(ctx).Each(func(name string, tags metrics.Tags, _ metrics.MetricVal) {
if strings.HasPrefix(name, prefix1) {
for _, tag := range tags {
if tag.Key() == "name" && tag.Value() == prefix2 {
assert.Fail(t, prefix1+"should not have the tag name="+prefix2, tag)
}
}
}
if strings.HasPrefix(name, prefix2) {
for _, tag := range tags {
if tag.Key() == "name" && tag.Value() == prefix1 {
assert.Fail(t, prefix2+"should not have the tag name="+prefix1, tag)
}
}
}
})
}

0 comments on commit 36b323d

Please sign in to comment.