Browse code

bump logrus

Signed-off-by: Jessica Frazelle <acidburn@docker.com>

Jessica Frazelle authored on 2016/01/21 02:47:41
Showing 15 changed files
... ...
@@ -7,7 +7,7 @@ source 'hack/.vendor-helpers.sh'
7 7
 
8 8
 # the following lines are in sorted order, FYI
9 9
 clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe
10
-clone git github.com/Sirupsen/logrus v0.8.2 # logrus is a common dependency among multiple deps
10
+clone git github.com/Sirupsen/logrus v0.8.7 # logrus is a common dependency among multiple deps
11 11
 clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
12 12
 clone git github.com/go-check/check 11d3bc7aa68e238947792f30573146a3231fc0f1
13 13
 clone git github.com/gorilla/context 14f550f51a
... ...
@@ -1,21 +1,47 @@
1
+# 0.8.7
2
+
3
+* logrus/core: fix possible race (#216)
4
+* logrus/doc: small typo fixes and doc improvements
5
+
6
+
7
+# 0.8.6
8
+
9
+* hooks/raven: allow passing an initialized client
10
+
11
+# 0.8.5
12
+
13
+* logrus/core: revert #208
14
+
15
+# 0.8.4
16
+
17
+* formatter/text: fix data race (#218)
18
+
19
+# 0.8.3
20
+
21
+* logrus/core: fix entry log level (#208)
22
+* logrus/core: improve performance of text formatter by 40%
23
+* logrus/core: expose `LevelHooks` type
24
+* logrus/core: add support for DragonflyBSD and NetBSD
25
+* formatter/text: print structs more verbosely
26
+
1 27
 # 0.8.2
2 28
 
3
-logrus: fix more Fatal family functions
29
+* logrus: fix more Fatal family functions
4 30
 
5 31
 # 0.8.1
6 32
 
7
-logrus: fix not exiting on `Fatalf` and `Fatalln`
33
+* logrus: fix not exiting on `Fatalf` and `Fatalln`
8 34
 
9 35
 # 0.8.0
10 36
 
11
-logrus: defaults to stderr instead of stdout
12
-hooks/sentry: add special field for `*http.Request`
13
-formatter/text: ignore Windows for colors
37
+* logrus: defaults to stderr instead of stdout
38
+* hooks/sentry: add special field for `*http.Request`
39
+* formatter/text: ignore Windows for colors
14 40
 
15 41
 # 0.7.3
16 42
 
17
-formatter/\*: allow configuration of timestamp layout
43
+* formatter/\*: allow configuration of timestamp layout
18 44
 
19 45
 # 0.7.2
20 46
 
21
-formatter/text: Add configuration option for time format (#158)
47
+* formatter/text: Add configuration option for time format (#158)
... ...
@@ -183,7 +183,7 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
183 183
 import (
184 184
   log "github.com/Sirupsen/logrus"
185 185
   "github.com/Sirupsen/logrus/hooks/airbrake"
186
-  "github.com/Sirupsen/logrus/hooks/syslog"
186
+  logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
187 187
   "log/syslog"
188 188
 )
189 189
 
... ...
@@ -206,12 +206,19 @@ func init() {
206 206
 | [Papertrail](https://github.com/Sirupsen/logrus/blob/master/hooks/papertrail/papertrail.go) | Send errors to the Papertrail hosted logging service via UDP. |
207 207
 | [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
208 208
 | [BugSnag](https://github.com/Sirupsen/logrus/blob/master/hooks/bugsnag/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
209
+| [Sentry](https://github.com/Sirupsen/logrus/blob/master/hooks/sentry/sentry.go) | Send errors to the Sentry error logging and aggregation service. |
209 210
 | [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
210 211
 | [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
211 212
 | [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
212 213
 | [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
213 214
 | [Graylog](https://github.com/gemnasium/logrus-hooks/tree/master/graylog) | Hook for logging to [Graylog](http://graylog2.org/) |
214 215
 | [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
216
+| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
217
+| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
218
+| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
219
+| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
220
+| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
221
+| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
215 222
 
216 223
 #### Level logging
217 224
 
... ...
@@ -267,7 +274,7 @@ init() {
267 267
   // do something here to set environment depending on an environment variable
268 268
   // or command-line flag
269 269
   if Environment == "production" {
270
-    log.SetFormatter(logrus.JSONFormatter)
270
+    log.SetFormatter(&log.JSONFormatter{})
271 271
   } else {
272 272
     // The TextFormatter is default, you don't actually have to do this.
273 273
     log.SetFormatter(&log.TextFormatter{})
... ...
@@ -310,7 +317,7 @@ type MyJSONFormatter struct {
310 310
 
311 311
 log.SetFormatter(new(MyJSONFormatter))
312 312
 
313
-func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
313
+func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
314 314
   // Note this doesn't include Time, Level and Message which are available on
315 315
   // the Entry. Consult `godoc` on information about those fields or read the
316 316
   // source of the official loggers.
... ...
@@ -324,7 +331,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
324 324
 
325 325
 #### Logger as an `io.Writer`
326 326
 
327
-Logrus can be transormed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it.
327
+Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it.
328 328
 
329 329
 ```go
330 330
 w := logger.Writer()
331 331
new file mode 100644
... ...
@@ -0,0 +1,26 @@
0
+/*
1
+Package logrus is a structured logger for Go, completely API compatible with the standard library logger.
2
+
3
+
4
+The simplest way to use Logrus is simply the package-level exported logger:
5
+
6
+  package main
7
+
8
+  import (
9
+    log "github.com/Sirupsen/logrus"
10
+  )
11
+
12
+  func main() {
13
+    log.WithFields(log.Fields{
14
+      "animal": "walrus",
15
+      "number": 1,
16
+      "size":   10,
17
+    }).Info("A walrus appears")
18
+  }
19
+
20
+Output:
21
+  time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
22
+
23
+For a full guide visit https://github.com/Sirupsen/logrus
24
+*/
25
+package logrus
... ...
@@ -8,6 +8,9 @@ import (
8 8
 	"time"
9 9
 )
10 10
 
11
+// Defines the key when adding errors using WithError.
12
+var ErrorKey = "error"
13
+
11 14
 // An entry is the final or intermediate Logrus logging entry. It contains all
12 15
 // the fields passed with WithField{,s}. It's finally logged when Debug, Info,
13 16
 // Warn, Error, Fatal or Panic is called on it. These objects can be reused and
... ...
@@ -53,6 +56,11 @@ func (entry *Entry) String() (string, error) {
53 53
 	return reader.String(), err
54 54
 }
55 55
 
56
+// Add an error as single field (using the key defined in ErrorKey) to the Entry.
57
+func (entry *Entry) WithError(err error) *Entry {
58
+	return entry.WithField(ErrorKey, err)
59
+}
60
+
56 61
 // Add a single field to the Entry.
57 62
 func (entry *Entry) WithField(key string, value interface{}) *Entry {
58 63
 	return entry.WithFields(Fields{key: value})
... ...
@@ -70,12 +78,14 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
70 70
 	return &Entry{Logger: entry.Logger, Data: data}
71 71
 }
72 72
 
73
-func (entry *Entry) log(level Level, msg string) {
73
+// This function is not declared with a pointer value because otherwise
74
+// race conditions will occur when using multiple goroutines
75
+func (entry Entry) log(level Level, msg string) {
74 76
 	entry.Time = time.Now()
75 77
 	entry.Level = level
76 78
 	entry.Message = msg
77 79
 
78
-	if err := entry.Logger.Hooks.Fire(level, entry); err != nil {
80
+	if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
79 81
 		entry.Logger.mu.Lock()
80 82
 		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
81 83
 		entry.Logger.mu.Unlock()
... ...
@@ -100,7 +110,7 @@ func (entry *Entry) log(level Level, msg string) {
100 100
 	// panic() to use in Entry#Panic(), we avoid the allocation by checking
101 101
 	// directly here.
102 102
 	if level <= PanicLevel {
103
-		panic(entry)
103
+		panic(&entry)
104 104
 	}
105 105
 }
106 106
 
... ...
@@ -48,6 +48,11 @@ func AddHook(hook Hook) {
48 48
 	std.Hooks.Add(hook)
49 49
 }
50 50
 
51
+// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
52
+func WithError(err error) *Entry {
53
+	return std.WithField(ErrorKey, err)
54
+}
55
+
51 56
 // WithField creates an entry from the standard logger and adds a field to
52 57
 // it. If you want multiple fields, use `WithFields`.
53 58
 //
... ...
@@ -11,11 +11,11 @@ type Hook interface {
11 11
 }
12 12
 
13 13
 // Internal type for storing the hooks on a logger instance.
14
-type levelHooks map[Level][]Hook
14
+type LevelHooks map[Level][]Hook
15 15
 
16 16
 // Add a hook to an instance of logger. This is called with
17 17
 // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
18
-func (hooks levelHooks) Add(hook Hook) {
18
+func (hooks LevelHooks) Add(hook Hook) {
19 19
 	for _, level := range hook.Levels() {
20 20
 		hooks[level] = append(hooks[level], hook)
21 21
 	}
... ...
@@ -23,7 +23,7 @@ func (hooks levelHooks) Add(hook Hook) {
23 23
 
24 24
 // Fire all the hooks for the passed level. Used by `entry.log` to fire
25 25
 // appropriate hooks for a log entry.
26
-func (hooks levelHooks) Fire(level Level, entry *Entry) error {
26
+func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
27 27
 	for _, hook := range hooks[level] {
28 28
 		if err := hook.Fire(entry); err != nil {
29 29
 			return err
... ...
@@ -8,13 +8,13 @@ import (
8 8
 
9 9
 type Logger struct {
10 10
 	// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
11
-	// file, or leave it default which is `os.Stdout`. You can also set this to
11
+	// file, or leave it default which is `os.Stderr`. You can also set this to
12 12
 	// something more adventorous, such as logging to Kafka.
13 13
 	Out io.Writer
14 14
 	// Hooks for the logger instance. These allow firing events based on logging
15 15
 	// levels and log entries. For example, to send errors to an error tracking
16 16
 	// service, log to StatsD or dump the core on fatal errors.
17
-	Hooks levelHooks
17
+	Hooks LevelHooks
18 18
 	// All log entries pass through the formatter before logged to Out. The
19 19
 	// included formatters are `TextFormatter` and `JSONFormatter` for which
20 20
 	// TextFormatter is the default. In development (when a TTY is attached) it
... ...
@@ -37,7 +37,7 @@ type Logger struct {
37 37
 //    var log = &Logger{
38 38
 //      Out: os.Stderr,
39 39
 //      Formatter: new(JSONFormatter),
40
-//      Hooks: make(levelHooks),
40
+//      Hooks: make(LevelHooks),
41 41
 //      Level: logrus.DebugLevel,
42 42
 //    }
43 43
 //
... ...
@@ -46,14 +46,14 @@ func New() *Logger {
46 46
 	return &Logger{
47 47
 		Out:       os.Stderr,
48 48
 		Formatter: new(TextFormatter),
49
-		Hooks:     make(levelHooks),
49
+		Hooks:     make(LevelHooks),
50 50
 		Level:     InfoLevel,
51 51
 	}
52 52
 }
53 53
 
54 54
 // Adds a field to the log entry, note that you it doesn't log until you call
55 55
 // Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
56
-// Ff you want multiple fields, use `WithFields`.
56
+// If you want multiple fields, use `WithFields`.
57 57
 func (logger *Logger) WithField(key string, value interface{}) *Entry {
58 58
 	return NewEntry(logger).WithField(key, value)
59 59
 }
... ...
@@ -74,7 +74,11 @@ const (
74 74
 )
75 75
 
76 76
 // Won't compile if StdLogger can't be realized by a log.Logger
77
-var _ StdLogger = &log.Logger{}
77
+var (
78
+	_ StdLogger = &log.Logger{}
79
+	_ StdLogger = &Entry{}
80
+	_ StdLogger = &Logger{}
81
+)
78 82
 
79 83
 // StdLogger is what your logrus-enabled library should take, that way
80 84
 // it'll accept a stdlib logger and a logrus logger. There's no standard
81 85
new file mode 100644
... ...
@@ -0,0 +1,9 @@
0
+// +build darwin freebsd openbsd netbsd dragonfly
1
+
2
+package logrus
3
+
4
+import "syscall"
5
+
6
+const ioctlReadTermios = syscall.TIOCGETA
7
+
8
+type Termios syscall.Termios
0 9
deleted file mode 100644
... ...
@@ -1,12 +0,0 @@
1
-// Based on ssh/terminal:
2
-// Copyright 2013 The Go Authors. All rights reserved.
3
-// Use of this source code is governed by a BSD-style
4
-// license that can be found in the LICENSE file.
5
-
6
-package logrus
7
-
8
-import "syscall"
9
-
10
-const ioctlReadTermios = syscall.TIOCGETA
11
-
12
-type Termios syscall.Termios
13 1
deleted file mode 100644
... ...
@@ -1,20 +0,0 @@
1
-/*
2
-  Go 1.2 doesn't include Termios for FreeBSD. This should be added in 1.3 and this could be merged with terminal_darwin.
3
-*/
4
-package logrus
5
-
6
-import (
7
-	"syscall"
8
-)
9
-
10
-const ioctlReadTermios = syscall.TIOCGETA
11
-
12
-type Termios struct {
13
-	Iflag  uint32
14
-	Oflag  uint32
15
-	Cflag  uint32
16
-	Lflag  uint32
17
-	Cc     [20]uint8
18
-	Ispeed uint32
19
-	Ospeed uint32
20
-}
... ...
@@ -3,7 +3,7 @@
3 3
 // Use of this source code is governed by a BSD-style
4 4
 // license that can be found in the LICENSE file.
5 5
 
6
-// +build linux darwin freebsd openbsd
6
+// +build linux darwin freebsd openbsd netbsd dragonfly
7 7
 
8 8
 package logrus
9 9
 
10 10
deleted file mode 100644
... ...
@@ -1,7 +0,0 @@
1
-package logrus
2
-
3
-import "syscall"
4
-
5
-const ioctlReadTermios = syscall.TIOCGETA
6
-
7
-type Termios syscall.Termios
... ...
@@ -73,14 +73,15 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
73 73
 	isColorTerminal := isTerminal && (runtime.GOOS != "windows")
74 74
 	isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors
75 75
 
76
-	if f.TimestampFormat == "" {
77
-		f.TimestampFormat = DefaultTimestampFormat
76
+	timestampFormat := f.TimestampFormat
77
+	if timestampFormat == "" {
78
+		timestampFormat = DefaultTimestampFormat
78 79
 	}
79 80
 	if isColored {
80
-		f.printColored(b, entry, keys)
81
+		f.printColored(b, entry, keys, timestampFormat)
81 82
 	} else {
82 83
 		if !f.DisableTimestamp {
83
-			f.appendKeyValue(b, "time", entry.Time.Format(f.TimestampFormat))
84
+			f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
84 85
 		}
85 86
 		f.appendKeyValue(b, "level", entry.Level.String())
86 87
 		f.appendKeyValue(b, "msg", entry.Message)
... ...
@@ -93,7 +94,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
93 93
 	return b.Bytes(), nil
94 94
 }
95 95
 
96
-func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string) {
96
+func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
97 97
 	var levelColor int
98 98
 	switch entry.Level {
99 99
 	case DebugLevel:
... ...
@@ -111,11 +112,11 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
111 111
 	if !f.FullTimestamp {
112 112
 		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
113 113
 	} else {
114
-		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(f.TimestampFormat), entry.Message)
114
+		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
115 115
 	}
116 116
 	for _, k := range keys {
117 117
 		v := entry.Data[k]
118
-		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
118
+		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
119 119
 	}
120 120
 }
121 121
 
... ...
@@ -131,21 +132,28 @@ func needsQuoting(text string) bool {
131 131
 	return true
132 132
 }
133 133
 
134
-func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
135
-	switch value.(type) {
134
+func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
135
+
136
+	b.WriteString(key)
137
+	b.WriteByte('=')
138
+
139
+	switch value := value.(type) {
136 140
 	case string:
137
-		if needsQuoting(value.(string)) {
138
-			fmt.Fprintf(b, "%v=%s ", key, value)
141
+		if needsQuoting(value) {
142
+			b.WriteString(value)
139 143
 		} else {
140
-			fmt.Fprintf(b, "%v=%q ", key, value)
144
+			fmt.Fprintf(b, "%q", value)
141 145
 		}
142 146
 	case error:
143
-		if needsQuoting(value.(error).Error()) {
144
-			fmt.Fprintf(b, "%v=%s ", key, value)
147
+		errmsg := value.Error()
148
+		if needsQuoting(errmsg) {
149
+			b.WriteString(errmsg)
145 150
 		} else {
146
-			fmt.Fprintf(b, "%v=%q ", key, value)
151
+			fmt.Fprintf(b, "%q", value)
147 152
 		}
148 153
 	default:
149
-		fmt.Fprintf(b, "%v=%v ", key, value)
154
+		fmt.Fprint(b, value)
150 155
 	}
156
+
157
+	b.WriteByte(' ')
151 158
 }