@@ -5,35 +5,41 @@ import (
55 "time"
66
77 "github.com/prometheus/client_golang/prometheus"
8- "github.com/prometheus/prometheus/model/labels"
98)
109
1110const (
12- vendMetricsInterval = 30 * time .Second
11+ vendMetricsInterval = 30 * time .Second
12+ perLabelsetSeriesLimit = "per_labelset_series_limit"
1313)
1414
15- type labelCounterStruct struct {
16- * sync.RWMutex
17- * labels.Labels
18- inCurrentCycle bool
19- }
20-
2115type seriesCounterStruct struct {
2216 * sync.RWMutex
23- seriesCountMap map [uint64 ]* labelCounterStruct
17+ seriesCountMap map [uint64 ]struct {}
18+ labelsetId string
2419}
2520
2621type userCounterStruct struct {
2722 * sync.RWMutex
2823 userSeriesMap map [string ]* seriesCounterStruct
2924}
3025
26+ type labelsetCounterStruct struct {
27+ * sync.RWMutex
28+ labelsetSeriesMap map [uint64 ]* seriesCounterStruct
29+ }
30+
3131type DiscardedSeriesTracker struct {
3232 * sync.RWMutex
3333 reasonUserMap map [string ]* userCounterStruct
3434 discardedSeriesGauge * prometheus.GaugeVec
3535}
3636
37+ type DiscardedSeriesPerLabelsetTracker struct {
38+ * sync.RWMutex
39+ userLabelsetMap map [string ]* labelsetCounterStruct
40+ discardedSeriesPerLabelsetGauge * prometheus.GaugeVec
41+ }
42+
3743func NewDiscardedSeriesTracker (discardedSeriesGauge * prometheus.GaugeVec ) * DiscardedSeriesTracker {
3844 tracker := & DiscardedSeriesTracker {
3945 RWMutex : & sync.RWMutex {},
@@ -43,8 +49,7 @@ func NewDiscardedSeriesTracker(discardedSeriesGauge *prometheus.GaugeVec) *Disca
4349 return tracker
4450}
4551
46- func (t * DiscardedSeriesTracker ) Track (reason string , user string , labels * labels.Labels ) {
47- series := labels .Hash ()
52+ func (t * DiscardedSeriesTracker ) Track (reason string , user string , series uint64 ) {
4853 t .RLock ()
4954 userCounter , ok := t .reasonUserMap [reason ]
5055 t .RUnlock ()
@@ -70,33 +75,24 @@ func (t *DiscardedSeriesTracker) Track(reason string, user string, labels *label
7075 if ! ok {
7176 seriesCounter = & seriesCounterStruct {
7277 RWMutex : & sync.RWMutex {},
73- seriesCountMap : make (map [uint64 ]* labelCounterStruct ),
78+ seriesCountMap : make (map [uint64 ]struct {} ),
7479 }
7580 userCounter .userSeriesMap [user ] = seriesCounter
7681 }
7782 userCounter .Unlock ()
7883 }
7984
8085 seriesCounter .RLock ()
81- labelCounter , ok : = seriesCounter .seriesCountMap [series ]
86+ _ , ok = seriesCounter .seriesCountMap [series ]
8287 seriesCounter .RUnlock ()
8388 if ! ok {
8489 seriesCounter .Lock ()
85- labelCounter , ok = seriesCounter .seriesCountMap [series ]
90+ _ , ok = seriesCounter .seriesCountMap [series ]
8691 if ! ok {
87- labelCounter = & labelCounterStruct {
88- Labels : labels ,
89- RWMutex : & sync.RWMutex {},
90- inCurrentCycle : true ,
91- }
92- seriesCounter .seriesCountMap [series ] = labelCounter
92+ seriesCounter .seriesCountMap [series ] = struct {}{}
9393 }
9494 seriesCounter .Unlock ()
9595 }
96-
97- labelCounter .Lock ()
98- labelCounter .inCurrentCycle = true
99- labelCounter .Unlock ()
10096}
10197
10298func (t * DiscardedSeriesTracker ) UpdateMetrics () {
@@ -106,31 +102,25 @@ func (t *DiscardedSeriesTracker) UpdateMetrics() {
106102 userCounter .RLock ()
107103 for user , seriesCounter := range userCounter .userSeriesMap {
108104 seriesCounter .Lock ()
109- for hash , labelCounter := range seriesCounter .seriesCountMap {
110- labelCounter .Lock ()
111- if labelCounter .inCurrentCycle {
112- t .discardedSeriesGauge .WithLabelValues (reason , user , labelCounter .String ()).Set (1.0 )
113- labelCounter .inCurrentCycle = false
114- } else {
115- t .discardedSeriesGauge .DeleteLabelValues (reason , user , labelCounter .String ())
116- delete (seriesCounter .seriesCountMap , hash )
117- }
118- labelCounter .Unlock ()
119- }
120- if len (seriesCounter .seriesCountMap ) == 0 {
105+ count := len (seriesCounter .seriesCountMap )
106+ t .discardedSeriesGauge .WithLabelValues (reason , user ).Set (float64 (count ))
107+ clear (seriesCounter .seriesCountMap )
108+ if count == 0 {
121109 usersToDelete = append (usersToDelete , user )
122110 }
123111 seriesCounter .Unlock ()
124112 }
125113 userCounter .RUnlock ()
126- userCounter .Lock ()
127- for _ , user := range usersToDelete {
128- _ , ok := userCounter .userSeriesMap [user ]
129- if ok && userCounter .userSeriesMap [user ].seriesCountMap != nil {
130- delete (userCounter .userSeriesMap , user )
114+ if len (usersToDelete ) > 0 {
115+ userCounter .Lock ()
116+ for _ , user := range usersToDelete {
117+ if _ , ok := userCounter .userSeriesMap [user ]; ok {
118+ t .discardedSeriesGauge .DeleteLabelValues (reason , user )
119+ delete (userCounter .userSeriesMap , user )
120+ }
131121 }
122+ userCounter .Unlock ()
132123 }
133- userCounter .Unlock ()
134124 }
135125 t .RUnlock ()
136126}
@@ -144,17 +134,118 @@ func (t *DiscardedSeriesTracker) StartVendDiscardedSeriesMetricGoroutine() {
144134 }()
145135}
146136
147- // only used in testing
137+ func NewDiscardedSeriesPerLabelsetTracker (discardedSeriesPerLabelsetGauge * prometheus.GaugeVec ) * DiscardedSeriesPerLabelsetTracker {
138+ tracker := & DiscardedSeriesPerLabelsetTracker {
139+ RWMutex : & sync.RWMutex {},
140+ userLabelsetMap : make (map [string ]* labelsetCounterStruct ),
141+ discardedSeriesPerLabelsetGauge : discardedSeriesPerLabelsetGauge ,
142+ }
143+ return tracker
144+ }
145+
146+ func (t * DiscardedSeriesPerLabelsetTracker ) Track (user string , series uint64 , matchedLabelsetHash uint64 , matchedLabelsetId string ) {
147+ t .RLock ()
148+ labelsetCounter , ok := t .userLabelsetMap [user ]
149+ t .RUnlock ()
150+ if ! ok {
151+ t .Lock ()
152+ labelsetCounter , ok = t .userLabelsetMap [user ]
153+ if ! ok {
154+ labelsetCounter = & labelsetCounterStruct {
155+ RWMutex : & sync.RWMutex {},
156+ labelsetSeriesMap : make (map [uint64 ]* seriesCounterStruct ),
157+ }
158+ t .userLabelsetMap [user ] = labelsetCounter
159+ }
160+ t .Unlock ()
161+ }
162+
163+ labelsetCounter .RLock ()
164+ seriesCounter , ok := labelsetCounter .labelsetSeriesMap [matchedLabelsetHash ]
165+ labelsetCounter .RUnlock ()
166+ if ! ok {
167+ labelsetCounter .Lock ()
168+ seriesCounter , ok = labelsetCounter .labelsetSeriesMap [matchedLabelsetHash ]
169+ if ! ok {
170+ seriesCounter = & seriesCounterStruct {
171+ RWMutex : & sync.RWMutex {},
172+ seriesCountMap : make (map [uint64 ]struct {}),
173+ labelsetId : matchedLabelsetId ,
174+ }
175+ labelsetCounter .labelsetSeriesMap [matchedLabelsetHash ] = seriesCounter
176+ }
177+ labelsetCounter .Unlock ()
178+ }
179+
180+ seriesCounter .RLock ()
181+ _ , ok = seriesCounter .seriesCountMap [series ]
182+ seriesCounter .RUnlock ()
183+ if ! ok {
184+ seriesCounter .Lock ()
185+ _ , ok = seriesCounter .seriesCountMap [series ]
186+ if ! ok {
187+ seriesCounter .seriesCountMap [series ] = struct {}{}
188+ }
189+ seriesCounter .Unlock ()
190+ }
191+ }
192+
193+ func (t * DiscardedSeriesPerLabelsetTracker ) UpdateMetrics () {
194+ usersToDelete := make ([]string , 0 )
195+ labelsetsToDelete := make ([]uint64 , 0 )
196+ t .RLock ()
197+ for user , labelsetCounter := range t .userLabelsetMap {
198+ labelsetCounter .RLock ()
199+ if len (labelsetCounter .labelsetSeriesMap ) == 0 {
200+ usersToDelete = append (usersToDelete , user )
201+ }
202+ for labelsetHash , seriesCounter := range labelsetCounter .labelsetSeriesMap {
203+ seriesCounter .Lock ()
204+ count := len (seriesCounter .seriesCountMap )
205+ t .discardedSeriesPerLabelsetGauge .WithLabelValues (perLabelsetSeriesLimit , user , seriesCounter .labelsetId ).Set (float64 (count ))
206+ clear (seriesCounter .seriesCountMap )
207+ if count == 0 {
208+ labelsetsToDelete = append (labelsetsToDelete , labelsetHash )
209+ }
210+ seriesCounter .Unlock ()
211+ }
212+ labelsetCounter .RUnlock ()
213+ if len (labelsetsToDelete ) > 0 {
214+ labelsetCounter .Lock ()
215+ for _ , labelsetHash := range labelsetsToDelete {
216+ if _ , ok := labelsetCounter .labelsetSeriesMap [labelsetHash ]; ok {
217+ labelsetId := labelsetCounter .labelsetSeriesMap [labelsetHash ].labelsetId
218+ t .discardedSeriesPerLabelsetGauge .DeleteLabelValues (perLabelsetSeriesLimit , user , labelsetId )
219+ delete (labelsetCounter .labelsetSeriesMap , labelsetHash )
220+ }
221+ }
222+ labelsetCounter .Unlock ()
223+ }
224+ }
225+ t .RUnlock ()
226+ if len (usersToDelete ) > 0 {
227+ t .Lock ()
228+ for _ , user := range usersToDelete {
229+ delete (t .userLabelsetMap , user )
230+ }
231+ t .Unlock ()
232+ }
233+ }
234+
235+ func (t * DiscardedSeriesPerLabelsetTracker ) StartVendDiscardedSeriesMetricGoroutine () {
236+ go func () {
237+ ticker := time .NewTicker (vendMetricsInterval )
238+ for range ticker .C {
239+ t .UpdateMetrics ()
240+ }
241+ }()
242+ }
243+
148244func (t * DiscardedSeriesTracker ) getSeriesCount (reason string , user string ) int {
149- count := 0
150245 if userCounter , ok := t .reasonUserMap [reason ]; ok {
151246 if seriesCounter , ok := userCounter .userSeriesMap [user ]; ok {
152- for _ , label := range seriesCounter .seriesCountMap {
153- if label .inCurrentCycle {
154- count ++
155- }
156- }
247+ return len (seriesCounter .seriesCountMap )
157248 }
158249 }
159- return count
250+ return 0
160251}
0 commit comments