From 127e03f57293862a4b18c22d31350380a6be3c65 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto Date: Sun, 14 Dec 2025 22:36:17 +0700 Subject: [PATCH 1/2] 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 --- .../common/hosterrorscache/hosterrorscache.go | 28 +++++++++++++++++-- pkg/protocols/http/request_test.go | 3 ++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/pkg/protocols/common/hosterrorscache/hosterrorscache.go b/pkg/protocols/common/hosterrorscache/hosterrorscache.go index 3053b8efb1..571e2af92f 100644 --- a/pkg/protocols/common/hosterrorscache/hosterrorscache.go +++ b/pkg/protocols/common/hosterrorscache/hosterrorscache.go @@ -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: diff --git a/pkg/protocols/http/request_test.go b/pkg/protocols/http/request_test.go index 9eb7b100e4..dfc5041a23 100644 --- a/pkg/protocols/http/request_test.go +++ b/pkg/protocols/http/request_test.go @@ -274,6 +274,9 @@ func (f *fakeHostErrorsCache) MarkFailedOrRemove(string, *contextargs.Context, e // Check always returns true to simulate an already unresponsive host func (f *fakeHostErrorsCache) Check(string, *contextargs.Context) bool { return true } +// IsPermanentErr returns false for tests +func (f *fakeHostErrorsCache) IsPermanentErr(*contextargs.Context, error) bool { return false } + func TestExecuteParallelHTTP_StopAtFirstMatch(t *testing.T) { options := testutils.DefaultOptions testutils.Init(options) From 8a583bf9ca8c6cf6e013ab9105f89cef5e04fc0c Mon Sep 17 00:00:00 2001 From: Dwi Siswanto Date: Sun, 14 Dec 2025 22:41:32 +0700 Subject: [PATCH 2/2] chore(core): rm colorized template id Signed-off-by: Dwi Siswanto --- pkg/core/executors.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/core/executors.go b/pkg/core/executors.go index aeb85ddfe6..22c2b090c6 100644 --- a/pkg/core/executors.go +++ b/pkg/core/executors.go @@ -112,7 +112,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ match, err := e.executeTemplateOnInput(ctx, template, t.value) if err != nil { - e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), t.value.Input, err) + e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", template.ID, t.value.Input, err) } results.CompareAndSwap(false, match) }() @@ -216,7 +216,7 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t match, err := e.executeTemplateOnInput(ctx, template, value) if err != nil { - e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) + e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", template.ID, value.Input, err) } results.CompareAndSwap(false, match) }(tpl, target, sg)