fix(hosterrorscache): dup log spam for permanent errs

The "Skipped X from target list as found
unresponsive permanently" message was logged on
every `(*Cache).Check()` call for hosts with
permanent errors, resulting in thousands of
duplicate log entries in verbose mode.

Wrap the log statement in `sync.Once` to match the
behavior already used for non-permanent error
logging.

Signed-off-by: Dwi Siswanto <git@dw1.io>
This commit is contained in:
Dwi Siswanto
2025-12-14 22:36:17 +07:00
parent cf3b5bf449
commit 127e03f572
2 changed files with 29 additions and 2 deletions

View File

@@ -27,6 +27,7 @@ type CacheInterface interface {
Remove(ctx *contextargs.Context) // remove a host from the cache
MarkFailed(protoType string, ctx *contextargs.Context, err error) // record a failure (and cause) for the host
MarkFailedOrRemove(protoType string, ctx *contextargs.Context, err error) // record a failure (and cause) for the host or remove it
IsPermanentErr(ctx *contextargs.Context, err error) bool // return true if the error is permanent for the host
}
var (
@@ -137,8 +138,9 @@ func (c *Cache) Check(protoType string, ctx *contextargs.Context) bool {
defer cache.mu.Unlock()
if cache.isPermanentErr {
// skipping permanent errors is expected so verbose instead of info
gologger.Verbose().Msgf("Skipped %s from target list as found unresponsive permanently: %s", finalValue, cache.cause)
cache.Do(func() {
gologger.Info().Msgf("Skipped %s from target list as found unresponsive permanently: %s", finalValue, cache.cause)
})
return true
}
@@ -232,6 +234,28 @@ func (c *Cache) MarkFailedOrRemove(protoType string, ctx *contextargs.Context, e
_ = c.failedTargets.Set(cacheKey, cache)
}
// IsPermanentErr returns true if the error is permanent for the host.
func (c *Cache) IsPermanentErr(ctx *contextargs.Context, err error) bool {
if err == nil {
return false
}
if errkit.IsKind(err, errkit.ErrKindNetworkPermanent) {
return true
}
cacheKey := c.GetKeyFromContext(ctx, err)
cache, cacheErr := c.failedTargets.GetIFPresent(cacheKey)
if cacheErr != nil {
return false
}
cache.mu.Lock()
defer cache.mu.Unlock()
return cache.isPermanentErr
}
// GetKeyFromContext returns the key for the cache from the context
func (c *Cache) GetKeyFromContext(ctx *contextargs.Context, err error) string {
// Note: