// Package verbose provides a process-wide verbosity level and a pluggable // log sink so verbose output integrates with the downloader's progress bars. // // Level meaning: // // 0 (Off) - no extra output // 1 (V) - log per-track CDN URLs from the downloader // 2 (VV) - additionally log every outbound HTTP request via the // netutil-wrapped transport (covers all provider API calls // and downloads) package verbose import ( "fmt" "os" "sync/atomic" ) const ( Off byte = 0 V byte = 1 VV byte = 2 ) var ( level atomic.Uint32 sink atomic.Pointer[func(string)] ) // SetLevel clamps and stores the verbosity level. Pass 0 to disable. func SetLevel(l int) { if l < 0 { l = 0 } if l > int(VV) { l = int(VV) } level.Store(uint32(l)) } func Level() byte { return byte(level.Load()) } func Enabled(l byte) bool { return Level() >= l } // SetSink installs a writer for verbose output. Use this to route logs // through the downloader so they don't tear progress bars. Pass nil to // fall back to stderr. func SetSink(fn func(string)) { if fn == nil { sink.Store(nil) return } sink.Store(&fn) } // Printf emits a line at the given level if verbosity is enabled. The // caller is responsible for including a trailing newline. func Printf(l byte, format string, args ...any) { if !Enabled(l) { return } msg := fmt.Sprintf(format, args...) if p := sink.Load(); p != nil { (*p)(msg) return } _, _ = fmt.Fprint(os.Stderr, msg) }