@@ -31,9 +31,10 @@ type QueueLimiter[T any] interface {
3131// NewQueueLimiter returns a simple static QueueLimiter.
3232func NewQueueLimiter [T any ](capacity int ) QueueLimiter [T ] {
3333 q := & queue [T ]{
34- cap : capacity ,
35- recordLimit : func (context.Context , int ) {},
36- recordUsage : func (context.Context , int ) {},
34+ cap : capacity ,
35+ recordLimit : func (context.Context , int ) {},
36+ recordUsage : func (context.Context , int ) {},
37+ recordDenied : func (context.Context , int ) {},
3738 }
3839 q .cond .L = & q .mu
3940 return q
@@ -46,8 +47,9 @@ type queue[T any] struct {
4647 scope settings.Scope // optional
4748 tenant string // optional
4849
49- recordLimit func (context.Context , int )
50- recordUsage func (context.Context , int )
50+ recordLimit func (context.Context , int )
51+ recordUsage func (context.Context , int )
52+ recordDenied func (context.Context , int )
5153
5254 cap int
5355 list list.List
@@ -81,8 +83,9 @@ func (q *queue[T]) Put(ctx context.Context, t T) error {
8183 q .mu .Lock ()
8284 defer q .mu .Unlock ()
8385
84- if q .list .Len () >= q .cap {
85- return ErrorQueueFull {Key : q .key , Scope : q .scope , Tenant : q .tenant , Limit : q .cap }
86+ if c := q .cap ; q .list .Len () >= c {
87+ q .recordDenied (ctx , 1 )
88+ return ErrorQueueFull {Key : q .key , Scope : q .scope , Tenant : q .tenant , Limit : c }
8689 }
8790 q .list .PushBack (t )
8891 q .cond .Signal ()
@@ -158,12 +161,23 @@ func newUnscopedQueue[T any](f Factory, limit settings.Setting[int]) (QueueLimit
158161 if err != nil {
159162 return nil , err
160163 }
164+ deniedHist , err := f .Meter .Int64Histogram ("queue." + limit .Key + ".denied" , metric .WithUnit (limit .Unit ))
165+ if err != nil {
166+ return nil , err
167+ }
161168 q .recordLimit = func (ctx context.Context , i int ) {
162169 limitGauge .Record (ctx , int64 (i ))
163170 }
164171 q .recordUsage = func (ctx context.Context , i int ) {
165172 usageGauge .Record (ctx , int64 (i ))
166173 }
174+ q .recordDenied = func (ctx context.Context , i int ) {
175+ deniedHist .Record (ctx , int64 (i ))
176+ }
177+ } else {
178+ q .recordLimit = func (context.Context , int ) {}
179+ q .recordUsage = func (context.Context , int ) {}
180+ q .recordDenied = func (context.Context , int ) {}
167181 }
168182
169183 if f .Settings != nil {
@@ -174,7 +188,6 @@ func newUnscopedQueue[T any](f Factory, limit settings.Setting[int]) (QueueLimit
174188 q .subFn = func (ctx context.Context ) (updates <- chan settings.Update [int ], cancelSub func ()) {
175189 return limit .Subscribe (ctx , registry )
176190 }
177-
178191 }
179192 }
180193
@@ -207,6 +220,10 @@ func newScopedQueue[T any](f Factory, limit settings.Setting[int]) (QueueLimiter
207220 if err != nil {
208221 return nil , err
209222 }
223+ q .deniedHist , err = f .Meter .Int64Histogram ("queue." + limit .Key + ".denied" , metric .WithUnit (limit .Unit ))
224+ if err != nil {
225+ return nil , err
226+ }
210227 }
211228
212229 if f .Settings != nil {
@@ -237,8 +254,9 @@ type scopedQueue[T any] struct {
237254
238255 key string // optional
239256
240- limitGauge metric.Int64Gauge // optional
241- usageGauge metric.Int64Gauge // optional
257+ limitGauge metric.Int64Gauge // optional
258+ usageGauge metric.Int64Gauge // optional
259+ deniedHist metric.Int64Histogram // optional
242260
243261 // opt: reap after period of non-use
244262 queues sync.Map // map[string]*queue
@@ -344,6 +362,11 @@ func (s *scopedQueue[T]) newQueue(tenant string) *queue[T] {
344362 s .usageGauge .Record (ctx , int64 (c ), withScope (ctx , s .scope ))
345363 }
346364 },
365+ recordDenied : func (ctx context.Context , c int ) {
366+ if s .deniedHist != nil {
367+ s .deniedHist .Record (ctx , int64 (c ), withScope (ctx , s .scope ))
368+ }
369+ },
347370 }
348371 q .cond .L = & q .mu
349372 q .updater .recordLimit = q .setCap
0 commit comments