From aaf9ce30b14866263cc9372ab035d8b1cb4d410a Mon Sep 17 00:00:00 2001 From: Benjamin Borbe Date: Wed, 12 Aug 2026 22:20:50 +0200 Subject: [PATCH 1/2] fix: use libtime.Now() in the two remaining raw time.Now() sites log_sampler-time.go already documents the convention -- 'uses github.com/bborbe/time for consistent time handling across the library' -- and github.com/bborbe/time is already a direct dependency, so this is internal consistency rather than a new dependency. Both sites drive time-threshold logic: LogMemoryUsage's log-if-interval-elapsed check and Set's auto-reset-after-duration timestamp. Neither could be exercised deterministically against a frozen clock while calling time.Now() directly. Found by repo-review at 7c4b378: 88 mechanical findings across 74 rules, 1 confirmed. --- CHANGELOG.md | 4 ++++ log_memory-monitor.go | 3 ++- log_set-loglevel-setter.go | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 420f74c..9131e16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ Please choose versions by [Semantic Versioning](http://semver.org/). * MINOR version when you add functionality in a backwards-compatible manner, and * PATCH version when you make backwards-compatible bug fixes. +## Unreleased + +- fix: `memoryMonitor.LogMemoryUsage` and `logLevelSetter.Set` now use `libtime.Now()` instead of `time.Now()`, matching the convention `log_sampler-time.go` already documents ("uses github.com/bborbe/time for consistent time handling across the library"). Both sites drive time-threshold logic — log-if-interval-elapsed and auto-reset-after-duration — which could not be exercised deterministically against a frozen clock. + ## v1.6.20 - update Go to 1.26.5 and update dependencies diff --git a/log_memory-monitor.go b/log_memory-monitor.go index 1c27f1d..597665f 100644 --- a/log_memory-monitor.go +++ b/log_memory-monitor.go @@ -10,6 +10,7 @@ import ( "sync" "time" + libtime "github.com/bborbe/time" "github.com/golang/glog" ) @@ -43,7 +44,7 @@ func (m *memoryMonitor) LogMemoryUsage(name string) { m.mutex.Lock() defer m.mutex.Unlock() - now := time.Now() + now := libtime.Now() // Check if enough time has passed since last log if m.lastLogTime.IsZero() || now.Sub(m.lastLogTime) >= m.logInterval { diff --git a/log_set-loglevel-setter.go b/log_set-loglevel-setter.go index 4b69352..97fca3e 100644 --- a/log_set-loglevel-setter.go +++ b/log_set-loglevel-setter.go @@ -11,6 +11,7 @@ import ( "sync" "time" + libtime "github.com/bborbe/time" "github.com/golang/glog" ) @@ -69,7 +70,7 @@ func (l *logLevelSetter) Set(ctx context.Context, logLevel glog.Level) error { l.mux.Lock() defer l.mux.Unlock() - l.lastSetTime = time.Now() + l.lastSetTime = libtime.Now() l.currentLogLevel = logLevel _ = flag.Set("v", strconv.Itoa(int(logLevel))) From 6d9db197825443adf2aa1a1bc1d878b74e94af79 Mon Sep 17 00:00:00 2001 From: Benjamin Borbe Date: Wed, 12 Aug 2026 22:31:54 +0200 Subject: [PATCH 2/2] fix: read lastSetTime through libtime too, not time.Since The first commit changed the write (lastSetTime = libtime.Now()) but left the read as time.Since(l.lastSetTime). Against a frozen clock those are two different clocks, so the comparison was inconsistent -- arguably worse than the uniform-stdlib version it replaced. Now libtime.Now().Sub(l.lastSetTime), matching the pattern already used in log_sampler-time.go. Caught by the bot review on the first push. --- CHANGELOG.md | 2 +- log_set-loglevel-setter.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9131e16..6f50623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ Please choose versions by [Semantic Versioning](http://semver.org/). ## Unreleased -- fix: `memoryMonitor.LogMemoryUsage` and `logLevelSetter.Set` now use `libtime.Now()` instead of `time.Now()`, matching the convention `log_sampler-time.go` already documents ("uses github.com/bborbe/time for consistent time handling across the library"). Both sites drive time-threshold logic — log-if-interval-elapsed and auto-reset-after-duration — which could not be exercised deterministically against a frozen clock. +- fix: `memoryMonitor.LogMemoryUsage`, `logLevelSetter.Set` and `logLevelSetter.resetLogLevel` now use `libtime` instead of stdlib `time`, matching the convention `log_sampler-time.go` already documents ("uses github.com/bborbe/time for consistent time handling across the library"). All three drive time-threshold logic — log-if-interval-elapsed and auto-reset-after-duration — which could not be exercised deterministically against a frozen clock. The reset check uses `libtime.Now().Sub(lastSetTime)` rather than `time.Since(lastSetTime)`, so both the write and the read of `lastSetTime` come from the same clock. ## v1.6.20 diff --git a/log_set-loglevel-setter.go b/log_set-loglevel-setter.go index 97fca3e..2004752 100644 --- a/log_set-loglevel-setter.go +++ b/log_set-loglevel-setter.go @@ -91,7 +91,7 @@ func (l *logLevelSetter) resetLogLevel() { l.mux.Lock() defer l.mux.Unlock() - if time.Since(l.lastSetTime) <= l.autoResetDuration { + if libtime.Now().Sub(l.lastSetTime) <= l.autoResetDuration { glog.V(l.defaultLoglevel).Infof("time since lastSet is too short => skip reset loglevel") return }