mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-10-21 06:37:21 +00:00
improvements mid apr 2025 (#26)
* General improvements and bug fixes. * Admin dashboard
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// RPSTracker tracks requests per second using periodic sampling
|
||||
type RPSTracker struct {
|
||||
lastCount atomic.Int64
|
||||
lastSampleTime atomic.Int64 // Unix nano
|
||||
currentRPS uint64 // stored as uint64, accessed with atomic operations
|
||||
mu sync.RWMutex // for currentRPS updates
|
||||
}
|
||||
|
||||
// NewRPSTracker creates a new RPS tracker
|
||||
func NewRPSTracker() *RPSTracker {
|
||||
tracker := &RPSTracker{}
|
||||
tracker.lastSampleTime.Store(time.Now().UnixNano())
|
||||
go tracker.updateLoop()
|
||||
return tracker
|
||||
}
|
||||
|
||||
// RecordRequest increments the request counter
|
||||
func (r *RPSTracker) RecordRequest() {
|
||||
// Just increment the counter, sampling happens in background
|
||||
r.lastCount.Add(1)
|
||||
}
|
||||
|
||||
// updateLoop periodically calculates current RPS
|
||||
func (r *RPSTracker) updateLoop() {
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for range ticker.C {
|
||||
r.sample()
|
||||
}
|
||||
}
|
||||
|
||||
// sample calculates RPS since last sample
|
||||
func (r *RPSTracker) sample() {
|
||||
now := time.Now()
|
||||
nowNano := now.UnixNano()
|
||||
|
||||
currentCount := r.lastCount.Load()
|
||||
lastSampleNano := r.lastSampleTime.Load()
|
||||
|
||||
if lastSampleNano == 0 {
|
||||
r.lastSampleTime.Store(nowNano)
|
||||
return
|
||||
}
|
||||
|
||||
elapsed := float64(nowNano-lastSampleNano) / float64(time.Second)
|
||||
if elapsed > 0 {
|
||||
rps := float64(currentCount) / elapsed
|
||||
// Store RPS as centirps for precision (multiply by 100)
|
||||
r.mu.Lock()
|
||||
atomic.StoreUint64(&r.currentRPS, uint64(rps*100))
|
||||
r.mu.Unlock()
|
||||
}
|
||||
|
||||
// Reset for next sample
|
||||
r.lastCount.Store(0)
|
||||
r.lastSampleTime.Store(nowNano)
|
||||
}
|
||||
|
||||
// GetCurrentRPS returns the current requests per second
|
||||
func (r *RPSTracker) GetCurrentRPS() float64 {
|
||||
r.mu.RLock()
|
||||
centirps := atomic.LoadUint64(&r.currentRPS)
|
||||
r.mu.RUnlock()
|
||||
return float64(centirps) / 100.0
|
||||
}
|
||||
|
||||
var globalRPSTracker *RPSTracker
|
||||
|
||||
// InitializeRPSTracker initializes the global RPS tracker
|
||||
func InitializeRPSTracker() *RPSTracker {
|
||||
if globalRPSTracker == nil {
|
||||
globalRPSTracker = NewRPSTracker()
|
||||
}
|
||||
return globalRPSTracker
|
||||
}
|
||||
|
||||
// GetRPSTracker returns the global RPS tracker
|
||||
func GetRPSTracker() *RPSTracker {
|
||||
return globalRPSTracker
|
||||
}
|
||||
Reference in New Issue
Block a user