1package gocbcore 2 3import ( 4 "fmt" 5 "log" 6 "os" 7 "strings" 8) 9 10// LogLevel specifies the severity of a log message. 11type LogLevel int 12 13// Various logging levels (or subsystems) which can categorize the message. 14// Currently these are ordered in decreasing severity. 15const ( 16 LogError LogLevel = iota 17 LogWarn 18 LogInfo 19 LogDebug 20 LogTrace 21 LogSched 22 LogMaxVerbosity 23) 24 25// LogRedactLevel specifies the degree with which to redact the logs. 26type LogRedactLevel int 27 28const ( 29 // RedactNone indicates to perform no redactions 30 RedactNone LogRedactLevel = iota 31 32 // RedactPartial indicates to redact all possible user-identifying information from logs. 33 RedactPartial 34 35 // RedactFull indicates to fully redact all possible identifying information from logs. 36 RedactFull 37) 38 39// SetLogRedactionLevel specifies the level with which logs should be redacted. 40func SetLogRedactionLevel(level LogRedactLevel) { 41 globalLogRedactionLevel = level 42} 43 44func isLogRedactionLevelNone() bool { 45 return globalLogRedactionLevel == RedactNone 46} 47 48func isLogRedactionLevelPartial() bool { 49 return globalLogRedactionLevel == RedactPartial 50} 51 52func isLogRedactionLevelFull() bool { 53 return globalLogRedactionLevel == RedactFull 54} 55 56func logLevelToString(level LogLevel) string { 57 switch level { 58 case LogError: 59 return "error" 60 case LogWarn: 61 return "warn" 62 case LogInfo: 63 return "info" 64 case LogDebug: 65 return "debug" 66 case LogTrace: 67 return "trace" 68 case LogSched: 69 return "sched" 70 } 71 72 return fmt.Sprintf("unknown (%d)", level) 73} 74 75// Logger defines a logging interface. You can either use one of the default loggers 76// (DefaultStdioLogger(), VerboseStdioLogger()) or implement your own. 77type Logger interface { 78 // Outputs logging information: 79 // level is the verbosity level 80 // offset is the position within the calling stack from which the message 81 // originated. This is useful for contextual loggers which retrieve file/line 82 // information. 83 Log(level LogLevel, offset int, format string, v ...interface{}) error 84} 85 86type defaultLogger struct { 87 Level LogLevel 88 GoLogger *log.Logger 89} 90 91func (l *defaultLogger) Log(level LogLevel, offset int, format string, v ...interface{}) error { 92 if level > l.Level { 93 return nil 94 } 95 s := fmt.Sprintf(format, v...) 96 return l.GoLogger.Output(offset+2, s) 97} 98 99var ( 100 globalDefaultLogger = defaultLogger{ 101 GoLogger: log.New(os.Stderr, "GOCB ", log.Lmicroseconds|log.Lshortfile), Level: LogDebug, 102 } 103 104 globalVerboseLogger = defaultLogger{ 105 GoLogger: globalDefaultLogger.GoLogger, Level: LogMaxVerbosity, 106 } 107 108 globalLogger Logger 109 globalLogRedactionLevel LogRedactLevel 110) 111 112// DefaultStdOutLogger gets the default logger. This actually logs to stderr 113// rather than stdout. Use DefaultStdioLogger which has a correct name, since 114// the "standard" logger logs to stderr, rather than stdout. 115// 116// Deprecated: Use DefaultStdioLogger() instead. 117func DefaultStdOutLogger() Logger { 118 return &globalDefaultLogger 119} 120 121// DefaultStdioLogger gets the default standard I/O logger. 122// gocbcore.SetLogger(gocbcore.DefaultStdioLogger()) 123func DefaultStdioLogger() Logger { 124 return &globalDefaultLogger 125} 126 127// VerboseStdioLogger is a more verbose level of DefaultStdioLogger(). Messages 128// pertaining to the scheduling of ordinary commands (and their responses) will 129// also be emitted. 130// gocbcore.SetLogger(gocbcore.VerboseStdioLogger()) 131func VerboseStdioLogger() Logger { 132 return &globalVerboseLogger 133} 134 135// SetLogger sets a logger to be used by the library. A logger can be obtained via 136// the DefaultStdioLogger() or VerboseStdioLogger() functions. You can also implement 137// your own logger using the Logger interface. 138func SetLogger(logger Logger) { 139 globalLogger = logger 140} 141 142func logExf(level LogLevel, offset int, format string, v ...interface{}) { 143 if globalLogger != nil { 144 err := globalLogger.Log(level, offset+1, format, v...) 145 if err != nil { 146 log.Printf("Logger error occurred (%s)\n", err) 147 } 148 } 149} 150 151func logDebugf(format string, v ...interface{}) { 152 logExf(LogDebug, 1, format, v...) 153} 154 155func logSchedf(format string, v ...interface{}) { 156 logExf(LogSched, 1, format, v...) 157} 158 159func logWarnf(format string, v ...interface{}) { 160 logExf(LogWarn, 1, format, v...) 161} 162 163func logErrorf(format string, v ...interface{}) { 164 logExf(LogError, 1, format, v...) 165} 166 167func reindentLog(indent, message string) string { 168 reindentedMessage := strings.Replace(message, "\n", "\n"+indent, -1) 169 return fmt.Sprintf("%s%s", indent, reindentedMessage) 170} 171