David K. Bainbridge | 528b318 | 2017-01-23 08:51:59 -0800 | [diff] [blame] | 1 | // Copyright 2014 Canonical Ltd. |
| 2 | // Licensed under the LGPLv3, see LICENCE file for details. |
| 3 | |
| 4 | package loggo |
| 5 | |
| 6 | import ( |
| 7 | "fmt" |
| 8 | "runtime" |
| 9 | "time" |
| 10 | ) |
| 11 | |
| 12 | // A Logger represents a logging module. It has an associated logging |
| 13 | // level which can be changed; messages of lesser severity will |
| 14 | // be dropped. Loggers have a hierarchical relationship - see |
| 15 | // the package documentation. |
| 16 | // |
| 17 | // The zero Logger value is usable - any messages logged |
| 18 | // to it will be sent to the root Logger. |
| 19 | type Logger struct { |
| 20 | impl *module |
| 21 | } |
| 22 | |
| 23 | func (logger Logger) getModule() *module { |
| 24 | if logger.impl == nil { |
| 25 | return defaultContext.root |
| 26 | } |
| 27 | return logger.impl |
| 28 | } |
| 29 | |
| 30 | // Name returns the logger's module name. |
| 31 | func (logger Logger) Name() string { |
| 32 | return logger.getModule().Name() |
| 33 | } |
| 34 | |
| 35 | // LogLevel returns the configured min log level of the logger. |
| 36 | func (logger Logger) LogLevel() Level { |
| 37 | return logger.getModule().level |
| 38 | } |
| 39 | |
| 40 | // EffectiveLogLevel returns the effective min log level of |
| 41 | // the receiver - that is, messages with a lesser severity |
| 42 | // level will be discarded. |
| 43 | // |
| 44 | // If the log level of the receiver is unspecified, |
| 45 | // it will be taken from the effective log level of its |
| 46 | // parent. |
| 47 | func (logger Logger) EffectiveLogLevel() Level { |
| 48 | return logger.getModule().getEffectiveLogLevel() |
| 49 | } |
| 50 | |
| 51 | // SetLogLevel sets the severity level of the given logger. |
| 52 | // The root logger cannot be set to UNSPECIFIED level. |
| 53 | // See EffectiveLogLevel for how this affects the |
| 54 | // actual messages logged. |
| 55 | func (logger Logger) SetLogLevel(level Level) { |
| 56 | logger.getModule().setLevel(level) |
| 57 | } |
| 58 | |
| 59 | // Logf logs a printf-formatted message at the given level. |
| 60 | // A message will be discarded if level is less than the |
| 61 | // the effective log level of the logger. |
| 62 | // Note that the writers may also filter out messages that |
| 63 | // are less than their registered minimum severity level. |
| 64 | func (logger Logger) Logf(level Level, message string, args ...interface{}) { |
| 65 | logger.LogCallf(2, level, message, args...) |
| 66 | } |
| 67 | |
| 68 | // LogCallf logs a printf-formatted message at the given level. |
| 69 | // The location of the call is indicated by the calldepth argument. |
| 70 | // A calldepth of 1 means the function that called this function. |
| 71 | // A message will be discarded if level is less than the |
| 72 | // the effective log level of the logger. |
| 73 | // Note that the writers may also filter out messages that |
| 74 | // are less than their registered minimum severity level. |
| 75 | func (logger Logger) LogCallf(calldepth int, level Level, message string, args ...interface{}) { |
| 76 | module := logger.getModule() |
| 77 | if !module.willWrite(level) { |
| 78 | return |
| 79 | } |
| 80 | // Gather time, and filename, line number. |
| 81 | now := time.Now() // get this early. |
| 82 | // Param to Caller is the call depth. Since this method is called from |
| 83 | // the Logger methods, we want the place that those were called from. |
| 84 | _, file, line, ok := runtime.Caller(calldepth + 1) |
| 85 | if !ok { |
| 86 | file = "???" |
| 87 | line = 0 |
| 88 | } |
| 89 | // Trim newline off format string, following usual |
| 90 | // Go logging conventions. |
| 91 | if len(message) > 0 && message[len(message)-1] == '\n' { |
| 92 | message = message[0 : len(message)-1] |
| 93 | } |
| 94 | |
| 95 | // To avoid having a proliferation of Info/Infof methods, |
| 96 | // only use Sprintf if there are any args, and rely on the |
| 97 | // `go vet` tool for the obvious cases where someone has forgotten |
| 98 | // to provide an arg. |
| 99 | formattedMessage := message |
| 100 | if len(args) > 0 { |
| 101 | formattedMessage = fmt.Sprintf(message, args...) |
| 102 | } |
| 103 | module.write(Entry{ |
| 104 | Level: level, |
| 105 | Filename: file, |
| 106 | Line: line, |
| 107 | Timestamp: now, |
| 108 | Message: formattedMessage, |
| 109 | }) |
| 110 | } |
| 111 | |
| 112 | // Criticalf logs the printf-formatted message at critical level. |
| 113 | func (logger Logger) Criticalf(message string, args ...interface{}) { |
| 114 | logger.Logf(CRITICAL, message, args...) |
| 115 | } |
| 116 | |
| 117 | // Errorf logs the printf-formatted message at error level. |
| 118 | func (logger Logger) Errorf(message string, args ...interface{}) { |
| 119 | logger.Logf(ERROR, message, args...) |
| 120 | } |
| 121 | |
| 122 | // Warningf logs the printf-formatted message at warning level. |
| 123 | func (logger Logger) Warningf(message string, args ...interface{}) { |
| 124 | logger.Logf(WARNING, message, args...) |
| 125 | } |
| 126 | |
| 127 | // Infof logs the printf-formatted message at info level. |
| 128 | func (logger Logger) Infof(message string, args ...interface{}) { |
| 129 | logger.Logf(INFO, message, args...) |
| 130 | } |
| 131 | |
| 132 | // Debugf logs the printf-formatted message at debug level. |
| 133 | func (logger Logger) Debugf(message string, args ...interface{}) { |
| 134 | logger.Logf(DEBUG, message, args...) |
| 135 | } |
| 136 | |
| 137 | // Tracef logs the printf-formatted message at trace level. |
| 138 | func (logger Logger) Tracef(message string, args ...interface{}) { |
| 139 | logger.Logf(TRACE, message, args...) |
| 140 | } |
| 141 | |
| 142 | // IsLevelEnabled returns whether debugging is enabled |
| 143 | // for the given log level. |
| 144 | func (logger Logger) IsLevelEnabled(level Level) bool { |
| 145 | return logger.getModule().willWrite(level) |
| 146 | } |
| 147 | |
| 148 | // IsErrorEnabled returns whether debugging is enabled |
| 149 | // at error level. |
| 150 | func (logger Logger) IsErrorEnabled() bool { |
| 151 | return logger.IsLevelEnabled(ERROR) |
| 152 | } |
| 153 | |
| 154 | // IsWarningEnabled returns whether debugging is enabled |
| 155 | // at warning level. |
| 156 | func (logger Logger) IsWarningEnabled() bool { |
| 157 | return logger.IsLevelEnabled(WARNING) |
| 158 | } |
| 159 | |
| 160 | // IsInfoEnabled returns whether debugging is enabled |
| 161 | // at info level. |
| 162 | func (logger Logger) IsInfoEnabled() bool { |
| 163 | return logger.IsLevelEnabled(INFO) |
| 164 | } |
| 165 | |
| 166 | // IsDebugEnabled returns whether debugging is enabled |
| 167 | // at debug level. |
| 168 | func (logger Logger) IsDebugEnabled() bool { |
| 169 | return logger.IsLevelEnabled(DEBUG) |
| 170 | } |
| 171 | |
| 172 | // IsTraceEnabled returns whether debugging is enabled |
| 173 | // at trace level. |
| 174 | func (logger Logger) IsTraceEnabled() bool { |
| 175 | return logger.IsLevelEnabled(TRACE) |
| 176 | } |