1package hclog 2 3import ( 4 "io" 5 "log" 6 "os" 7 "strings" 8 "sync" 9) 10 11var ( 12 //DefaultOutput is used as the default log output. 13 DefaultOutput io.Writer = os.Stderr 14 15 // DefaultLevel is used as the default log level. 16 DefaultLevel = Info 17) 18 19// Level represents a log level. 20type Level int32 21 22const ( 23 // NoLevel is a special level used to indicate that no level has been 24 // set and allow for a default to be used. 25 NoLevel Level = 0 26 27 // Trace is the most verbose level. Intended to be used for the tracing 28 // of actions in code, such as function enters/exits, etc. 29 Trace Level = 1 30 31 // Debug information for programmer lowlevel analysis. 32 Debug Level = 2 33 34 // Info information about steady state operations. 35 Info Level = 3 36 37 // Warn information about rare but handled events. 38 Warn Level = 4 39 40 // Error information about unrecoverable events. 41 Error Level = 5 42) 43 44// Format is a simple convience type for when formatting is required. When 45// processing a value of this type, the logger automatically treats the first 46// argument as a Printf formatting string and passes the rest as the values 47// to be formatted. For example: L.Info(Fmt{"%d beans/day", beans}). 48type Format []interface{} 49 50// Fmt returns a Format type. This is a convience function for creating a Format 51// type. 52func Fmt(str string, args ...interface{}) Format { 53 return append(Format{str}, args...) 54} 55 56// LevelFromString returns a Level type for the named log level, or "NoLevel" if 57// the level string is invalid. This facilitates setting the log level via 58// config or environment variable by name in a predictable way. 59func LevelFromString(levelStr string) Level { 60 // We don't care about case. Accept both "INFO" and "info". 61 levelStr = strings.ToLower(strings.TrimSpace(levelStr)) 62 switch levelStr { 63 case "trace": 64 return Trace 65 case "debug": 66 return Debug 67 case "info": 68 return Info 69 case "warn": 70 return Warn 71 case "error": 72 return Error 73 default: 74 return NoLevel 75 } 76} 77 78// Logger describes the interface that must be implemeted by all loggers. 79type Logger interface { 80 // Args are alternating key, val pairs 81 // keys must be strings 82 // vals can be any type, but display is implementation specific 83 // Emit a message and key/value pairs at the TRACE level 84 Trace(msg string, args ...interface{}) 85 86 // Emit a message and key/value pairs at the DEBUG level 87 Debug(msg string, args ...interface{}) 88 89 // Emit a message and key/value pairs at the INFO level 90 Info(msg string, args ...interface{}) 91 92 // Emit a message and key/value pairs at the WARN level 93 Warn(msg string, args ...interface{}) 94 95 // Emit a message and key/value pairs at the ERROR level 96 Error(msg string, args ...interface{}) 97 98 // Indicate if TRACE logs would be emitted. This and the other Is* guards 99 // are used to elide expensive logging code based on the current level. 100 IsTrace() bool 101 102 // Indicate if DEBUG logs would be emitted. This and the other Is* guards 103 IsDebug() bool 104 105 // Indicate if INFO logs would be emitted. This and the other Is* guards 106 IsInfo() bool 107 108 // Indicate if WARN logs would be emitted. This and the other Is* guards 109 IsWarn() bool 110 111 // Indicate if ERROR logs would be emitted. This and the other Is* guards 112 IsError() bool 113 114 // Creates a sublogger that will always have the given key/value pairs 115 With(args ...interface{}) Logger 116 117 // Create a logger that will prepend the name string on the front of all messages. 118 // If the logger already has a name, the new value will be appended to the current 119 // name. That way, a major subsystem can use this to decorate all it's own logs 120 // without losing context. 121 Named(name string) Logger 122 123 // Create a logger that will prepend the name string on the front of all messages. 124 // This sets the name of the logger to the value directly, unlike Named which honor 125 // the current name as well. 126 ResetNamed(name string) Logger 127 128 // Updates the level. This should affect all sub-loggers as well. If an 129 // implementation cannot update the level on the fly, it should no-op. 130 SetLevel(level Level) 131 132 // Return a value that conforms to the stdlib log.Logger interface 133 StandardLogger(opts *StandardLoggerOptions) *log.Logger 134 135 // Return a value that conforms to io.Writer, which can be passed into log.SetOutput() 136 StandardWriter(opts *StandardLoggerOptions) io.Writer 137} 138 139// StandardLoggerOptions can be used to configure a new standard logger. 140type StandardLoggerOptions struct { 141 // Indicate that some minimal parsing should be done on strings to try 142 // and detect their level and re-emit them. 143 // This supports the strings like [ERROR], [ERR] [TRACE], [WARN], [INFO], 144 // [DEBUG] and strip it off before reapplying it. 145 InferLevels bool 146 147 // ForceLevel is used to force all output from the standard logger to be at 148 // the specified level. Similar to InferLevels, this will strip any level 149 // prefix contained in the logged string before applying the forced level. 150 // If set, this override InferLevels. 151 ForceLevel Level 152} 153 154// LoggerOptions can be used to configure a new logger. 155type LoggerOptions struct { 156 // Name of the subsystem to prefix logs with 157 Name string 158 159 // The threshold for the logger. Anything less severe is supressed 160 Level Level 161 162 // Where to write the logs to. Defaults to os.Stderr if nil 163 Output io.Writer 164 165 // An optional mutex pointer in case Output is shared 166 Mutex *sync.Mutex 167 168 // Control if the output should be in JSON. 169 JSONFormat bool 170 171 // Include file and line information in each log line 172 IncludeLocation bool 173 174 // The time format to use instead of the default 175 TimeFormat string 176} 177