Compare commits

..

2 Commits

Author SHA1 Message Date
3d4198ac42 remove goroutine for db
Some checks failed
coverage / build (pull_request) Failing after 2m5s
lint / lint (pull_request) Successful in 4m47s
test / test (pull_request) Successful in 4m5s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-10-07 00:07:25 +03:00
5dfcc76ce8 meter: add Unregister metric
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-09-22 09:52:17 +03:00
3 changed files with 83 additions and 23 deletions

View File

@@ -3,6 +3,7 @@ package sql
import ( import (
"context" "context"
"database/sql" "database/sql"
"sync"
"time" "time"
) )
@@ -11,31 +12,84 @@ type Statser interface {
} }
func NewStatsMeter(ctx context.Context, db Statser, opts ...Option) { func NewStatsMeter(ctx context.Context, db Statser, opts ...Option) {
options := NewOptions(opts...)
go func() {
ticker := time.NewTicker(options.MeterStatsInterval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
if db == nil { if db == nil {
return return
} }
options := NewOptions(opts...)
var (
statsMu sync.Mutex
lastUpdated time.Time
maxOpenConnections, openConnections, inUse, idle, waitCount float64
maxIdleClosed, maxIdleTimeClosed, maxLifetimeClosed float64
waitDuration float64
)
updateFn := func() {
statsMu.Lock()
defer statsMu.Unlock()
if time.Since(lastUpdated) < options.MeterStatsInterval {
return
}
stats := db.Stats() stats := db.Stats()
options.Meter.Counter(MaxOpenConnections).Set(uint64(stats.MaxOpenConnections)) maxOpenConnections = float64(stats.MaxOpenConnections)
options.Meter.Counter(OpenConnections).Set(uint64(stats.OpenConnections)) openConnections = float64(stats.OpenConnections)
options.Meter.Counter(InuseConnections).Set(uint64(stats.InUse)) inUse = float64(stats.InUse)
options.Meter.Counter(IdleConnections).Set(uint64(stats.Idle)) idle = float64(stats.Idle)
options.Meter.Counter(WaitConnections).Set(uint64(stats.WaitCount)) waitCount = float64(stats.WaitCount)
options.Meter.FloatCounter(BlockedSeconds).Set(stats.WaitDuration.Seconds()) maxIdleClosed = float64(stats.MaxIdleClosed)
options.Meter.Counter(MaxIdleClosed).Set(uint64(stats.MaxIdleClosed)) maxIdleTimeClosed = float64(stats.MaxIdleTimeClosed)
options.Meter.Counter(MaxIdletimeClosed).Set(uint64(stats.MaxIdleTimeClosed)) maxLifetimeClosed = float64(stats.MaxLifetimeClosed)
options.Meter.Counter(MaxLifetimeClosed).Set(uint64(stats.MaxLifetimeClosed)) waitDuration = float64(stats.WaitDuration.Seconds())
lastUpdated = time.Now()
} }
}
}() options.Meter.Gauge(MaxOpenConnections, func() float64 {
updateFn()
return maxOpenConnections
})
options.Meter.Gauge(OpenConnections, func() float64 {
updateFn()
return openConnections
})
options.Meter.Gauge(InuseConnections, func() float64 {
updateFn()
return inUse
})
options.Meter.Gauge(IdleConnections, func() float64 {
updateFn()
return idle
})
options.Meter.Gauge(WaitConnections, func() float64 {
updateFn()
return waitCount
})
options.Meter.Gauge(BlockedSeconds, func() float64 {
updateFn()
return waitDuration
})
options.Meter.Gauge(MaxIdleClosed, func() float64 {
updateFn()
return maxIdleClosed
})
options.Meter.Gauge(MaxIdletimeClosed, func() float64 {
updateFn()
return maxIdleTimeClosed
})
options.Meter.Gauge(MaxLifetimeClosed, func() float64 {
updateFn()
return maxLifetimeClosed
})
} }

View File

@@ -59,6 +59,8 @@ type Meter interface {
Options() Options Options() Options
// String return meter type // String return meter type
String() string String() string
// Unregister metric name and drop all data
Unregister(name string, labels ...string) bool
} }
// Counter is a counter // Counter is a counter

View File

@@ -28,6 +28,10 @@ func (r *noopMeter) Name() string {
return r.opts.Name return r.opts.Name
} }
func (r *noopMeter) Unregister(name string, labels ...string) bool {
return true
}
// Init initialize options // Init initialize options
func (r *noopMeter) Init(opts ...Option) error { func (r *noopMeter) Init(opts ...Option) error {
for _, o := range opts { for _, o := range opts {