Skip to content

Commit 5e8ac3c

Browse files
author
beorn7
committed
Add a concurrent end-to-end test for observe-register-gather
This is an attempt to expose istio/istio#8906 . The failure to do so makes me believe the error is either already fixed in current client_golang, or something weird I haven't spotted yet is happening in the istio code. Signed-off-by: beorn7 <[email protected]>
1 parent e1fb14a commit 5e8ac3c

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

prometheus/registry_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ package prometheus_test
2121

2222
import (
2323
"bytes"
24+
"math/rand"
2425
"net/http"
2526
"net/http/httptest"
27+
"sync"
2628
"testing"
29+
"time"
2730

2831
dto "github.com/prometheus/client_model/go"
2932

@@ -772,3 +775,99 @@ func TestAlreadyRegistered(t *testing.T) {
772775
t.Error("unexpected error:", err)
773776
}
774777
}
778+
779+
// TestHistogramVecRegisterGatherConcurrency is an end-to-end test that
780+
// concurrently calls Observe on random elements of a HistogramVec while the
781+
// same HistogramVec is registered concurrently and the Gather method of the
782+
// registry is called concurrently.
783+
func TestHistogramVecRegisterGatherConcurrency(t *testing.T) {
784+
var (
785+
reg = prometheus.NewPedanticRegistry()
786+
hv = prometheus.NewHistogramVec(
787+
prometheus.HistogramOpts{
788+
Name: "test_histogram",
789+
Help: "This helps testing.",
790+
ConstLabels: prometheus.Labels{"foo": "bar"},
791+
},
792+
[]string{"one", "two", "three"},
793+
)
794+
labelValues = []string{"a", "b", "c", "alpha", "beta", "gamma", "aleph", "beth", "gimel"}
795+
quit = make(chan struct{})
796+
wg sync.WaitGroup
797+
)
798+
799+
observe := func() {
800+
defer wg.Done()
801+
for {
802+
select {
803+
case <-quit:
804+
return
805+
default:
806+
obs := rand.NormFloat64()*.1 + .2
807+
hv.WithLabelValues(
808+
labelValues[rand.Intn(len(labelValues))],
809+
labelValues[rand.Intn(len(labelValues))],
810+
labelValues[rand.Intn(len(labelValues))],
811+
).Observe(obs)
812+
}
813+
}
814+
}
815+
816+
register := func() {
817+
defer wg.Done()
818+
for {
819+
select {
820+
case <-quit:
821+
return
822+
default:
823+
if err := reg.Register(hv); err != nil {
824+
if _, ok := err.(prometheus.AlreadyRegisteredError); !ok {
825+
t.Error("Registering failed:", err)
826+
}
827+
}
828+
time.Sleep(7 * time.Millisecond)
829+
}
830+
}
831+
}
832+
833+
gather := func() {
834+
defer wg.Done()
835+
for {
836+
select {
837+
case <-quit:
838+
return
839+
default:
840+
if g, err := reg.Gather(); err != nil {
841+
t.Error("Gathering failed:", err)
842+
} else {
843+
if len(g) == 0 {
844+
continue
845+
}
846+
if len(g) != 1 {
847+
t.Error("Gathered unexpected number of metric families:", len(g))
848+
}
849+
if len(g[0].Metric[0].Label) != 4 {
850+
t.Error("Gathered unexpected number of label pairs:", len(g[0].Metric[0].Label))
851+
}
852+
}
853+
time.Sleep(4 * time.Millisecond)
854+
}
855+
}
856+
}
857+
858+
wg.Add(10)
859+
go observe()
860+
go observe()
861+
go register()
862+
go observe()
863+
go gather()
864+
go observe()
865+
go register()
866+
go observe()
867+
go gather()
868+
go observe()
869+
870+
time.Sleep(time.Second)
871+
close(quit)
872+
wg.Wait()
873+
}

0 commit comments

Comments
 (0)