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  }