Files
27582dde69 Add log which will report dropped log count (#9752)
### Describe Your Changes

I have added a counter for the throttled logs which gets logged every 1
minute.
Fixes #9498

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Co-authored-by: Hui Wang <[email protected]>
2025-11-12 19:32:33 +02:00

77 lines
1.7 KiB
Go

package logger
import (
"fmt"
"sync"
"sync/atomic"
"time"
)
var (
logThrottlerRegistryMu = sync.Mutex{}
logThrottlerRegistry = make(map[string]*LogThrottler)
)
// WithThrottler returns a logger throttled by time - only one message in throttle duration will be logged.
//
// New logger is created only once for each unique name passed.
// The function is thread-safe.
func WithThrottler(name string, throttle time.Duration) *LogThrottler {
logThrottlerRegistryMu.Lock()
defer logThrottlerRegistryMu.Unlock()
lt, ok := logThrottlerRegistry[name]
if ok {
return lt
}
lt = newLogThrottler(throttle)
logThrottlerRegistry[name] = lt
return lt
}
// LogThrottler is a logger, which throttles log messages passed to Warnf and Errorf.
//
// LogThrottler must be created via WithThrottler() call.
type LogThrottler struct {
ch chan struct{}
dropped atomic.Uint64
}
func newLogThrottler(throttle time.Duration) *LogThrottler {
lt := &LogThrottler{
ch: make(chan struct{}, 1),
}
go func() {
for {
<-lt.ch
time.Sleep(throttle)
}
}()
return lt
}
// Errorf logs error message.
func (lt *LogThrottler) Errorf(format string, args ...any) {
select {
case lt.ch <- struct{}{}:
dropped := lt.dropped.Swap(0)
format = fmt.Sprintf("%s. (Similar %d log messages were dropped due to throttling)", format, dropped)
ErrorfSkipframes(1, format, args...)
default:
lt.dropped.Add(1)
}
}
// Warnf logs warn message.
func (lt *LogThrottler) Warnf(format string, args ...any) {
select {
case lt.ch <- struct{}{}:
dropped := lt.dropped.Swap(0)
format = fmt.Sprintf("%s. (Similar %d log messages were dropped due to throttling)", format, dropped)
WarnfSkipframes(1, format, args...)
default:
lt.dropped.Add(1)
}
}