github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/log/timed_level.go (about) 1 package log 2 3 import ( 4 "context" 5 "sync" 6 "time" 7 ) 8 9 // LevelSetter is a function that sets the log-level. 10 type LevelSetter func(ctx context.Context, logLevel string) 11 12 // TimedLevel is an object capable of setting a log-level for a given time 13 // period and then resetting it to a default. 14 type TimedLevel interface { 15 sync.Locker 16 17 // Get returns the current level and the time left until that level 18 // is reset to default. An empty string and zero is returned if 19 // no level has been set or if it has expired already. 20 Get() (string, time.Duration) 21 22 // Set sets a new log-level that will be active for the given duration. If the 23 // duration is zero, then the log-level will be active until the next call to 24 // Set. If level is the empty string, then duration is ignored and the log-level 25 // will be reset to default. 26 Set(ctx context.Context, level string, duration time.Duration) 27 28 // Reset restores the log-level to its default value 29 Reset(ctx context.Context) 30 } 31 32 type timedLevel struct { 33 sync.Mutex 34 setter LevelSetter 35 tempLevel string 36 defaultLevel string 37 timer *time.Timer 38 expires *time.Time 39 } 40 41 // NewTimedLevel returns a new TimedLevel for the given default level and setter. 42 func NewTimedLevel(defaultLevel string, setter LevelSetter) TimedLevel { 43 return &timedLevel{ 44 setter: setter, 45 defaultLevel: defaultLevel, 46 } 47 } 48 49 func (tl *timedLevel) Get() (string, time.Duration) { 50 tl.Lock() 51 defer tl.Unlock() 52 if tl.tempLevel == "" || tl.expires == nil { 53 return tl.tempLevel, 0 54 } 55 remain := time.Until(*tl.expires) 56 if remain <= 0 { 57 return "", 0 58 } 59 return tl.tempLevel, remain 60 } 61 62 func (tl *timedLevel) Set(ctx context.Context, level string, duration time.Duration) { 63 if level == "" { 64 tl.Reset(ctx) 65 return 66 } 67 68 tl.Lock() 69 defer tl.Unlock() 70 71 if tl.timer != nil { 72 tl.timer.Stop() 73 } 74 75 tl.setter(ctx, level) 76 tl.tempLevel = level 77 if duration == 0 { 78 tl.expires = nil 79 tl.timer = nil 80 return 81 } 82 83 exTime := time.Now().Add(duration) 84 tl.expires = &exTime 85 if tl.timer == nil { 86 tl.timer = time.AfterFunc(duration, func() { 87 tl.Reset(ctx) 88 }) 89 } else { 90 tl.timer.Reset(duration) 91 } 92 } 93 94 // Reset restores the log-level to its default value. 95 func (tl *timedLevel) Reset(ctx context.Context) { 96 tl.Lock() 97 defer tl.Unlock() 98 tl.expires = nil 99 tl.tempLevel = "" 100 tl.setter(ctx, tl.defaultLevel) 101 }