11 // Defines the key when adding errors using WithError.
12 var ErrorKey = "error"
14 // An entry is the final or intermediate Logrus logging entry. It contains all
15 // the fields passed with WithField{,s}. It's finally logged when Debug, Info,
16 // Warn, Error, Fatal or Panic is called on it. These objects can be reused and
17 // passed around as much as you wish to avoid field duplication.
21 // Contains all the fields set by the user.
24 // Time at which the log entry was created
27 // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
30 // Message passed to Debug, Info, Warn, Error, Fatal or Panic
34 func NewEntry(logger *Logger) *Entry {
37 // Default is three fields, give a little extra room
38 Data: make(Fields, 5),
42 // Returns a reader for the entry, which is a proxy to the formatter.
43 func (entry *Entry) Reader() (*bytes.Buffer, error) {
44 serialized, err := entry.Logger.Formatter.Format(entry)
45 return bytes.NewBuffer(serialized), err
48 // Returns the string representation from the reader and ultimately the
50 func (entry *Entry) String() (string, error) {
51 reader, err := entry.Reader()
56 return reader.String(), err
59 // Add an error as single field (using the key defined in ErrorKey) to the Entry.
60 func (entry *Entry) WithError(err error) *Entry {
61 return entry.WithField(ErrorKey, err)
64 // Add a single field to the Entry.
65 func (entry *Entry) WithField(key string, value interface{}) *Entry {
66 return entry.WithFields(Fields{key: value})
69 // Add a map of fields to the Entry.
70 func (entry *Entry) WithFields(fields Fields) *Entry {
72 for k, v := range entry.Data {
75 for k, v := range fields {
78 return &Entry{Logger: entry.Logger, Data: data}
81 // This function is not declared with a pointer value because otherwise
82 // race conditions will occur when using multiple goroutines
83 func (entry Entry) log(level Level, msg string) {
84 entry.Time = time.Now()
88 if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
89 entry.Logger.mu.Lock()
90 fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
91 entry.Logger.mu.Unlock()
94 reader, err := entry.Reader()
96 entry.Logger.mu.Lock()
97 fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
98 entry.Logger.mu.Unlock()
101 entry.Logger.mu.Lock()
102 defer entry.Logger.mu.Unlock()
104 _, err = io.Copy(entry.Logger.Out, reader)
106 fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
109 // To avoid Entry#log() returning a value that only would make sense for
110 // panic() to use in Entry#Panic(), we avoid the allocation by checking
112 if level <= PanicLevel {
117 func (entry *Entry) Debug(args ...interface{}) {
118 if entry.Logger.Level >= DebugLevel {
119 entry.log(DebugLevel, fmt.Sprint(args...))
123 func (entry *Entry) Print(args ...interface{}) {
127 func (entry *Entry) Info(args ...interface{}) {
128 if entry.Logger.Level >= InfoLevel {
129 entry.log(InfoLevel, fmt.Sprint(args...))
133 func (entry *Entry) Warn(args ...interface{}) {
134 if entry.Logger.Level >= WarnLevel {
135 entry.log(WarnLevel, fmt.Sprint(args...))
139 func (entry *Entry) Warning(args ...interface{}) {
143 func (entry *Entry) Error(args ...interface{}) {
144 if entry.Logger.Level >= ErrorLevel {
145 entry.log(ErrorLevel, fmt.Sprint(args...))
149 func (entry *Entry) Fatal(args ...interface{}) {
150 if entry.Logger.Level >= FatalLevel {
151 entry.log(FatalLevel, fmt.Sprint(args...))
156 func (entry *Entry) Panic(args ...interface{}) {
157 if entry.Logger.Level >= PanicLevel {
158 entry.log(PanicLevel, fmt.Sprint(args...))
160 panic(fmt.Sprint(args...))
163 // Entry Printf family functions
165 func (entry *Entry) Debugf(format string, args ...interface{}) {
166 if entry.Logger.Level >= DebugLevel {
167 entry.Debug(fmt.Sprintf(format, args...))
171 func (entry *Entry) Infof(format string, args ...interface{}) {
172 if entry.Logger.Level >= InfoLevel {
173 entry.Info(fmt.Sprintf(format, args...))
177 func (entry *Entry) Printf(format string, args ...interface{}) {
178 entry.Infof(format, args...)
181 func (entry *Entry) Warnf(format string, args ...interface{}) {
182 if entry.Logger.Level >= WarnLevel {
183 entry.Warn(fmt.Sprintf(format, args...))
187 func (entry *Entry) Warningf(format string, args ...interface{}) {
188 entry.Warnf(format, args...)
191 func (entry *Entry) Errorf(format string, args ...interface{}) {
192 if entry.Logger.Level >= ErrorLevel {
193 entry.Error(fmt.Sprintf(format, args...))
197 func (entry *Entry) Fatalf(format string, args ...interface{}) {
198 if entry.Logger.Level >= FatalLevel {
199 entry.Fatal(fmt.Sprintf(format, args...))
204 func (entry *Entry) Panicf(format string, args ...interface{}) {
205 if entry.Logger.Level >= PanicLevel {
206 entry.Panic(fmt.Sprintf(format, args...))
210 // Entry Println family functions
212 func (entry *Entry) Debugln(args ...interface{}) {
213 if entry.Logger.Level >= DebugLevel {
214 entry.Debug(entry.sprintlnn(args...))
218 func (entry *Entry) Infoln(args ...interface{}) {
219 if entry.Logger.Level >= InfoLevel {
220 entry.Info(entry.sprintlnn(args...))
224 func (entry *Entry) Println(args ...interface{}) {
225 entry.Infoln(args...)
228 func (entry *Entry) Warnln(args ...interface{}) {
229 if entry.Logger.Level >= WarnLevel {
230 entry.Warn(entry.sprintlnn(args...))
234 func (entry *Entry) Warningln(args ...interface{}) {
235 entry.Warnln(args...)
238 func (entry *Entry) Errorln(args ...interface{}) {
239 if entry.Logger.Level >= ErrorLevel {
240 entry.Error(entry.sprintlnn(args...))
244 func (entry *Entry) Fatalln(args ...interface{}) {
245 if entry.Logger.Level >= FatalLevel {
246 entry.Fatal(entry.sprintlnn(args...))
251 func (entry *Entry) Panicln(args ...interface{}) {
252 if entry.Logger.Level >= PanicLevel {
253 entry.Panic(entry.sprintlnn(args...))
257 // Sprintlnn => Sprint no newline. This is to get the behavior of how
258 // fmt.Sprintln where spaces are always added between operands, regardless of
259 // their type. Instead of vendoring the Sprintln implementation to spare a
260 // string allocation, we do the simplest thing.
261 func (entry *Entry) sprintlnn(args ...interface{}) string {
262 msg := fmt.Sprintln(args...)
263 return msg[:len(msg)-1]