github.com/anthropics/anthropic-sdk-go@v1.70.1/internal/auth/logging.go (about) 1 package auth 2 3 import ( 4 "log" 5 "sync" 6 ) 7 8 // warnOnce emits a log line for an error category exactly once per process. 9 // Used for best-effort failures that should not surface as request errors 10 // but also must not be swallowed silently (e.g. a permissions problem on 11 // the credentials cache would otherwise cause a fresh exchange on every 12 // request with no visible cause). 13 var ( 14 warnOnceMu sync.Mutex 15 warnOnceSet = map[string]bool{} 16 ) 17 18 func warnOnce(key, format string, args ...any) { 19 warnOnceMu.Lock() 20 already := warnOnceSet[key] 21 warnOnceSet[key] = true 22 warnOnceMu.Unlock() 23 if already { 24 return 25 } 26 log.Printf("anthropic-sdk-go/auth: "+format, args...) 27 } 28 29 // ResetWarnOnceForTest clears the warnOnce dedupe set. Exported for test 30 // helpers in sibling packages (e.g. internal/auth integration tests in 31 // package auth_test) that need to observe a warning a prior test may 32 // already have triggered. 33 func ResetWarnOnceForTest() { 34 warnOnceMu.Lock() 35 warnOnceSet = map[string]bool{} 36 warnOnceMu.Unlock() 37 } 38 39 // ConfigShadowSource describes where the static credential that is 40 // shadowing a profile came from. Used by [WarnConfigShadowed] to tailor 41 // the remediation hint. 42 type ConfigShadowSource int 43 44 const ( 45 // ConfigShadowFromEnv means the static credential was picked up from 46 // ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN by the env autoloader. 47 // Remediation: unset the env var. 48 ConfigShadowFromEnv ConfigShadowSource = iota 49 // ConfigShadowFromOption means the static credential was passed 50 // explicitly via option.WithAPIKey / option.WithAuthToken. 51 // Remediation: remove the option. 52 ConfigShadowFromOption 53 ) 54 55 // WarnConfigShadowed warns once when a static credential is present 56 // alongside a profile config. Per the documented precedence, the static 57 // credential wins, which silently disables the profile's auth. Source 58 // determines whether the remediation points at an env var or an explicit 59 // option call. 60 func WarnConfigShadowed(name string, source ConfigShadowSource) { 61 var remediation string 62 switch source { 63 case ConfigShadowFromOption: 64 remediation = "remove the explicit option" 65 default: 66 remediation = "unset " + name + " (and remove any explicit WithAPIKey/WithAuthToken calls if present)" 67 } 68 warnOnce( 69 "config-shadowed-by-"+name, 70 "%s is set and takes precedence over the profile configuration passed via WithConfig; to use the profile, %s", 71 name, remediation, 72 ) 73 }