71 lines
1.5 KiB
Go
71 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
type callbackQueueMetrics struct {
|
|
current atomic.Int64
|
|
processing atomic.Int64
|
|
maximum atomic.Int64
|
|
enqueued atomic.Int64
|
|
completed atomic.Int64
|
|
waitNanos atomic.Int64
|
|
maxWait atomic.Int64
|
|
}
|
|
|
|
func (m *callbackQueueMetrics) enqueue() {
|
|
if m == nil {
|
|
return
|
|
}
|
|
current := m.current.Add(1)
|
|
m.enqueued.Add(1)
|
|
updateAtomicMax(&m.maximum, current)
|
|
}
|
|
|
|
func (m *callbackQueueMetrics) startCallback(queuedAt time.Time) {
|
|
if m == nil {
|
|
return
|
|
}
|
|
wait := time.Since(queuedAt).Nanoseconds()
|
|
if wait < 0 {
|
|
wait = 0
|
|
}
|
|
m.current.Add(-1)
|
|
m.processing.Add(1)
|
|
m.waitNanos.Add(wait)
|
|
updateAtomicMax(&m.maxWait, wait)
|
|
}
|
|
|
|
func (m *callbackQueueMetrics) finishCallback() {
|
|
if m == nil {
|
|
return
|
|
}
|
|
m.processing.Add(-1)
|
|
m.completed.Add(1)
|
|
}
|
|
|
|
func (m *callbackQueueMetrics) snapshot() CallbackQueueSnapshot {
|
|
if m == nil {
|
|
return CallbackQueueSnapshot{}
|
|
}
|
|
return CallbackQueueSnapshot{
|
|
Current: m.current.Load(), Processing: m.processing.Load(), Maximum: m.maximum.Load(), Enqueued: m.enqueued.Load(),
|
|
Completed: m.completed.Load(), WaitSecondsTotal: float64(m.waitNanos.Load()) / float64(time.Second),
|
|
WaitSecondsMax: float64(m.maxWait.Load()) / float64(time.Second),
|
|
}
|
|
}
|
|
|
|
func (m *callbackQueueMetrics) isDrained() bool {
|
|
return m == nil || (m.current.Load() == 0 && m.processing.Load() == 0)
|
|
}
|
|
|
|
func updateAtomicMax(target *atomic.Int64, value int64) {
|
|
for current := target.Load(); value > current; current = target.Load() {
|
|
if target.CompareAndSwap(current, value) {
|
|
return
|
|
}
|
|
}
|
|
}
|