mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Merge pull request #11331 from jfrazelle/update-logrus
Update logrus to 0.6.6
This commit is contained in:
		
						commit
						5494432f91
					
				
					 26 changed files with 758 additions and 66 deletions
				
			
		| 
						 | 
					@ -5042,8 +5042,8 @@ func TestBuildSpaces(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Skip over the times
 | 
						// Skip over the times
 | 
				
			||||||
	e1 := err1.Error()[strings.Index(err1.Error(), `level="`):]
 | 
						e1 := err1.Error()[strings.Index(err1.Error(), `level=`):]
 | 
				
			||||||
	e2 := err2.Error()[strings.Index(err1.Error(), `level="`):]
 | 
						e2 := err2.Error()[strings.Index(err1.Error(), `level=`):]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ignore whitespace since that's what were verifying doesn't change stuff
 | 
						// Ignore whitespace since that's what were verifying doesn't change stuff
 | 
				
			||||||
	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
 | 
						if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
 | 
				
			||||||
| 
						 | 
					@ -5056,8 +5056,8 @@ func TestBuildSpaces(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Skip over the times
 | 
						// Skip over the times
 | 
				
			||||||
	e1 = err1.Error()[strings.Index(err1.Error(), `level="`):]
 | 
						e1 = err1.Error()[strings.Index(err1.Error(), `level=`):]
 | 
				
			||||||
	e2 = err2.Error()[strings.Index(err1.Error(), `level="`):]
 | 
						e2 = err2.Error()[strings.Index(err1.Error(), `level=`):]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ignore whitespace since that's what were verifying doesn't change stuff
 | 
						// Ignore whitespace since that's what were verifying doesn't change stuff
 | 
				
			||||||
	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
 | 
						if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
 | 
				
			||||||
| 
						 | 
					@ -5070,8 +5070,8 @@ func TestBuildSpaces(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Skip over the times
 | 
						// Skip over the times
 | 
				
			||||||
	e1 = err1.Error()[strings.Index(err1.Error(), `level="`):]
 | 
						e1 = err1.Error()[strings.Index(err1.Error(), `level=`):]
 | 
				
			||||||
	e2 = err2.Error()[strings.Index(err1.Error(), `level="`):]
 | 
						e2 = err2.Error()[strings.Index(err1.Error(), `level=`):]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ignore whitespace since that's what were verifying doesn't change stuff
 | 
						// Ignore whitespace since that's what were verifying doesn't change stuff
 | 
				
			||||||
	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
 | 
						if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -244,7 +244,7 @@ func TestDaemonLoggingLevel(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	d.Stop()
 | 
						d.Stop()
 | 
				
			||||||
	content, _ := ioutil.ReadFile(d.logFile.Name())
 | 
						content, _ := ioutil.ReadFile(d.logFile.Name())
 | 
				
			||||||
	if !strings.Contains(string(content), `level="debug"`) {
 | 
						if !strings.Contains(string(content), `level=debug`) {
 | 
				
			||||||
		t.Fatalf(`Missing level="debug" in log file:\n%s`, string(content))
 | 
							t.Fatalf(`Missing level="debug" in log file:\n%s`, string(content))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,7 +254,7 @@ func TestDaemonLoggingLevel(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	d.Stop()
 | 
						d.Stop()
 | 
				
			||||||
	content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
						content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
				
			||||||
	if strings.Contains(string(content), `level="debug"`) {
 | 
						if strings.Contains(string(content), `level=debug`) {
 | 
				
			||||||
		t.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content))
 | 
							t.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,7 +264,7 @@ func TestDaemonLoggingLevel(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	d.Stop()
 | 
						d.Stop()
 | 
				
			||||||
	content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
						content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
				
			||||||
	if !strings.Contains(string(content), `level="debug"`) {
 | 
						if !strings.Contains(string(content), `level=debug`) {
 | 
				
			||||||
		t.Fatalf(`Missing level="debug" in log file using -D:\n%s`, string(content))
 | 
							t.Fatalf(`Missing level="debug" in log file using -D:\n%s`, string(content))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -274,7 +274,7 @@ func TestDaemonLoggingLevel(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	d.Stop()
 | 
						d.Stop()
 | 
				
			||||||
	content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
						content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
				
			||||||
	if !strings.Contains(string(content), `level="debug"`) {
 | 
						if !strings.Contains(string(content), `level=debug`) {
 | 
				
			||||||
		t.Fatalf(`Missing level="debug" in log file using --debug:\n%s`, string(content))
 | 
							t.Fatalf(`Missing level="debug" in log file using --debug:\n%s`, string(content))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -284,7 +284,7 @@ func TestDaemonLoggingLevel(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	d.Stop()
 | 
						d.Stop()
 | 
				
			||||||
	content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
						content, _ = ioutil.ReadFile(d.logFile.Name())
 | 
				
			||||||
	if !strings.Contains(string(content), `level="debug"`) {
 | 
						if !strings.Contains(string(content), `level=debug`) {
 | 
				
			||||||
		t.Fatalf(`Missing level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content))
 | 
							t.Fatalf(`Missing level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ clone hg code.google.com/p/gosqlite 74691fb6f837
 | 
				
			||||||
 | 
					
 | 
				
			||||||
clone git github.com/docker/libtrust 230dfd18c232
 | 
					clone git github.com/docker/libtrust 230dfd18c232
 | 
				
			||||||
 | 
					
 | 
				
			||||||
clone git github.com/Sirupsen/logrus v0.6.0
 | 
					clone git github.com/Sirupsen/logrus v0.6.6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
clone git github.com/go-fsnotify/fsnotify v1.0.4
 | 
					clone git github.com/go-fsnotify/fsnotify v1.0.4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,5 +71,5 @@ fi
 | 
				
			||||||
clone git github.com/docker/libcontainer aa10040b570386c1ae311c6245b9e21295b2b83a
 | 
					clone git github.com/docker/libcontainer aa10040b570386c1ae311c6245b9e21295b2b83a
 | 
				
			||||||
# see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file)
 | 
					# see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file)
 | 
				
			||||||
rm -rf src/github.com/docker/libcontainer/vendor
 | 
					rm -rf src/github.com/docker/libcontainer/vendor
 | 
				
			||||||
eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli')"
 | 
					eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli' | grep -v 'github.com/Sirupsen/logrus')"
 | 
				
			||||||
# we exclude "github.com/codegangsta/cli" here because it's only needed for "nsinit", which Docker doesn't include
 | 
					# we exclude "github.com/codegangsta/cli" here because it's only needed for "nsinit", which Docker doesn't include
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,8 +2,7 @@ language: go
 | 
				
			||||||
go:
 | 
					go:
 | 
				
			||||||
  - 1.2
 | 
					  - 1.2
 | 
				
			||||||
  - 1.3
 | 
					  - 1.3
 | 
				
			||||||
 | 
					  - 1.4
 | 
				
			||||||
  - tip
 | 
					  - tip
 | 
				
			||||||
install:
 | 
					install:
 | 
				
			||||||
  - go get github.com/stretchr/testify
 | 
					  - go get -t ./...
 | 
				
			||||||
  - go get github.com/stvp/go-udp-testing
 | 
					 | 
				
			||||||
  - go get github.com/tobi/airbrake-go
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										51
									
								
								vendor/src/github.com/Sirupsen/logrus/README.md
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								vendor/src/github.com/Sirupsen/logrus/README.md
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1,10 +1,11 @@
 | 
				
			||||||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [](https://travis-ci.org/Sirupsen/logrus)
 | 
					# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [](https://travis-ci.org/Sirupsen/logrus) [][godoc]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Logrus is a structured logger for Go (golang), completely API compatible with
 | 
					Logrus is a structured logger for Go (golang), completely API compatible with
 | 
				
			||||||
the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
 | 
					the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
 | 
				
			||||||
yet stable (pre 1.0), the core API is unlikely change much but please version
 | 
					yet stable (pre 1.0). Logrus itself is completely stable and has been used in
 | 
				
			||||||
control your Logrus to make sure you aren't fetching latest `master` on every
 | 
					many large deployments. The core API is unlikely to change much but please
 | 
				
			||||||
build.**
 | 
					version control your Logrus to make sure you aren't fetching latest `master` on
 | 
				
			||||||
 | 
					every build.**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Nicely color-coded in development (when a TTY is attached, otherwise just
 | 
					Nicely color-coded in development (when a TTY is attached, otherwise just
 | 
				
			||||||
plain text):
 | 
					plain text):
 | 
				
			||||||
| 
						 | 
					@ -33,7 +34,7 @@ ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
With the default `log.Formatter = new(logrus.TextFormatter)` when a TTY is not
 | 
					With the default `log.Formatter = new(logrus.TextFormatter)` when a TTY is not
 | 
				
			||||||
attached, the output is compatible with the
 | 
					attached, the output is compatible with the
 | 
				
			||||||
[l2met](http://r.32k.io/l2met-introduction) format:
 | 
					[logfmt](http://godoc.org/github.com/kr/logfmt) format:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```text
 | 
					```text
 | 
				
			||||||
time="2014-04-20 15:36:23.830442383 -0400 EDT" level="info" msg="A group of walrus emerges from the ocean" animal="walrus" size=10
 | 
					time="2014-04-20 15:36:23.830442383 -0400 EDT" level="info" msg="A group of walrus emerges from the ocean" animal="walrus" size=10
 | 
				
			||||||
| 
						 | 
					@ -206,11 +207,18 @@ import (
 | 
				
			||||||
  log "github.com/Sirupsen/logrus"
 | 
					  log "github.com/Sirupsen/logrus"
 | 
				
			||||||
  "github.com/Sirupsen/logrus/hooks/airbrake"
 | 
					  "github.com/Sirupsen/logrus/hooks/airbrake"
 | 
				
			||||||
  "github.com/Sirupsen/logrus/hooks/syslog"
 | 
					  "github.com/Sirupsen/logrus/hooks/syslog"
 | 
				
			||||||
 | 
					  "log/syslog"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
  log.AddHook(new(logrus_airbrake.AirbrakeHook))
 | 
					  log.AddHook(new(logrus_airbrake.AirbrakeHook))
 | 
				
			||||||
  log.AddHook(logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, ""))
 | 
					
 | 
				
			||||||
 | 
					  hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
 | 
				
			||||||
 | 
					  if err != nil {
 | 
				
			||||||
 | 
					    log.Error("Unable to connect to local syslog daemon")
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    log.AddHook(hook)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -228,6 +236,15 @@ func init() {
 | 
				
			||||||
* [`github.com/nubo/hiprus`](https://github.com/nubo/hiprus)
 | 
					* [`github.com/nubo/hiprus`](https://github.com/nubo/hiprus)
 | 
				
			||||||
  Send errors to a channel in hipchat.
 | 
					  Send errors to a channel in hipchat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`github.com/sebest/logrusly`](https://github.com/sebest/logrusly)
 | 
				
			||||||
 | 
					  Send logs to Loggly (https://www.loggly.com/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`github.com/johntdyer/slackrus`](https://github.com/johntdyer/slackrus)
 | 
				
			||||||
 | 
					  Hook for Slack chat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`github.com/wercker/journalhook`](https://github.com/wercker/journalhook).
 | 
				
			||||||
 | 
					  Hook for logging to `systemd-journald`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Level logging
 | 
					#### Level logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
 | 
					Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
 | 
				
			||||||
| 
						 | 
					@ -307,7 +324,7 @@ The built-in logging formatters are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Third party logging formatters:
 | 
					Third party logging formatters:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [`zalgo`](https://github.com/aybabtme/logzalgo): invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
 | 
					* [`zalgo`](https://github.com/aybabtme/logzalgo): invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can define your formatter by implementing the `Formatter` interface,
 | 
					You can define your formatter by implementing the `Formatter` interface,
 | 
				
			||||||
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
 | 
					requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
 | 
				
			||||||
| 
						 | 
					@ -332,10 +349,28 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Logger as an `io.Writer`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					w := logger.Writer()
 | 
				
			||||||
 | 
					defer w.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					srv := http.Server{
 | 
				
			||||||
 | 
					    // create a stdlib log.Logger that writes to
 | 
				
			||||||
 | 
					    // logrus.Logger.
 | 
				
			||||||
 | 
					    ErrorLog: log.New(w, "", 0),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each line written to that writer will be printed the usual way, using formatters
 | 
				
			||||||
 | 
					and hooks. The level for those entries is `info`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Rotation
 | 
					#### Rotation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Log rotation is not provided with Logrus. Log rotation should be done by an
 | 
					Log rotation is not provided with Logrus. Log rotation should be done by an
 | 
				
			||||||
external program (like `logrotated(8)`) that can compress and delete old log
 | 
					external program (like `logrotate(8)`) that can compress and delete old log
 | 
				
			||||||
entries. It should not be a feature of the application-level logger.
 | 
					entries. It should not be a feature of the application-level logger.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,7 @@ func (entry *Entry) log(level Level, msg string) {
 | 
				
			||||||
	// panic() to use in Entry#Panic(), we avoid the allocation by checking
 | 
						// panic() to use in Entry#Panic(), we avoid the allocation by checking
 | 
				
			||||||
	// directly here.
 | 
						// directly here.
 | 
				
			||||||
	if level <= PanicLevel {
 | 
						if level <= PanicLevel {
 | 
				
			||||||
		panic(reader.String())
 | 
							panic(entry)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,10 @@ func (entry *Entry) Warn(args ...interface{}) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (entry *Entry) Warning(args ...interface{}) {
 | 
				
			||||||
 | 
						entry.Warn(args...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (entry *Entry) Error(args ...interface{}) {
 | 
					func (entry *Entry) Error(args ...interface{}) {
 | 
				
			||||||
	if entry.Logger.Level >= ErrorLevel {
 | 
						if entry.Logger.Level >= ErrorLevel {
 | 
				
			||||||
		entry.log(ErrorLevel, fmt.Sprint(args...))
 | 
							entry.log(ErrorLevel, fmt.Sprint(args...))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										53
									
								
								vendor/src/github.com/Sirupsen/logrus/entry_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/src/github.com/Sirupsen/logrus/entry_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,53 @@
 | 
				
			||||||
 | 
					package logrus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEntryPanicln(t *testing.T) {
 | 
				
			||||||
 | 
						errBoom := fmt.Errorf("boom time")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							p := recover()
 | 
				
			||||||
 | 
							assert.NotNil(t, p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch pVal := p.(type) {
 | 
				
			||||||
 | 
							case *Entry:
 | 
				
			||||||
 | 
								assert.Equal(t, "kaboom", pVal.Message)
 | 
				
			||||||
 | 
								assert.Equal(t, errBoom, pVal.Data["err"])
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger := New()
 | 
				
			||||||
 | 
						logger.Out = &bytes.Buffer{}
 | 
				
			||||||
 | 
						entry := NewEntry(logger)
 | 
				
			||||||
 | 
						entry.WithField("err", errBoom).Panicln("kaboom")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEntryPanicf(t *testing.T) {
 | 
				
			||||||
 | 
						errBoom := fmt.Errorf("boom again")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							p := recover()
 | 
				
			||||||
 | 
							assert.NotNil(t, p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch pVal := p.(type) {
 | 
				
			||||||
 | 
							case *Entry:
 | 
				
			||||||
 | 
								assert.Equal(t, "kaboom true", pVal.Message)
 | 
				
			||||||
 | 
								assert.Equal(t, errBoom, pVal.Data["err"])
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger := New()
 | 
				
			||||||
 | 
						logger.Out = &bytes.Buffer{}
 | 
				
			||||||
 | 
						entry := NewEntry(logger)
 | 
				
			||||||
 | 
						entry.WithField("err", errBoom).Panicf("kaboom %v", true)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -9,9 +9,26 @@ var log = logrus.New()
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	log.Formatter = new(logrus.JSONFormatter)
 | 
						log.Formatter = new(logrus.JSONFormatter)
 | 
				
			||||||
	log.Formatter = new(logrus.TextFormatter) // default
 | 
						log.Formatter = new(logrus.TextFormatter) // default
 | 
				
			||||||
 | 
						log.Level = logrus.DebugLevel
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							err := recover()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.WithFields(logrus.Fields{
 | 
				
			||||||
 | 
									"omg":    true,
 | 
				
			||||||
 | 
									"err":    err,
 | 
				
			||||||
 | 
									"number": 100,
 | 
				
			||||||
 | 
								}).Fatal("The ice breaks!")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.WithFields(logrus.Fields{
 | 
				
			||||||
 | 
							"animal": "walrus",
 | 
				
			||||||
 | 
							"number": 8,
 | 
				
			||||||
 | 
						}).Debug("Started observing beach")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.WithFields(logrus.Fields{
 | 
						log.WithFields(logrus.Fields{
 | 
				
			||||||
		"animal": "walrus",
 | 
							"animal": "walrus",
 | 
				
			||||||
		"size":   10,
 | 
							"size":   10,
 | 
				
			||||||
| 
						 | 
					@ -23,7 +40,11 @@ func main() {
 | 
				
			||||||
	}).Warn("The group's number increased tremendously!")
 | 
						}).Warn("The group's number increased tremendously!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.WithFields(logrus.Fields{
 | 
						log.WithFields(logrus.Fields{
 | 
				
			||||||
		"omg":    true,
 | 
							"temperature": -4,
 | 
				
			||||||
		"number": 100,
 | 
						}).Debug("Temperature changes")
 | 
				
			||||||
	}).Fatal("The ice breaks!")
 | 
					
 | 
				
			||||||
 | 
						log.WithFields(logrus.Fields{
 | 
				
			||||||
 | 
							"animal": "orca",
 | 
				
			||||||
 | 
							"size":   9009,
 | 
				
			||||||
 | 
						}).Panic("It's over 9000!")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,10 @@ var (
 | 
				
			||||||
	std = New()
 | 
						std = New()
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func StandardLogger() *Logger {
 | 
				
			||||||
 | 
						return std
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetOutput sets the standard logger output.
 | 
					// SetOutput sets the standard logger output.
 | 
				
			||||||
func SetOutput(out io.Writer) {
 | 
					func SetOutput(out io.Writer) {
 | 
				
			||||||
	std.mu.Lock()
 | 
						std.mu.Lock()
 | 
				
			||||||
| 
						 | 
					@ -30,6 +34,13 @@ func SetLevel(level Level) {
 | 
				
			||||||
	std.Level = level
 | 
						std.Level = level
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetLevel returns the standard logger level.
 | 
				
			||||||
 | 
					func GetLevel() Level {
 | 
				
			||||||
 | 
						std.mu.Lock()
 | 
				
			||||||
 | 
						defer std.mu.Unlock()
 | 
				
			||||||
 | 
						return std.Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AddHook adds a hook to the standard logger hooks.
 | 
					// AddHook adds a hook to the standard logger hooks.
 | 
				
			||||||
func AddHook(hook Hook) {
 | 
					func AddHook(hook Hook) {
 | 
				
			||||||
	std.mu.Lock()
 | 
						std.mu.Lock()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,19 +26,19 @@ type Formatter interface {
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// It's not exported because it's still using Data in an opinionated way. It's to
 | 
					// It's not exported because it's still using Data in an opinionated way. It's to
 | 
				
			||||||
// avoid code duplication between the two default formatters.
 | 
					// avoid code duplication between the two default formatters.
 | 
				
			||||||
func prefixFieldClashes(entry *Entry) {
 | 
					func prefixFieldClashes(data Fields) {
 | 
				
			||||||
	_, ok := entry.Data["time"]
 | 
						_, ok := data["time"]
 | 
				
			||||||
	if ok {
 | 
						if ok {
 | 
				
			||||||
		entry.Data["fields.time"] = entry.Data["time"]
 | 
							data["fields.time"] = data["time"]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, ok = entry.Data["msg"]
 | 
						_, ok = data["msg"]
 | 
				
			||||||
	if ok {
 | 
						if ok {
 | 
				
			||||||
		entry.Data["fields.msg"] = entry.Data["msg"]
 | 
							data["fields.msg"] = data["msg"]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, ok = entry.Data["level"]
 | 
						_, ok = data["level"]
 | 
				
			||||||
	if ok {
 | 
						if ok {
 | 
				
			||||||
		entry.Data["fields.level"] = entry.Data["level"]
 | 
							data["fields.level"] = data["level"]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import (
 | 
				
			||||||
// with the Airbrake API. You must set:
 | 
					// with the Airbrake API. You must set:
 | 
				
			||||||
// * airbrake.Endpoint
 | 
					// * airbrake.Endpoint
 | 
				
			||||||
// * airbrake.ApiKey
 | 
					// * airbrake.ApiKey
 | 
				
			||||||
// * airbrake.Environment (only sends exceptions when set to "production")
 | 
					// * airbrake.Environment
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Before using this hook, to send an error. Entries that trigger an Error,
 | 
					// Before using this hook, to send an error. Entries that trigger an Error,
 | 
				
			||||||
// Fatal or Panic should now include an "error" field to send to Airbrake.
 | 
					// Fatal or Panic should now include an "error" field to send to Airbrake.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,8 @@ func NewPapertrailHook(host string, port int, appName string) (*PapertrailHook,
 | 
				
			||||||
// Fire is called when a log event is fired.
 | 
					// Fire is called when a log event is fired.
 | 
				
			||||||
func (hook *PapertrailHook) Fire(entry *logrus.Entry) error {
 | 
					func (hook *PapertrailHook) Fire(entry *logrus.Entry) error {
 | 
				
			||||||
	date := time.Now().Format(format)
 | 
						date := time.Now().Format(format)
 | 
				
			||||||
	payload := fmt.Sprintf("<22> %s %s: [%s] %s", date, hook.AppName, entry.Data["level"], entry.Message)
 | 
						msg, _ := entry.String()
 | 
				
			||||||
 | 
						payload := fmt.Sprintf("<22> %s %s: %s", date, hook.AppName, msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bytesWritten, err := hook.UDPConn.Write([]byte(payload))
 | 
						bytesWritten, err := hook.UDPConn.Write([]byte(payload))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								vendor/src/github.com/Sirupsen/logrus/hooks/sentry/README.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/src/github.com/Sirupsen/logrus/hooks/sentry/README.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,61 @@
 | 
				
			||||||
 | 
					# Sentry Hook for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Sentry](https://getsentry.com) provides both self-hosted and hosted
 | 
				
			||||||
 | 
					solutions for exception tracking.
 | 
				
			||||||
 | 
					Both client and server are
 | 
				
			||||||
 | 
					[open source](https://github.com/getsentry/sentry).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Every sentry application defined on the server gets a different
 | 
				
			||||||
 | 
					[DSN](https://www.getsentry.com/docs/). In the example below replace
 | 
				
			||||||
 | 
					`YOUR_DSN` with the one created for your application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
					  "github.com/Sirupsen/logrus"
 | 
				
			||||||
 | 
					  "github.com/Sirupsen/logrus/hooks/sentry"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
					  log       := logrus.New()
 | 
				
			||||||
 | 
					  hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{
 | 
				
			||||||
 | 
					    logrus.PanicLevel,
 | 
				
			||||||
 | 
					    logrus.FatalLevel,
 | 
				
			||||||
 | 
					    logrus.ErrorLevel,
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if err == nil {
 | 
				
			||||||
 | 
					    log.Hooks.Add(hook)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Special fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some logrus fields have a special meaning in this hook,
 | 
				
			||||||
 | 
					these are server_name and logger.
 | 
				
			||||||
 | 
					When logs are sent to sentry these fields are treated differently.
 | 
				
			||||||
 | 
					- server_name (also known as hostname) is the name of the server which
 | 
				
			||||||
 | 
					is logging the event (hostname.example.com)
 | 
				
			||||||
 | 
					- logger is the part of the application which is logging the event.
 | 
				
			||||||
 | 
					In go this usually means setting it to the name of the package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`Timeout` is the time the sentry hook will wait for a response
 | 
				
			||||||
 | 
					from the sentry server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If this time elapses with no response from
 | 
				
			||||||
 | 
					the server an error will be returned.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If `Timeout` is set to 0 the SentryHook will not wait for a reply
 | 
				
			||||||
 | 
					and will assume a correct delivery.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The SentryHook has a default timeout of `100 milliseconds` when created
 | 
				
			||||||
 | 
					with a call to `NewSentryHook`. This can be changed by assigning a value to the `Timeout` field:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					hook, _ := logrus_sentry.NewSentryHook(...)
 | 
				
			||||||
 | 
					hook.Timeout = 20*time.Second
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										100
									
								
								vendor/src/github.com/Sirupsen/logrus/hooks/sentry/sentry.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/src/github.com/Sirupsen/logrus/hooks/sentry/sentry.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,100 @@
 | 
				
			||||||
 | 
					package logrus_sentry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Sirupsen/logrus"
 | 
				
			||||||
 | 
						"github.com/getsentry/raven-go"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						severityMap = map[logrus.Level]raven.Severity{
 | 
				
			||||||
 | 
							logrus.DebugLevel: raven.DEBUG,
 | 
				
			||||||
 | 
							logrus.InfoLevel:  raven.INFO,
 | 
				
			||||||
 | 
							logrus.WarnLevel:  raven.WARNING,
 | 
				
			||||||
 | 
							logrus.ErrorLevel: raven.ERROR,
 | 
				
			||||||
 | 
							logrus.FatalLevel: raven.FATAL,
 | 
				
			||||||
 | 
							logrus.PanicLevel: raven.FATAL,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getAndDel(d logrus.Fields, key string) (string, bool) {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							ok  bool
 | 
				
			||||||
 | 
							v   interface{}
 | 
				
			||||||
 | 
							val string
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if v, ok = d[key]; !ok {
 | 
				
			||||||
 | 
							return "", false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if val, ok = v.(string); !ok {
 | 
				
			||||||
 | 
							return "", false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						delete(d, key)
 | 
				
			||||||
 | 
						return val, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SentryHook delivers logs to a sentry server.
 | 
				
			||||||
 | 
					type SentryHook struct {
 | 
				
			||||||
 | 
						// Timeout sets the time to wait for a delivery error from the sentry server.
 | 
				
			||||||
 | 
						// If this is set to zero the server will not wait for any response and will
 | 
				
			||||||
 | 
						// consider the message correctly sent
 | 
				
			||||||
 | 
						Timeout time.Duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client *raven.Client
 | 
				
			||||||
 | 
						levels []logrus.Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewSentryHook creates a hook to be added to an instance of logger
 | 
				
			||||||
 | 
					// and initializes the raven client.
 | 
				
			||||||
 | 
					// This method sets the timeout to 100 milliseconds.
 | 
				
			||||||
 | 
					func NewSentryHook(DSN string, levels []logrus.Level) (*SentryHook, error) {
 | 
				
			||||||
 | 
						client, err := raven.NewClient(DSN, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &SentryHook{100 * time.Millisecond, client, levels}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Called when an event should be sent to sentry
 | 
				
			||||||
 | 
					// Special fields that sentry uses to give more information to the server
 | 
				
			||||||
 | 
					// are extracted from entry.Data (if they are found)
 | 
				
			||||||
 | 
					// These fields are: logger and server_name
 | 
				
			||||||
 | 
					func (hook *SentryHook) Fire(entry *logrus.Entry) error {
 | 
				
			||||||
 | 
						packet := &raven.Packet{
 | 
				
			||||||
 | 
							Message:   entry.Message,
 | 
				
			||||||
 | 
							Timestamp: raven.Timestamp(entry.Time),
 | 
				
			||||||
 | 
							Level:     severityMap[entry.Level],
 | 
				
			||||||
 | 
							Platform:  "go",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						d := entry.Data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if logger, ok := getAndDel(d, "logger"); ok {
 | 
				
			||||||
 | 
							packet.Logger = logger
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if serverName, ok := getAndDel(d, "server_name"); ok {
 | 
				
			||||||
 | 
							packet.ServerName = serverName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						packet.Extra = map[string]interface{}(d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, errCh := hook.client.Capture(packet, nil)
 | 
				
			||||||
 | 
						timeout := hook.Timeout
 | 
				
			||||||
 | 
						if timeout != 0 {
 | 
				
			||||||
 | 
							timeoutCh := time.After(timeout)
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case err := <-errCh:
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							case <-timeoutCh:
 | 
				
			||||||
 | 
								return fmt.Errorf("no response from sentry server in %s", timeout)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Levels returns the available logging levels.
 | 
				
			||||||
 | 
					func (hook *SentryHook) Levels() []logrus.Level {
 | 
				
			||||||
 | 
						return hook.levels
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										97
									
								
								vendor/src/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/src/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,97 @@
 | 
				
			||||||
 | 
					package logrus_sentry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/http/httptest"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Sirupsen/logrus"
 | 
				
			||||||
 | 
						"github.com/getsentry/raven-go"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						message     = "error message"
 | 
				
			||||||
 | 
						server_name = "testserver.internal"
 | 
				
			||||||
 | 
						logger_name = "test.logger"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getTestLogger() *logrus.Logger {
 | 
				
			||||||
 | 
						l := logrus.New()
 | 
				
			||||||
 | 
						l.Out = ioutil.Discard
 | 
				
			||||||
 | 
						return l
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithTestDSN(t *testing.T, tf func(string, <-chan *raven.Packet)) {
 | 
				
			||||||
 | 
						pch := make(chan *raven.Packet, 1)
 | 
				
			||||||
 | 
						s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							defer req.Body.Close()
 | 
				
			||||||
 | 
							d := json.NewDecoder(req.Body)
 | 
				
			||||||
 | 
							p := &raven.Packet{}
 | 
				
			||||||
 | 
							err := d.Decode(p)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pch <- p
 | 
				
			||||||
 | 
						}))
 | 
				
			||||||
 | 
						defer s.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fragments := strings.SplitN(s.URL, "://", 2)
 | 
				
			||||||
 | 
						dsn := fmt.Sprintf(
 | 
				
			||||||
 | 
							"%s://public:secret@%s/sentry/project-id",
 | 
				
			||||||
 | 
							fragments[0],
 | 
				
			||||||
 | 
							fragments[1],
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						tf(dsn, pch)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSpecialFields(t *testing.T) {
 | 
				
			||||||
 | 
						WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
 | 
				
			||||||
 | 
							logger := getTestLogger()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							hook, err := NewSentryHook(dsn, []logrus.Level{
 | 
				
			||||||
 | 
								logrus.ErrorLevel,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							logger.Hooks.Add(hook)
 | 
				
			||||||
 | 
							logger.WithFields(logrus.Fields{
 | 
				
			||||||
 | 
								"server_name": server_name,
 | 
				
			||||||
 | 
								"logger":      logger_name,
 | 
				
			||||||
 | 
							}).Error(message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							packet := <-pch
 | 
				
			||||||
 | 
							if packet.Logger != logger_name {
 | 
				
			||||||
 | 
								t.Errorf("logger should have been %s, was %s", logger_name, packet.Logger)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if packet.ServerName != server_name {
 | 
				
			||||||
 | 
								t.Errorf("server_name should have been %s, was %s", server_name, packet.ServerName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSentryHandler(t *testing.T) {
 | 
				
			||||||
 | 
						WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
 | 
				
			||||||
 | 
							logger := getTestLogger()
 | 
				
			||||||
 | 
							hook, err := NewSentryHook(dsn, []logrus.Level{
 | 
				
			||||||
 | 
								logrus.ErrorLevel,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							logger.Hooks.Add(hook)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							logger.Error(message)
 | 
				
			||||||
 | 
							packet := <-pch
 | 
				
			||||||
 | 
							if packet.Message != message {
 | 
				
			||||||
 | 
								t.Errorf("message should have been %s, was %s", message, packet.Message)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
  "log/syslog"
 | 
					  "log/syslog"
 | 
				
			||||||
  "github.com/Sirupsen/logrus"
 | 
					  "github.com/Sirupsen/logrus"
 | 
				
			||||||
  "github.com/Sirupsen/logrus/hooks/syslog"
 | 
					  logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
| 
						 | 
					@ -17,4 +17,4 @@ func main() {
 | 
				
			||||||
    log.Hooks.Add(hook)
 | 
					    log.Hooks.Add(hook)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,18 +29,18 @@ func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch entry.Data["level"] {
 | 
						switch entry.Level {
 | 
				
			||||||
	case "panic":
 | 
						case logrus.PanicLevel:
 | 
				
			||||||
		return hook.Writer.Crit(line)
 | 
							return hook.Writer.Crit(line)
 | 
				
			||||||
	case "fatal":
 | 
						case logrus.FatalLevel:
 | 
				
			||||||
		return hook.Writer.Crit(line)
 | 
							return hook.Writer.Crit(line)
 | 
				
			||||||
	case "error":
 | 
						case logrus.ErrorLevel:
 | 
				
			||||||
		return hook.Writer.Err(line)
 | 
							return hook.Writer.Err(line)
 | 
				
			||||||
	case "warn":
 | 
						case logrus.WarnLevel:
 | 
				
			||||||
		return hook.Writer.Warning(line)
 | 
							return hook.Writer.Warning(line)
 | 
				
			||||||
	case "info":
 | 
						case logrus.InfoLevel:
 | 
				
			||||||
		return hook.Writer.Info(line)
 | 
							return hook.Writer.Info(line)
 | 
				
			||||||
	case "debug":
 | 
						case logrus.DebugLevel:
 | 
				
			||||||
		return hook.Writer.Debug(line)
 | 
							return hook.Writer.Debug(line)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,12 +9,22 @@ import (
 | 
				
			||||||
type JSONFormatter struct{}
 | 
					type JSONFormatter struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 | 
					func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 | 
				
			||||||
	prefixFieldClashes(entry)
 | 
						data := make(Fields, len(entry.Data)+3)
 | 
				
			||||||
	entry.Data["time"] = entry.Time.Format(time.RFC3339)
 | 
						for k, v := range entry.Data {
 | 
				
			||||||
	entry.Data["msg"] = entry.Message
 | 
							// Otherwise errors are ignored by `encoding/json`
 | 
				
			||||||
	entry.Data["level"] = entry.Level.String()
 | 
							// https://github.com/Sirupsen/logrus/issues/137
 | 
				
			||||||
 | 
							if err, ok := v.(error); ok {
 | 
				
			||||||
 | 
								data[k] = err.Error()
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								data[k] = v
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						prefixFieldClashes(data)
 | 
				
			||||||
 | 
						data["time"] = entry.Time.Format(time.RFC3339)
 | 
				
			||||||
 | 
						data["msg"] = entry.Message
 | 
				
			||||||
 | 
						data["level"] = entry.Level.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serialized, err := json.Marshal(entry.Data)
 | 
						serialized, err := json.Marshal(data)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
 | 
							return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										120
									
								
								vendor/src/github.com/Sirupsen/logrus/json_formatter_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								vendor/src/github.com/Sirupsen/logrus/json_formatter_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,120 @@
 | 
				
			||||||
 | 
					package logrus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestErrorNotLost(t *testing.T) {
 | 
				
			||||||
 | 
						formatter := &JSONFormatter{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to format entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry := make(map[string]interface{})
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, &entry)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to unmarshal formatted entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if entry["error"] != "wild walrus" {
 | 
				
			||||||
 | 
							t.Fatal("Error field not set")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
 | 
				
			||||||
 | 
						formatter := &JSONFormatter{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to format entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry := make(map[string]interface{})
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, &entry)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to unmarshal formatted entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if entry["omg"] != "wild walrus" {
 | 
				
			||||||
 | 
							t.Fatal("Error field not set")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestFieldClashWithTime(t *testing.T) {
 | 
				
			||||||
 | 
						formatter := &JSONFormatter{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b, err := formatter.Format(WithField("time", "right now!"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to format entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry := make(map[string]interface{})
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, &entry)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to unmarshal formatted entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if entry["fields.time"] != "right now!" {
 | 
				
			||||||
 | 
							t.Fatal("fields.time not set to original time field")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if entry["time"] != "0001-01-01T00:00:00Z" {
 | 
				
			||||||
 | 
							t.Fatal("time field not set to current time, was: ", entry["time"])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestFieldClashWithMsg(t *testing.T) {
 | 
				
			||||||
 | 
						formatter := &JSONFormatter{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b, err := formatter.Format(WithField("msg", "something"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to format entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry := make(map[string]interface{})
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, &entry)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to unmarshal formatted entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if entry["fields.msg"] != "something" {
 | 
				
			||||||
 | 
							t.Fatal("fields.msg not set to original msg field")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestFieldClashWithLevel(t *testing.T) {
 | 
				
			||||||
 | 
						formatter := &JSONFormatter{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b, err := formatter.Format(WithField("level", "something"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to format entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry := make(map[string]interface{})
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, &entry)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to unmarshal formatted entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if entry["fields.level"] != "something" {
 | 
				
			||||||
 | 
							t.Fatal("fields.level not set to original level field")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestJSONEntryEndsWithNewline(t *testing.T) {
 | 
				
			||||||
 | 
						formatter := &JSONFormatter{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b, err := formatter.Format(WithField("level", "something"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("Unable to format entry: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if b[len(b)-1] != '\n' {
 | 
				
			||||||
 | 
							t.Fatal("Expected JSON log entry to end with a newline")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ type Logger struct {
 | 
				
			||||||
//      Out: os.Stderr,
 | 
					//      Out: os.Stderr,
 | 
				
			||||||
//      Formatter: new(JSONFormatter),
 | 
					//      Formatter: new(JSONFormatter),
 | 
				
			||||||
//      Hooks: make(levelHooks),
 | 
					//      Hooks: make(levelHooks),
 | 
				
			||||||
//      Level: logrus.Debug,
 | 
					//      Level: logrus.DebugLevel,
 | 
				
			||||||
//    }
 | 
					//    }
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// It's recommended to make this a global instance called `log`.
 | 
					// It's recommended to make this a global instance called `log`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
| 
						 | 
					@ -44,8 +45,12 @@ func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields ma
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		kvArr := strings.Split(kv, "=")
 | 
							kvArr := strings.Split(kv, "=")
 | 
				
			||||||
		key := strings.TrimSpace(kvArr[0])
 | 
							key := strings.TrimSpace(kvArr[0])
 | 
				
			||||||
		val, err := strconv.Unquote(kvArr[1])
 | 
							val := kvArr[1]
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							if kvArr[1][0] == '"' {
 | 
				
			||||||
 | 
								var err error
 | 
				
			||||||
 | 
								val, err = strconv.Unquote(val)
 | 
				
			||||||
 | 
								assert.NoError(t, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		fields[key] = val
 | 
							fields[key] = val
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	assertions(fields)
 | 
						assertions(fields)
 | 
				
			||||||
| 
						 | 
					@ -204,6 +209,38 @@ func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var buffer bytes.Buffer
 | 
				
			||||||
 | 
						var fields Fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger := New()
 | 
				
			||||||
 | 
						logger.Out = &buffer
 | 
				
			||||||
 | 
						logger.Formatter = new(JSONFormatter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llog := logger.WithField("context", "eating raw fish")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llog.Info("looks delicious")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := json.Unmarshal(buffer.Bytes(), &fields)
 | 
				
			||||||
 | 
						assert.NoError(t, err, "should have decoded first message")
 | 
				
			||||||
 | 
						assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
 | 
				
			||||||
 | 
						assert.Equal(t, fields["msg"], "looks delicious")
 | 
				
			||||||
 | 
						assert.Equal(t, fields["context"], "eating raw fish")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llog.Warn("omg it is!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = json.Unmarshal(buffer.Bytes(), &fields)
 | 
				
			||||||
 | 
						assert.NoError(t, err, "should have decoded second message")
 | 
				
			||||||
 | 
						assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
 | 
				
			||||||
 | 
						assert.Equal(t, fields["msg"], "omg it is!")
 | 
				
			||||||
 | 
						assert.Equal(t, fields["context"], "eating raw fish")
 | 
				
			||||||
 | 
						assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestConvertLevelToString(t *testing.T) {
 | 
					func TestConvertLevelToString(t *testing.T) {
 | 
				
			||||||
	assert.Equal(t, "debug", DebugLevel.String())
 | 
						assert.Equal(t, "debug", DebugLevel.String())
 | 
				
			||||||
	assert.Equal(t, "info", InfoLevel.String())
 | 
						assert.Equal(t, "info", InfoLevel.String())
 | 
				
			||||||
| 
						 | 
					@ -245,3 +282,20 @@ func TestParseLevel(t *testing.T) {
 | 
				
			||||||
	l, err = ParseLevel("invalid")
 | 
						l, err = ParseLevel("invalid")
 | 
				
			||||||
	assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
 | 
						assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGetSetLevelRace(t *testing.T) {
 | 
				
			||||||
 | 
						wg := sync.WaitGroup{}
 | 
				
			||||||
 | 
						for i := 0; i < 100; i++ {
 | 
				
			||||||
 | 
							wg.Add(1)
 | 
				
			||||||
 | 
							go func(i int) {
 | 
				
			||||||
 | 
								defer wg.Done()
 | 
				
			||||||
 | 
								if i%2 == 0 {
 | 
				
			||||||
 | 
									SetLevel(InfoLevel)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									GetLevel()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}(i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wg.Wait()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
// Use of this source code is governed by a BSD-style
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// +build linux,!appengine darwin freebsd
 | 
					// +build linux darwin freebsd openbsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package logrus
 | 
					package logrus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								vendor/src/github.com/Sirupsen/logrus/terminal_openbsd.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/src/github.com/Sirupsen/logrus/terminal_openbsd.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package logrus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ioctlReadTermios = syscall.TIOCGETA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Termios syscall.Termios
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ package logrus
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -14,11 +15,13 @@ const (
 | 
				
			||||||
	green   = 32
 | 
						green   = 32
 | 
				
			||||||
	yellow  = 33
 | 
						yellow  = 33
 | 
				
			||||||
	blue    = 34
 | 
						blue    = 34
 | 
				
			||||||
 | 
						gray    = 37
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	baseTimestamp time.Time
 | 
						baseTimestamp time.Time
 | 
				
			||||||
	isTerminal    bool
 | 
						isTerminal    bool
 | 
				
			||||||
 | 
						noQuoteNeeded *regexp.Regexp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
| 
						 | 
					@ -32,28 +35,47 @@ func miniTS() int {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TextFormatter struct {
 | 
					type TextFormatter struct {
 | 
				
			||||||
	// Set to true to bypass checking for a TTY before outputting colors.
 | 
						// Set to true to bypass checking for a TTY before outputting colors.
 | 
				
			||||||
	ForceColors   bool
 | 
						ForceColors bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Force disabling colors.
 | 
				
			||||||
	DisableColors bool
 | 
						DisableColors bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Disable timestamp logging. useful when output is redirected to logging
 | 
				
			||||||
 | 
						// system that already adds timestamps.
 | 
				
			||||||
 | 
						DisableTimestamp bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Enable logging the full timestamp when a TTY is attached instead of just
 | 
				
			||||||
 | 
						// the time passed since beginning of execution.
 | 
				
			||||||
 | 
						FullTimestamp bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The fields are sorted by default for a consistent output. For applications
 | 
				
			||||||
 | 
						// that log extremely frequently and don't use the JSON formatter this may not
 | 
				
			||||||
 | 
						// be desired.
 | 
				
			||||||
 | 
						DisableSorting bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
 | 
					func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
 | 
				
			||||||
 | 
						var keys []string = make([]string, 0, len(entry.Data))
 | 
				
			||||||
	var keys []string
 | 
					 | 
				
			||||||
	for k := range entry.Data {
 | 
						for k := range entry.Data {
 | 
				
			||||||
		keys = append(keys, k)
 | 
							keys = append(keys, k)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sort.Strings(keys)
 | 
					
 | 
				
			||||||
 | 
						if !f.DisableSorting {
 | 
				
			||||||
 | 
							sort.Strings(keys)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b := &bytes.Buffer{}
 | 
						b := &bytes.Buffer{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	prefixFieldClashes(entry)
 | 
						prefixFieldClashes(entry.Data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isColored := (f.ForceColors || isTerminal) && !f.DisableColors
 | 
						isColored := (f.ForceColors || isTerminal) && !f.DisableColors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if isColored {
 | 
						if isColored {
 | 
				
			||||||
		printColored(b, entry, keys)
 | 
							f.printColored(b, entry, keys)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
 | 
							if !f.DisableTimestamp {
 | 
				
			||||||
 | 
								f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		f.appendKeyValue(b, "level", entry.Level.String())
 | 
							f.appendKeyValue(b, "level", entry.Level.String())
 | 
				
			||||||
		f.appendKeyValue(b, "msg", entry.Message)
 | 
							f.appendKeyValue(b, "msg", entry.Message)
 | 
				
			||||||
		for _, key := range keys {
 | 
							for _, key := range keys {
 | 
				
			||||||
| 
						 | 
					@ -65,9 +87,11 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
 | 
				
			||||||
	return b.Bytes(), nil
 | 
						return b.Bytes(), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func printColored(b *bytes.Buffer, entry *Entry, keys []string) {
 | 
					func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string) {
 | 
				
			||||||
	var levelColor int
 | 
						var levelColor int
 | 
				
			||||||
	switch entry.Level {
 | 
						switch entry.Level {
 | 
				
			||||||
 | 
						case DebugLevel:
 | 
				
			||||||
 | 
							levelColor = gray
 | 
				
			||||||
	case WarnLevel:
 | 
						case WarnLevel:
 | 
				
			||||||
		levelColor = yellow
 | 
							levelColor = yellow
 | 
				
			||||||
	case ErrorLevel, FatalLevel, PanicLevel:
 | 
						case ErrorLevel, FatalLevel, PanicLevel:
 | 
				
			||||||
| 
						 | 
					@ -78,17 +102,43 @@ func printColored(b *bytes.Buffer, entry *Entry, keys []string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	levelText := strings.ToUpper(entry.Level.String())[0:4]
 | 
						levelText := strings.ToUpper(entry.Level.String())[0:4]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
 | 
						if !f.FullTimestamp {
 | 
				
			||||||
 | 
							fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(time.RFC3339), entry.Message)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for _, k := range keys {
 | 
						for _, k := range keys {
 | 
				
			||||||
		v := entry.Data[k]
 | 
							v := entry.Data[k]
 | 
				
			||||||
		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
 | 
							fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func needsQuoting(text string) bool {
 | 
				
			||||||
 | 
						for _, ch := range text {
 | 
				
			||||||
 | 
							if !((ch >= 'a' && ch <= 'z') ||
 | 
				
			||||||
 | 
								(ch >= 'A' && ch <= 'Z') ||
 | 
				
			||||||
 | 
								(ch >= '0' && ch <= '9') ||
 | 
				
			||||||
 | 
								ch == '-' || ch == '.') {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
 | 
					func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
 | 
				
			||||||
	switch value.(type) {
 | 
						switch value.(type) {
 | 
				
			||||||
	case string, error:
 | 
						case string:
 | 
				
			||||||
		fmt.Fprintf(b, "%v=%q ", key, value)
 | 
							if needsQuoting(value.(string)) {
 | 
				
			||||||
 | 
								fmt.Fprintf(b, "%v=%s ", key, value)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fmt.Fprintf(b, "%v=%q ", key, value)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case error:
 | 
				
			||||||
 | 
							if needsQuoting(value.(error).Error()) {
 | 
				
			||||||
 | 
								fmt.Fprintf(b, "%v=%s ", key, value)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fmt.Fprintf(b, "%v=%q ", key, value)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		fmt.Fprintf(b, "%v=%v ", key, value)
 | 
							fmt.Fprintf(b, "%v=%v ", key, value)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								vendor/src/github.com/Sirupsen/logrus/text_formatter_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/src/github.com/Sirupsen/logrus/text_formatter_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					package logrus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestQuoting(t *testing.T) {
 | 
				
			||||||
 | 
						tf := &TextFormatter{DisableColors: true}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						checkQuoting := func(q bool, value interface{}) {
 | 
				
			||||||
 | 
							b, _ := tf.Format(WithField("test", value))
 | 
				
			||||||
 | 
							idx := bytes.Index(b, ([]byte)("test="))
 | 
				
			||||||
 | 
							cont := bytes.Contains(b[idx+5:], []byte{'"'})
 | 
				
			||||||
 | 
							if cont != q {
 | 
				
			||||||
 | 
								if q {
 | 
				
			||||||
 | 
									t.Errorf("quoting expected for: %#v", value)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									t.Errorf("quoting not expected for: %#v", value)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						checkQuoting(false, "abcd")
 | 
				
			||||||
 | 
						checkQuoting(false, "v1.0")
 | 
				
			||||||
 | 
						checkQuoting(false, "1234567890")
 | 
				
			||||||
 | 
						checkQuoting(true, "/foobar")
 | 
				
			||||||
 | 
						checkQuoting(true, "x y")
 | 
				
			||||||
 | 
						checkQuoting(true, "x,y")
 | 
				
			||||||
 | 
						checkQuoting(false, errors.New("invalid"))
 | 
				
			||||||
 | 
						checkQuoting(true, errors.New("invalid argument"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO add tests for sorting etc., this requires a parser for the text
 | 
				
			||||||
 | 
					// formatter output.
 | 
				
			||||||
							
								
								
									
										31
									
								
								vendor/src/github.com/Sirupsen/logrus/writer.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/src/github.com/Sirupsen/logrus/writer.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					package logrus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (logger *Logger) Writer() (*io.PipeWriter) {
 | 
				
			||||||
 | 
						reader, writer := io.Pipe()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go logger.writerScanner(reader)
 | 
				
			||||||
 | 
						runtime.SetFinalizer(writer, writerFinalizer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return writer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (logger *Logger) writerScanner(reader *io.PipeReader) {
 | 
				
			||||||
 | 
						scanner := bufio.NewScanner(reader)
 | 
				
			||||||
 | 
						for scanner.Scan() {
 | 
				
			||||||
 | 
							logger.Print(scanner.Text())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := scanner.Err(); err != nil {
 | 
				
			||||||
 | 
							logger.Errorf("Error while reading from Writer: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						reader.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writerFinalizer(writer *io.PipeWriter) {
 | 
				
			||||||
 | 
						writer.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue