github.com/instana/go-sensor@v1.62.2-0.20240520081010-4919868049e1/logger/logger.go (about) 1 // (c) Copyright IBM Corp. 2021 2 // (c) Copyright Instana Inc. 2020 3 4 package logger 5 6 import ( 7 "fmt" 8 "log" 9 "os" 10 "strings" 11 "sync" 12 ) 13 14 // Valid log levels to be used with (*logger.Logger).SetLevel() 15 const ( 16 ErrorLevel Level = iota 17 WarnLevel 18 InfoLevel 19 DebugLevel 20 ) 21 22 // DefaultPrefix is the default log prefix used by Logger 23 const DefaultPrefix = "instana: " 24 25 // Level defines the minimum logging level for logger.Log 26 type Level uint8 27 28 // Less returns whether the log level is less than the given one in logical order: 29 // ErrorLevel > WarnLevel > InfoLevel > DebugLevel 30 func (lvl Level) Less(other Level) bool { 31 return uint8(lvl) > uint8(other) 32 } 33 34 // String returns the log line label for this level 35 func (lvl Level) String() string { 36 switch lvl { 37 case DebugLevel: 38 return "DEBUG" 39 case InfoLevel: 40 return "INFO" 41 case WarnLevel: 42 return "WARN" 43 case ErrorLevel: 44 return "ERROR" 45 default: 46 return "UNKNOWN" 47 } 48 } 49 50 // Printer is used by logger.Log instance to print out a log message 51 type Printer interface { 52 Print(a ...interface{}) 53 } 54 55 // Logger is a configurable leveled logger used by Instana's Go sensor. It follows the same interface 56 // as github.com/sirupsen/logrus.Logger and go.uber.org/zap.SugaredLogger 57 type Logger struct { 58 p Printer 59 60 mu sync.Mutex 61 lvl Level 62 prefix string 63 } 64 65 // New initializes a new instance of Logger that uses provided printer as a backend to 66 // output the log messages. The stdlib log.Logger satisfies logger.Printer interface: 67 // 68 // logger := logger.New(logger.WarnLevel, log.New(os.Stderr, "instana:", log.LstdFlags)) 69 // logger.SetLevel(logger.WarnLevel) 70 // 71 // logger.Debug("this is a debug message") // won't be printed 72 // logger.Error("this is an message") // ... while this one will 73 // 74 // In case there is no printer provided, logger.Logger will use a new instance of log.Logger 75 // initialized with log.Lstdflags that writes to os.Stderr: 76 // 77 // log.New(os.Stderr, "", log.Lstdflags) 78 // 79 // The default logging level for a new logger instance is logger.ErrorLevel. 80 func New(printer Printer) *Logger { 81 if printer == nil { 82 printer = log.New(os.Stderr, "", log.LstdFlags) 83 } 84 85 l := &Logger{ 86 p: printer, 87 prefix: DefaultPrefix, 88 } 89 90 setInstanaLogLevel(l) 91 92 return l 93 } 94 95 func setInstanaLogLevel(l *Logger) { 96 instanaLogLevelEnvVar := os.Getenv("INSTANA_LOG_LEVEL") 97 98 envVarLogLevel := map[string]Level{ 99 "error": ErrorLevel, 100 "info": InfoLevel, 101 "warn": WarnLevel, 102 "debug": DebugLevel, 103 } 104 105 if value, ok := envVarLogLevel[strings.ToLower(instanaLogLevelEnvVar)]; ok { 106 l.SetLevel(value) 107 } else { 108 l.SetLevel(ErrorLevel) 109 } 110 } 111 112 // SetLevel changes the log level for this logger instance. In case there is an INSTANA_DEBUG env variable set, 113 // the provided log level will be overridden with DebugLevel. 114 func (l *Logger) SetLevel(level Level) { 115 if _, ok := os.LookupEnv("INSTANA_DEBUG"); ok { 116 if level != DebugLevel { 117 defer l.Info( 118 "INSTANA_DEBUG env variable is set, the log level has been set to ", 119 DebugLevel, 120 " instead of requested ", 121 level, 122 ) 123 } 124 level = DebugLevel 125 } 126 127 l.mu.Lock() 128 defer l.mu.Unlock() 129 130 l.lvl = level 131 } 132 133 // SetPrefix sets the label that will be used as a prefix for each log line 134 func (l *Logger) SetPrefix(prefix string) { 135 l.mu.Lock() 136 defer l.mu.Unlock() 137 138 l.prefix = prefix 139 } 140 141 // Debug appends a debug message to the log 142 func (l *Logger) Debug(v ...interface{}) { 143 if l.lvl < DebugLevel { 144 return 145 } 146 147 l.print(DebugLevel, v) 148 } 149 150 // Info appends an info message to the log 151 func (l *Logger) Info(v ...interface{}) { 152 if l.lvl < InfoLevel { 153 return 154 } 155 156 l.print(InfoLevel, v) 157 } 158 159 // Warn appends a warning message to the log 160 func (l *Logger) Warn(v ...interface{}) { 161 if l.lvl < WarnLevel { 162 return 163 } 164 165 l.print(WarnLevel, v) 166 } 167 168 // Error appends an error message to the log 169 func (l *Logger) Error(v ...interface{}) { 170 if l.lvl < ErrorLevel { 171 return 172 } 173 174 l.print(ErrorLevel, v) 175 } 176 177 func (l *Logger) print(lvl Level, v []interface{}) { 178 l.p.Print(l.prefix, lvl.String(), ": ", fmt.Sprint(v...)) 179 }