update to github.com/sirupsen/logrus v1.0.0
Signed-off-by: Andrew Pennebaker <apennebaker@datapipe.com>
This commit is contained in:
		
				
					committed by
					
						
						Derek McGowan
					
				
			
			
				
	
			
			
			
						parent
						
							dd7642fc1c
						
					
				
				
					commit
					1d2a079f08
				
			
							
								
								
									
										41
									
								
								vendor/github.com/Sirupsen/logrus/json_formatter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/Sirupsen/logrus/json_formatter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,41 +0,0 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type JSONFormatter struct {
 | 
			
		||||
	// TimestampFormat sets the format used for marshaling timestamps.
 | 
			
		||||
	TimestampFormat string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 | 
			
		||||
	data := make(Fields, len(entry.Data)+3)
 | 
			
		||||
	for k, v := range entry.Data {
 | 
			
		||||
		switch v := v.(type) {
 | 
			
		||||
		case error:
 | 
			
		||||
			// Otherwise errors are ignored by `encoding/json`
 | 
			
		||||
			// https://github.com/Sirupsen/logrus/issues/137
 | 
			
		||||
			data[k] = v.Error()
 | 
			
		||||
		default:
 | 
			
		||||
			data[k] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	prefixFieldClashes(data)
 | 
			
		||||
 | 
			
		||||
	timestampFormat := f.TimestampFormat
 | 
			
		||||
	if timestampFormat == "" {
 | 
			
		||||
		timestampFormat = DefaultTimestampFormat
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data["time"] = entry.Time.Format(timestampFormat)
 | 
			
		||||
	data["msg"] = entry.Message
 | 
			
		||||
	data["level"] = entry.Level.String()
 | 
			
		||||
 | 
			
		||||
	serialized, err := json.Marshal(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return append(serialized, '\n'), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/Sirupsen/logrus/terminal_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/Sirupsen/logrus/terminal_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,15 +0,0 @@
 | 
			
		||||
// +build solaris,!appengine
 | 
			
		||||
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if the given file descriptor is a terminal.
 | 
			
		||||
func IsTerminal() bool {
 | 
			
		||||
	_, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/github.com/Sirupsen/logrus/terminal_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Sirupsen/logrus/terminal_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,27 +0,0 @@
 | 
			
		||||
// Based on ssh/terminal:
 | 
			
		||||
// Copyright 2011 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build windows,!appengine
 | 
			
		||||
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
 | 
			
		||||
func IsTerminal() bool {
 | 
			
		||||
	fd := syscall.Stderr
 | 
			
		||||
	var st uint32
 | 
			
		||||
	r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
 | 
			
		||||
	return r != 0 && e == 0
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										100
									
								
								vendor/github.com/sirupsen/logrus/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/github.com/sirupsen/logrus/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
# 1.0.0
 | 
			
		||||
 | 
			
		||||
* Officially changed name to lower-case
 | 
			
		||||
* bug: colors on Windows 10 (#541)
 | 
			
		||||
* bug: fix race in accessing level (#512)
 | 
			
		||||
 | 
			
		||||
# 0.11.5
 | 
			
		||||
 | 
			
		||||
* feature: add writer and writerlevel to entry (#372)
 | 
			
		||||
 | 
			
		||||
# 0.11.4
 | 
			
		||||
 | 
			
		||||
* bug: fix undefined variable on solaris (#493)
 | 
			
		||||
 | 
			
		||||
# 0.11.3
 | 
			
		||||
 | 
			
		||||
* formatter: configure quoting of empty values (#484)
 | 
			
		||||
* formatter: configure quoting character (default is `"`) (#484)
 | 
			
		||||
* bug: fix not importing io correctly in non-linux environments (#481)
 | 
			
		||||
 | 
			
		||||
# 0.11.2
 | 
			
		||||
 | 
			
		||||
* bug: fix windows terminal detection (#476)
 | 
			
		||||
 | 
			
		||||
# 0.11.1
 | 
			
		||||
 | 
			
		||||
* bug: fix tty detection with custom out (#471)
 | 
			
		||||
 | 
			
		||||
# 0.11.0
 | 
			
		||||
 | 
			
		||||
* performance: Use bufferpool to allocate (#370)
 | 
			
		||||
* terminal: terminal detection for app-engine (#343)
 | 
			
		||||
* feature: exit handler (#375)
 | 
			
		||||
 | 
			
		||||
# 0.10.0
 | 
			
		||||
 | 
			
		||||
* feature: Add a test hook (#180)
 | 
			
		||||
* feature: `ParseLevel` is now case-insensitive (#326)
 | 
			
		||||
* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
 | 
			
		||||
* performance: avoid re-allocations on `WithFields` (#335)
 | 
			
		||||
 | 
			
		||||
# 0.9.0
 | 
			
		||||
 | 
			
		||||
* logrus/text_formatter: don't emit empty msg
 | 
			
		||||
* logrus/hooks/airbrake: move out of main repository
 | 
			
		||||
* logrus/hooks/sentry: move out of main repository
 | 
			
		||||
* logrus/hooks/papertrail: move out of main repository
 | 
			
		||||
* logrus/hooks/bugsnag: move out of main repository
 | 
			
		||||
* logrus/core: run tests with `-race`
 | 
			
		||||
* logrus/core: detect TTY based on `stderr`
 | 
			
		||||
* logrus/core: support `WithError` on logger
 | 
			
		||||
* logrus/core: Solaris support
 | 
			
		||||
 | 
			
		||||
# 0.8.7
 | 
			
		||||
 | 
			
		||||
* logrus/core: fix possible race (#216)
 | 
			
		||||
* logrus/doc: small typo fixes and doc improvements
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# 0.8.6
 | 
			
		||||
 | 
			
		||||
* hooks/raven: allow passing an initialized client
 | 
			
		||||
 | 
			
		||||
# 0.8.5
 | 
			
		||||
 | 
			
		||||
* logrus/core: revert #208
 | 
			
		||||
 | 
			
		||||
# 0.8.4
 | 
			
		||||
 | 
			
		||||
* formatter/text: fix data race (#218)
 | 
			
		||||
 | 
			
		||||
# 0.8.3
 | 
			
		||||
 | 
			
		||||
* logrus/core: fix entry log level (#208)
 | 
			
		||||
* logrus/core: improve performance of text formatter by 40%
 | 
			
		||||
* logrus/core: expose `LevelHooks` type
 | 
			
		||||
* logrus/core: add support for DragonflyBSD and NetBSD
 | 
			
		||||
* formatter/text: print structs more verbosely
 | 
			
		||||
 | 
			
		||||
# 0.8.2
 | 
			
		||||
 | 
			
		||||
* logrus: fix more Fatal family functions
 | 
			
		||||
 | 
			
		||||
# 0.8.1
 | 
			
		||||
 | 
			
		||||
* logrus: fix not exiting on `Fatalf` and `Fatalln`
 | 
			
		||||
 | 
			
		||||
# 0.8.0
 | 
			
		||||
 | 
			
		||||
* logrus: defaults to stderr instead of stdout
 | 
			
		||||
* hooks/sentry: add special field for `*http.Request`
 | 
			
		||||
* formatter/text: ignore Windows for colors
 | 
			
		||||
 | 
			
		||||
# 0.7.3
 | 
			
		||||
 | 
			
		||||
* formatter/\*: allow configuration of timestamp layout
 | 
			
		||||
 | 
			
		||||
# 0.7.2
 | 
			
		||||
 | 
			
		||||
* formatter/text: Add configuration option for time format (#158)
 | 
			
		||||
							
								
								
									
										178
									
								
								vendor/github.com/Sirupsen/logrus/README.md → vendor/github.com/sirupsen/logrus/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										178
									
								
								vendor/github.com/Sirupsen/logrus/README.md → vendor/github.com/sirupsen/logrus/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
# 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) [](https://godoc.org/github.com/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) [](https://godoc.org/github.com/sirupsen/logrus)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@@ -7,6 +7,17 @@ many large deployments. The core API is unlikely to change much but please
 | 
			
		||||
version control your Logrus to make sure you aren't fetching latest `master` on
 | 
			
		||||
every build.**
 | 
			
		||||
 | 
			
		||||
**Seeing weird case-sensitive problems?** Unfortunately, the author failed to
 | 
			
		||||
realize the consequences of renaming to lower-case. Due to the Go package
 | 
			
		||||
environment, this caused issues. Regretfully, there's no turning back now.
 | 
			
		||||
Everything using `logrus` will need to use the lower-case:
 | 
			
		||||
`github.com/sirupsen/logrus`. Any package that isn't, should be changed.
 | 
			
		||||
 | 
			
		||||
I am terribly sorry for this inconvenience. Logrus strives hard for backwards
 | 
			
		||||
compatibility, and the author failed to realize the cascading consequences of
 | 
			
		||||
such a name-change. To fix Glide, see [these
 | 
			
		||||
comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
 | 
			
		||||
 | 
			
		||||
Nicely color-coded in development (when a TTY is attached, otherwise just
 | 
			
		||||
plain text):
 | 
			
		||||
 | 
			
		||||
@@ -46,6 +57,12 @@ time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x20822
 | 
			
		||||
exit status 1
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Case-sensitivity
 | 
			
		||||
 | 
			
		||||
The organization's name was changed to lower-case--and this will not be changed
 | 
			
		||||
back. If you are getting import conflicts due to case sensitivity, please use
 | 
			
		||||
the lower-case import: `github.com/sirupsen/logrus`.
 | 
			
		||||
 | 
			
		||||
#### Example
 | 
			
		||||
 | 
			
		||||
The simplest way to use Logrus is simply the package-level exported logger:
 | 
			
		||||
@@ -54,7 +71,7 @@ The simplest way to use Logrus is simply the package-level exported logger:
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
  log "github.com/Sirupsen/logrus"
 | 
			
		||||
  log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
@@ -65,7 +82,7 @@ func main() {
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note that it's completely api-compatible with the stdlib logger, so you can
 | 
			
		||||
replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"`
 | 
			
		||||
replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"`
 | 
			
		||||
and you'll now have the flexibility of Logrus. You can customize it all you
 | 
			
		||||
want:
 | 
			
		||||
 | 
			
		||||
@@ -74,15 +91,16 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
  "os"
 | 
			
		||||
  log "github.com/Sirupsen/logrus"
 | 
			
		||||
  log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
  // Log as JSON instead of the default ASCII formatter.
 | 
			
		||||
  log.SetFormatter(&log.JSONFormatter{})
 | 
			
		||||
 | 
			
		||||
  // Output to stderr instead of stdout, could also be a file.
 | 
			
		||||
  log.SetOutput(os.Stderr)
 | 
			
		||||
  // Output to stdout instead of the default stderr
 | 
			
		||||
  // Can be any io.Writer, see below for File example
 | 
			
		||||
  log.SetOutput(os.Stdout)
 | 
			
		||||
 | 
			
		||||
  // Only log the warning severity or above.
 | 
			
		||||
  log.SetLevel(log.WarnLevel)
 | 
			
		||||
@@ -123,7 +141,8 @@ application, you can also create an instance of the `logrus` Logger:
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
  "github.com/Sirupsen/logrus"
 | 
			
		||||
  "os"
 | 
			
		||||
  "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Create a new instance of the logger. You can have any number of instances.
 | 
			
		||||
@@ -132,7 +151,15 @@ var log = logrus.New()
 | 
			
		||||
func main() {
 | 
			
		||||
  // The API for setting attributes is a little different than the package level
 | 
			
		||||
  // exported logger. See Godoc.
 | 
			
		||||
  log.Out = os.Stderr
 | 
			
		||||
  log.Out = os.Stdout
 | 
			
		||||
 | 
			
		||||
  // You could set this to any `io.Writer` such as a file
 | 
			
		||||
  // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
 | 
			
		||||
  // if err == nil {
 | 
			
		||||
  //  log.Out = file
 | 
			
		||||
  // } else {
 | 
			
		||||
  //  log.Info("Failed to log to file, using default stderr")
 | 
			
		||||
  // }
 | 
			
		||||
 | 
			
		||||
  log.WithFields(logrus.Fields{
 | 
			
		||||
    "animal": "walrus",
 | 
			
		||||
@@ -143,7 +170,7 @@ func main() {
 | 
			
		||||
 | 
			
		||||
#### Fields
 | 
			
		||||
 | 
			
		||||
Logrus encourages careful, structured logging though logging fields instead of
 | 
			
		||||
Logrus encourages careful, structured logging through logging fields instead of
 | 
			
		||||
long, unparseable error messages. For example, instead of: `log.Fatalf("Failed
 | 
			
		||||
to send event %s to topic %s with key %d")`, you should log the much more
 | 
			
		||||
discoverable:
 | 
			
		||||
@@ -165,6 +192,20 @@ In general, with Logrus using any of the `printf`-family functions should be
 | 
			
		||||
seen as a hint you should add a field, however, you can still use the
 | 
			
		||||
`printf`-family functions with Logrus.
 | 
			
		||||
 | 
			
		||||
#### Default Fields
 | 
			
		||||
 | 
			
		||||
Often it's helpful to have fields _always_ attached to log statements in an
 | 
			
		||||
application or parts of one. For example, you may want to always log the
 | 
			
		||||
`request_id` and `user_ip` in the context of a request. Instead of writing
 | 
			
		||||
`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on
 | 
			
		||||
every line, you can create a `logrus.Entry` to pass around instead:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
 | 
			
		||||
requestLogger.Info("something happened on that request") # will log request_id and user_ip
 | 
			
		||||
requestLogger.Warn("something not great happened")
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Hooks
 | 
			
		||||
 | 
			
		||||
You can add hooks for logging levels. For example to send errors to an exception
 | 
			
		||||
@@ -176,9 +217,9 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
  log "github.com/Sirupsen/logrus"
 | 
			
		||||
  log "github.com/sirupsen/logrus"
 | 
			
		||||
  "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
 | 
			
		||||
  logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
 | 
			
		||||
  logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
 | 
			
		||||
  "log/syslog"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -200,40 +241,51 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
 | 
			
		||||
 | 
			
		||||
| Hook  | Description |
 | 
			
		||||
| ----- | ----------- |
 | 
			
		||||
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
 | 
			
		||||
| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
 | 
			
		||||
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
 | 
			
		||||
| [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. |
 | 
			
		||||
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
 | 
			
		||||
| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
 | 
			
		||||
| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
 | 
			
		||||
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
 | 
			
		||||
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
 | 
			
		||||
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
 | 
			
		||||
| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
 | 
			
		||||
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
 | 
			
		||||
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
 | 
			
		||||
| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
 | 
			
		||||
| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
 | 
			
		||||
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
 | 
			
		||||
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
 | 
			
		||||
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
 | 
			
		||||
| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) |
 | 
			
		||||
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
 | 
			
		||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
 | 
			
		||||
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
 | 
			
		||||
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
 | 
			
		||||
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
 | 
			
		||||
| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) |
 | 
			
		||||
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
 | 
			
		||||
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
 | 
			
		||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
 | 
			
		||||
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
 | 
			
		||||
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
 | 
			
		||||
| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) |
 | 
			
		||||
| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
 | 
			
		||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
 | 
			
		||||
| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)|
 | 
			
		||||
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
 | 
			
		||||
| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
 | 
			
		||||
| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/)
 | 
			
		||||
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
 | 
			
		||||
| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) |
 | 
			
		||||
| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
 | 
			
		||||
| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
 | 
			
		||||
| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
 | 
			
		||||
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
 | 
			
		||||
| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) |
 | 
			
		||||
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
 | 
			
		||||
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
 | 
			
		||||
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
 | 
			
		||||
| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) |
 | 
			
		||||
| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) |
 | 
			
		||||
| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
 | 
			
		||||
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
 | 
			
		||||
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
 | 
			
		||||
| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
 | 
			
		||||
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
 | 
			
		||||
| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) |
 | 
			
		||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
 | 
			
		||||
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
 | 
			
		||||
| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) |
 | 
			
		||||
| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
 | 
			
		||||
 | 
			
		||||
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
 | 
			
		||||
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
 | 
			
		||||
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
 | 
			
		||||
| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)|
 | 
			
		||||
| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
 | 
			
		||||
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
 | 
			
		||||
| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) |
 | 
			
		||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
 | 
			
		||||
| [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. |
 | 
			
		||||
| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
 | 
			
		||||
| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
 | 
			
		||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
 | 
			
		||||
| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
 | 
			
		||||
| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) |
 | 
			
		||||
 | 
			
		||||
#### Level logging
 | 
			
		||||
 | 
			
		||||
@@ -282,7 +334,7 @@ could do:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
  log "github.com/Sirupsen/logrus"
 | 
			
		||||
  log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
init() {
 | 
			
		||||
@@ -309,8 +361,11 @@ The built-in logging formatters are:
 | 
			
		||||
  without colors.
 | 
			
		||||
  * *Note:* to force colored output when there is no TTY, set the `ForceColors`
 | 
			
		||||
    field to `true`.  To force no colored output even if there is a TTY  set the
 | 
			
		||||
    `DisableColors` field to `true`
 | 
			
		||||
    `DisableColors` field to `true`. For Windows, see
 | 
			
		||||
    [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
 | 
			
		||||
  * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
 | 
			
		||||
* `logrus.JSONFormatter`. Logs fields as JSON.
 | 
			
		||||
  * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
 | 
			
		||||
 | 
			
		||||
Third party logging formatters:
 | 
			
		||||
 | 
			
		||||
@@ -359,6 +414,18 @@ srv := http.Server{
 | 
			
		||||
Each line written to that writer will be printed the usual way, using formatters
 | 
			
		||||
and hooks. The level for those entries is `info`.
 | 
			
		||||
 | 
			
		||||
This means that we can override the standard library logger easily:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
logger := logrus.New()
 | 
			
		||||
logger.Formatter = &logrus.JSONFormatter{}
 | 
			
		||||
 | 
			
		||||
// Use logrus for standard log output
 | 
			
		||||
// Note that `log` here references stdlib's log
 | 
			
		||||
// Not logrus imported under the name `log`.
 | 
			
		||||
log.SetOutput(logger.Writer())
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Rotation
 | 
			
		||||
 | 
			
		||||
Log rotation is not provided with Logrus. Log rotation should be done by an
 | 
			
		||||
@@ -370,7 +437,7 @@ entries. It should not be a feature of the application-level logger.
 | 
			
		||||
| Tool | Description |
 | 
			
		||||
| ---- | ----------- |
 | 
			
		||||
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
 | 
			
		||||
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper arround Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
 | 
			
		||||
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
 | 
			
		||||
 | 
			
		||||
#### Testing
 | 
			
		||||
 | 
			
		||||
@@ -380,15 +447,24 @@ Logrus has a built in facility for asserting the presence of log messages. This
 | 
			
		||||
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
logger, hook := NewNullLogger()
 | 
			
		||||
logger.Error("Hello error")
 | 
			
		||||
import(
 | 
			
		||||
  "github.com/sirupsen/logrus"
 | 
			
		||||
  "github.com/sirupsen/logrus/hooks/null"
 | 
			
		||||
  "github.com/stretchr/testify/assert"
 | 
			
		||||
  "testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
assert.Equal(1, len(hook.Entries))
 | 
			
		||||
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
 | 
			
		||||
assert.Equal("Hello error", hook.LastEntry().Message)
 | 
			
		||||
func TestSomething(t*testing.T){
 | 
			
		||||
  logger, hook := null.NewNullLogger()
 | 
			
		||||
  logger.Error("Helloerror")
 | 
			
		||||
 | 
			
		||||
hook.Reset()
 | 
			
		||||
assert.Nil(hook.LastEntry())
 | 
			
		||||
  assert.Equal(t, 1, len(hook.Entries))
 | 
			
		||||
  assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level)
 | 
			
		||||
  assert.Equal(t, "Helloerror", hook.LastEntry().Message)
 | 
			
		||||
 | 
			
		||||
  hook.Reset()
 | 
			
		||||
  assert.Nil(t, hook.LastEntry())
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Fatal handlers
 | 
			
		||||
@@ -407,7 +483,7 @@ logrus.RegisterExitHandler(handler)
 | 
			
		||||
...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Thread safty
 | 
			
		||||
#### Thread safety
 | 
			
		||||
 | 
			
		||||
By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
 | 
			
		||||
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
// The following code was sourced and modified from the
 | 
			
		||||
// https://bitbucket.org/tebeka/atexit package governed by the following license:
 | 
			
		||||
// https://github.com/tebeka/atexit package governed by the following license:
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 Miki Tebeka <miki.tebeka@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
							
								
								
									
										74
									
								
								vendor/github.com/sirupsen/logrus/alt_exit_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/sirupsen/logrus/alt_exit_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestRegister(t *testing.T) {
 | 
			
		||||
	current := len(handlers)
 | 
			
		||||
	RegisterExitHandler(func() {})
 | 
			
		||||
	if len(handlers) != current+1 {
 | 
			
		||||
		t.Fatalf("can't add handler")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestHandler(t *testing.T) {
 | 
			
		||||
	gofile := "/tmp/testprog.go"
 | 
			
		||||
	if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil {
 | 
			
		||||
		t.Fatalf("can't create go file")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	outfile := "/tmp/testprog.out"
 | 
			
		||||
	arg := time.Now().UTC().String()
 | 
			
		||||
	err := exec.Command("go", "run", gofile, outfile, arg).Run()
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Fatalf("completed normally, should have failed")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := ioutil.ReadFile(outfile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("can't read output file %s", outfile)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if string(data) != arg {
 | 
			
		||||
		t.Fatalf("bad data")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var testprog = []byte(`
 | 
			
		||||
// Test program for atexit, gets output file and data as arguments and writes
 | 
			
		||||
// data to output file in atexit handler.
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var outfile = ""
 | 
			
		||||
var data = ""
 | 
			
		||||
 | 
			
		||||
func handler() {
 | 
			
		||||
	ioutil.WriteFile(outfile, []byte(data), 0666)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func badHandler() {
 | 
			
		||||
	n := 0
 | 
			
		||||
	fmt.Println(1/n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
	outfile = flag.Arg(0)
 | 
			
		||||
	data = flag.Arg(1)
 | 
			
		||||
 | 
			
		||||
	logrus.RegisterExitHandler(handler)
 | 
			
		||||
	logrus.RegisterExitHandler(badHandler)
 | 
			
		||||
	logrus.Fatal("Bye bye")
 | 
			
		||||
}
 | 
			
		||||
`)
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/Sirupsen/logrus/doc.go → vendor/github.com/sirupsen/logrus/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/Sirupsen/logrus/doc.go → vendor/github.com/sirupsen/logrus/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@ The simplest way to use Logrus is simply the package-level exported logger:
 | 
			
		||||
  package main
 | 
			
		||||
 | 
			
		||||
  import (
 | 
			
		||||
    log "github.com/Sirupsen/logrus"
 | 
			
		||||
    log "github.com/sirupsen/logrus"
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  func main() {
 | 
			
		||||
@@ -21,6 +21,6 @@ The simplest way to use Logrus is simply the package-level exported logger:
 | 
			
		||||
Output:
 | 
			
		||||
  time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
 | 
			
		||||
 | 
			
		||||
For a full guide visit https://github.com/Sirupsen/logrus
 | 
			
		||||
For a full guide visit https://github.com/sirupsen/logrus
 | 
			
		||||
*/
 | 
			
		||||
package logrus
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/github.com/Sirupsen/logrus/entry.go → vendor/github.com/sirupsen/logrus/entry.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/Sirupsen/logrus/entry.go → vendor/github.com/sirupsen/logrus/entry.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -126,7 +126,7 @@ func (entry Entry) log(level Level, msg string) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Debug(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= DebugLevel {
 | 
			
		||||
	if entry.Logger.level() >= DebugLevel {
 | 
			
		||||
		entry.log(DebugLevel, fmt.Sprint(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -136,13 +136,13 @@ func (entry *Entry) Print(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Info(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= InfoLevel {
 | 
			
		||||
	if entry.Logger.level() >= InfoLevel {
 | 
			
		||||
		entry.log(InfoLevel, fmt.Sprint(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Warn(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= WarnLevel {
 | 
			
		||||
	if entry.Logger.level() >= WarnLevel {
 | 
			
		||||
		entry.log(WarnLevel, fmt.Sprint(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -152,20 +152,20 @@ func (entry *Entry) Warning(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Error(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= ErrorLevel {
 | 
			
		||||
	if entry.Logger.level() >= ErrorLevel {
 | 
			
		||||
		entry.log(ErrorLevel, fmt.Sprint(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Fatal(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= FatalLevel {
 | 
			
		||||
	if entry.Logger.level() >= FatalLevel {
 | 
			
		||||
		entry.log(FatalLevel, fmt.Sprint(args...))
 | 
			
		||||
	}
 | 
			
		||||
	Exit(1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Panic(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= PanicLevel {
 | 
			
		||||
	if entry.Logger.level() >= PanicLevel {
 | 
			
		||||
		entry.log(PanicLevel, fmt.Sprint(args...))
 | 
			
		||||
	}
 | 
			
		||||
	panic(fmt.Sprint(args...))
 | 
			
		||||
@@ -174,13 +174,13 @@ func (entry *Entry) Panic(args ...interface{}) {
 | 
			
		||||
// Entry Printf family functions
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Debugf(format string, args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= DebugLevel {
 | 
			
		||||
	if entry.Logger.level() >= DebugLevel {
 | 
			
		||||
		entry.Debug(fmt.Sprintf(format, args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Infof(format string, args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= InfoLevel {
 | 
			
		||||
	if entry.Logger.level() >= InfoLevel {
 | 
			
		||||
		entry.Info(fmt.Sprintf(format, args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -190,7 +190,7 @@ func (entry *Entry) Printf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Warnf(format string, args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= WarnLevel {
 | 
			
		||||
	if entry.Logger.level() >= WarnLevel {
 | 
			
		||||
		entry.Warn(fmt.Sprintf(format, args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -200,20 +200,20 @@ func (entry *Entry) Warningf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Errorf(format string, args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= ErrorLevel {
 | 
			
		||||
	if entry.Logger.level() >= ErrorLevel {
 | 
			
		||||
		entry.Error(fmt.Sprintf(format, args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Fatalf(format string, args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= FatalLevel {
 | 
			
		||||
	if entry.Logger.level() >= FatalLevel {
 | 
			
		||||
		entry.Fatal(fmt.Sprintf(format, args...))
 | 
			
		||||
	}
 | 
			
		||||
	Exit(1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Panicf(format string, args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= PanicLevel {
 | 
			
		||||
	if entry.Logger.level() >= PanicLevel {
 | 
			
		||||
		entry.Panic(fmt.Sprintf(format, args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -221,13 +221,13 @@ func (entry *Entry) Panicf(format string, args ...interface{}) {
 | 
			
		||||
// Entry Println family functions
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Debugln(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= DebugLevel {
 | 
			
		||||
	if entry.Logger.level() >= DebugLevel {
 | 
			
		||||
		entry.Debug(entry.sprintlnn(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Infoln(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= InfoLevel {
 | 
			
		||||
	if entry.Logger.level() >= InfoLevel {
 | 
			
		||||
		entry.Info(entry.sprintlnn(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -237,7 +237,7 @@ func (entry *Entry) Println(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Warnln(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= WarnLevel {
 | 
			
		||||
	if entry.Logger.level() >= WarnLevel {
 | 
			
		||||
		entry.Warn(entry.sprintlnn(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -247,20 +247,20 @@ func (entry *Entry) Warningln(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Errorln(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= ErrorLevel {
 | 
			
		||||
	if entry.Logger.level() >= ErrorLevel {
 | 
			
		||||
		entry.Error(entry.sprintlnn(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Fatalln(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= FatalLevel {
 | 
			
		||||
	if entry.Logger.level() >= FatalLevel {
 | 
			
		||||
		entry.Fatal(entry.sprintlnn(args...))
 | 
			
		||||
	}
 | 
			
		||||
	Exit(1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Panicln(args ...interface{}) {
 | 
			
		||||
	if entry.Logger.Level >= PanicLevel {
 | 
			
		||||
	if entry.Logger.level() >= PanicLevel {
 | 
			
		||||
		entry.Panic(entry.sprintlnn(args...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								vendor/github.com/sirupsen/logrus/entry_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/github.com/sirupsen/logrus/entry_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestEntryWithError(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	assert := assert.New(t)
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		ErrorKey = "error"
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	err := fmt.Errorf("kaboom at layer %d", 4711)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(err, WithError(err).Data["error"])
 | 
			
		||||
 | 
			
		||||
	logger := New()
 | 
			
		||||
	logger.Out = &bytes.Buffer{}
 | 
			
		||||
	entry := NewEntry(logger)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(err, entry.WithError(err).Data["error"])
 | 
			
		||||
 | 
			
		||||
	ErrorKey = "err"
 | 
			
		||||
 | 
			
		||||
	assert.Equal(err, entry.WithError(err).Data["err"])
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								vendor/github.com/sirupsen/logrus/examples/basic/basic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								vendor/github.com/sirupsen/logrus/examples/basic/basic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	// "os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var log = logrus.New()
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	log.Formatter = new(logrus.JSONFormatter)
 | 
			
		||||
	log.Formatter = new(logrus.TextFormatter) // default
 | 
			
		||||
 | 
			
		||||
	// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
 | 
			
		||||
	// if err == nil {
 | 
			
		||||
	// 	log.Out = file
 | 
			
		||||
	// } else {
 | 
			
		||||
	// 	log.Info("Failed to log to file, using default stderr")
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	log.Level = logrus.DebugLevel
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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{
 | 
			
		||||
		"animal": "walrus",
 | 
			
		||||
		"size":   10,
 | 
			
		||||
	}).Info("A group of walrus emerges from the ocean")
 | 
			
		||||
 | 
			
		||||
	log.WithFields(logrus.Fields{
 | 
			
		||||
		"omg":    true,
 | 
			
		||||
		"number": 122,
 | 
			
		||||
	}).Warn("The group's number increased tremendously!")
 | 
			
		||||
 | 
			
		||||
	log.WithFields(logrus.Fields{
 | 
			
		||||
		"temperature": -4,
 | 
			
		||||
	}).Debug("Temperature changes")
 | 
			
		||||
 | 
			
		||||
	log.WithFields(logrus.Fields{
 | 
			
		||||
		"animal": "orca",
 | 
			
		||||
		"size":   9009,
 | 
			
		||||
	}).Panic("It's over 9000!")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/sirupsen/logrus/examples/hook/hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/sirupsen/logrus/examples/hook/hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	"gopkg.in/gemnasium/logrus-airbrake-hook.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var log = logrus.New()
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	log.Formatter = new(logrus.TextFormatter) // default
 | 
			
		||||
	log.Hooks.Add(airbrake.NewHook(123, "xyz", "development"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	log.WithFields(logrus.Fields{
 | 
			
		||||
		"animal": "walrus",
 | 
			
		||||
		"size":   10,
 | 
			
		||||
	}).Info("A group of walrus emerges from the ocean")
 | 
			
		||||
 | 
			
		||||
	log.WithFields(logrus.Fields{
 | 
			
		||||
		"omg":    true,
 | 
			
		||||
		"number": 122,
 | 
			
		||||
	}).Warn("The group's number increased tremendously!")
 | 
			
		||||
 | 
			
		||||
	log.WithFields(logrus.Fields{
 | 
			
		||||
		"omg":    true,
 | 
			
		||||
		"number": 100,
 | 
			
		||||
	}).Fatal("The ice breaks!")
 | 
			
		||||
}
 | 
			
		||||
@@ -31,14 +31,14 @@ func SetFormatter(formatter Formatter) {
 | 
			
		||||
func SetLevel(level Level) {
 | 
			
		||||
	std.mu.Lock()
 | 
			
		||||
	defer std.mu.Unlock()
 | 
			
		||||
	std.Level = level
 | 
			
		||||
	std.setLevel(level)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetLevel returns the standard logger level.
 | 
			
		||||
func GetLevel() Level {
 | 
			
		||||
	std.mu.Lock()
 | 
			
		||||
	defer std.mu.Unlock()
 | 
			
		||||
	return std.Level
 | 
			
		||||
	return std.level()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddHook adds a hook to the standard logger hooks.
 | 
			
		||||
							
								
								
									
										101
									
								
								vendor/github.com/sirupsen/logrus/formatter_bench_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								vendor/github.com/sirupsen/logrus/formatter_bench_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// smallFields is a small size data set for benchmarking
 | 
			
		||||
var smallFields = Fields{
 | 
			
		||||
	"foo":   "bar",
 | 
			
		||||
	"baz":   "qux",
 | 
			
		||||
	"one":   "two",
 | 
			
		||||
	"three": "four",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// largeFields is a large size data set for benchmarking
 | 
			
		||||
var largeFields = Fields{
 | 
			
		||||
	"foo":       "bar",
 | 
			
		||||
	"baz":       "qux",
 | 
			
		||||
	"one":       "two",
 | 
			
		||||
	"three":     "four",
 | 
			
		||||
	"five":      "six",
 | 
			
		||||
	"seven":     "eight",
 | 
			
		||||
	"nine":      "ten",
 | 
			
		||||
	"eleven":    "twelve",
 | 
			
		||||
	"thirteen":  "fourteen",
 | 
			
		||||
	"fifteen":   "sixteen",
 | 
			
		||||
	"seventeen": "eighteen",
 | 
			
		||||
	"nineteen":  "twenty",
 | 
			
		||||
	"a":         "b",
 | 
			
		||||
	"c":         "d",
 | 
			
		||||
	"e":         "f",
 | 
			
		||||
	"g":         "h",
 | 
			
		||||
	"i":         "j",
 | 
			
		||||
	"k":         "l",
 | 
			
		||||
	"m":         "n",
 | 
			
		||||
	"o":         "p",
 | 
			
		||||
	"q":         "r",
 | 
			
		||||
	"s":         "t",
 | 
			
		||||
	"u":         "v",
 | 
			
		||||
	"w":         "x",
 | 
			
		||||
	"y":         "z",
 | 
			
		||||
	"this":      "will",
 | 
			
		||||
	"make":      "thirty",
 | 
			
		||||
	"entries":   "yeah",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errorFields = Fields{
 | 
			
		||||
	"foo": fmt.Errorf("bar"),
 | 
			
		||||
	"baz": fmt.Errorf("qux"),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkErrorTextFormatter(b *testing.B) {
 | 
			
		||||
	doBenchmark(b, &TextFormatter{DisableColors: true}, errorFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkSmallTextFormatter(b *testing.B) {
 | 
			
		||||
	doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkLargeTextFormatter(b *testing.B) {
 | 
			
		||||
	doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkSmallColoredTextFormatter(b *testing.B) {
 | 
			
		||||
	doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkLargeColoredTextFormatter(b *testing.B) {
 | 
			
		||||
	doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkSmallJSONFormatter(b *testing.B) {
 | 
			
		||||
	doBenchmark(b, &JSONFormatter{}, smallFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkLargeJSONFormatter(b *testing.B) {
 | 
			
		||||
	doBenchmark(b, &JSONFormatter{}, largeFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
 | 
			
		||||
	logger := New()
 | 
			
		||||
 | 
			
		||||
	entry := &Entry{
 | 
			
		||||
		Time:    time.Time{},
 | 
			
		||||
		Level:   InfoLevel,
 | 
			
		||||
		Message: "message",
 | 
			
		||||
		Data:    fields,
 | 
			
		||||
		Logger:  logger,
 | 
			
		||||
	}
 | 
			
		||||
	var d []byte
 | 
			
		||||
	var err error
 | 
			
		||||
	for i := 0; i < b.N; i++ {
 | 
			
		||||
		d, err = formatter.Format(entry)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			b.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		b.SetBytes(int64(len(d)))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										122
									
								
								vendor/github.com/sirupsen/logrus/hook_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								vendor/github.com/sirupsen/logrus/hook_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TestHook struct {
 | 
			
		||||
	Fired bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *TestHook) Fire(entry *Entry) error {
 | 
			
		||||
	hook.Fired = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *TestHook) Levels() []Level {
 | 
			
		||||
	return []Level{
 | 
			
		||||
		DebugLevel,
 | 
			
		||||
		InfoLevel,
 | 
			
		||||
		WarnLevel,
 | 
			
		||||
		ErrorLevel,
 | 
			
		||||
		FatalLevel,
 | 
			
		||||
		PanicLevel,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestHookFires(t *testing.T) {
 | 
			
		||||
	hook := new(TestHook)
 | 
			
		||||
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Hooks.Add(hook)
 | 
			
		||||
		assert.Equal(t, hook.Fired, false)
 | 
			
		||||
 | 
			
		||||
		log.Print("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, hook.Fired, true)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ModifyHook struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *ModifyHook) Fire(entry *Entry) error {
 | 
			
		||||
	entry.Data["wow"] = "whale"
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *ModifyHook) Levels() []Level {
 | 
			
		||||
	return []Level{
 | 
			
		||||
		DebugLevel,
 | 
			
		||||
		InfoLevel,
 | 
			
		||||
		WarnLevel,
 | 
			
		||||
		ErrorLevel,
 | 
			
		||||
		FatalLevel,
 | 
			
		||||
		PanicLevel,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestHookCanModifyEntry(t *testing.T) {
 | 
			
		||||
	hook := new(ModifyHook)
 | 
			
		||||
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Hooks.Add(hook)
 | 
			
		||||
		log.WithField("wow", "elephant").Print("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["wow"], "whale")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCanFireMultipleHooks(t *testing.T) {
 | 
			
		||||
	hook1 := new(ModifyHook)
 | 
			
		||||
	hook2 := new(TestHook)
 | 
			
		||||
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Hooks.Add(hook1)
 | 
			
		||||
		log.Hooks.Add(hook2)
 | 
			
		||||
 | 
			
		||||
		log.WithField("wow", "elephant").Print("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["wow"], "whale")
 | 
			
		||||
		assert.Equal(t, hook2.Fired, true)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ErrorHook struct {
 | 
			
		||||
	Fired bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *ErrorHook) Fire(entry *Entry) error {
 | 
			
		||||
	hook.Fired = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *ErrorHook) Levels() []Level {
 | 
			
		||||
	return []Level{
 | 
			
		||||
		ErrorLevel,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestErrorHookShouldntFireOnInfo(t *testing.T) {
 | 
			
		||||
	hook := new(ErrorHook)
 | 
			
		||||
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Hooks.Add(hook)
 | 
			
		||||
		log.Info("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, hook.Fired, false)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestErrorHookShouldFireOnError(t *testing.T) {
 | 
			
		||||
	hook := new(ErrorHook)
 | 
			
		||||
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Hooks.Add(hook)
 | 
			
		||||
		log.Error("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, hook.Fired, true)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/github.com/sirupsen/logrus/hooks/syslog/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/sirupsen/logrus/hooks/syslog/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
# Syslog Hooks for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
  "log/syslog"
 | 
			
		||||
  "github.com/sirupsen/logrus"
 | 
			
		||||
  logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
  log       := logrus.New()
 | 
			
		||||
  hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
 | 
			
		||||
 | 
			
		||||
  if err == nil {
 | 
			
		||||
    log.Hooks.Add(hook)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following.
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
  "log/syslog"
 | 
			
		||||
  "github.com/sirupsen/logrus"
 | 
			
		||||
  logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
  log       := logrus.New()
 | 
			
		||||
  hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
 | 
			
		||||
 | 
			
		||||
  if err == nil {
 | 
			
		||||
    log.Hooks.Add(hook)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										54
									
								
								vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
// +build !windows,!nacl,!plan9
 | 
			
		||||
 | 
			
		||||
package logrus_syslog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	"log/syslog"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SyslogHook to send logs via syslog.
 | 
			
		||||
type SyslogHook struct {
 | 
			
		||||
	Writer        *syslog.Writer
 | 
			
		||||
	SyslogNetwork string
 | 
			
		||||
	SyslogRaddr   string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates a hook to be added to an instance of logger. This is called with
 | 
			
		||||
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
 | 
			
		||||
// `if err == nil { log.Hooks.Add(hook) }`
 | 
			
		||||
func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
 | 
			
		||||
	w, err := syslog.Dial(network, raddr, priority, tag)
 | 
			
		||||
	return &SyslogHook{w, network, raddr}, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
 | 
			
		||||
	line, err := entry.String()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch entry.Level {
 | 
			
		||||
	case logrus.PanicLevel:
 | 
			
		||||
		return hook.Writer.Crit(line)
 | 
			
		||||
	case logrus.FatalLevel:
 | 
			
		||||
		return hook.Writer.Crit(line)
 | 
			
		||||
	case logrus.ErrorLevel:
 | 
			
		||||
		return hook.Writer.Err(line)
 | 
			
		||||
	case logrus.WarnLevel:
 | 
			
		||||
		return hook.Writer.Warning(line)
 | 
			
		||||
	case logrus.InfoLevel:
 | 
			
		||||
		return hook.Writer.Info(line)
 | 
			
		||||
	case logrus.DebugLevel:
 | 
			
		||||
		return hook.Writer.Debug(line)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *SyslogHook) Levels() []logrus.Level {
 | 
			
		||||
	return logrus.AllLevels
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/github.com/sirupsen/logrus/hooks/syslog/syslog_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/sirupsen/logrus/hooks/syslog/syslog_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
package logrus_syslog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	"log/syslog"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestLocalhostAddAndPrint(t *testing.T) {
 | 
			
		||||
	log := logrus.New()
 | 
			
		||||
	hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unable to connect to local syslog.")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Hooks.Add(hook)
 | 
			
		||||
 | 
			
		||||
	for _, level := range hook.Levels() {
 | 
			
		||||
		if len(log.Hooks[level]) != 1 {
 | 
			
		||||
			t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level]))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Info("Congratulations!")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								vendor/github.com/sirupsen/logrus/hooks/test/test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								vendor/github.com/sirupsen/logrus/hooks/test/test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
// The Test package is used for testing logrus. It is here for backwards
 | 
			
		||||
// compatibility from when logrus' organization was upper-case. Please use
 | 
			
		||||
// lower-case logrus and the `null` package instead of this one.
 | 
			
		||||
package test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Hook is a hook designed for dealing with logs in test scenarios.
 | 
			
		||||
type Hook struct {
 | 
			
		||||
	// Entries is an array of all entries that have been received by this hook.
 | 
			
		||||
	// For safe access, use the AllEntries() method, rather than reading this
 | 
			
		||||
	// value directly.
 | 
			
		||||
	Entries []*logrus.Entry
 | 
			
		||||
	mu      sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewGlobal installs a test hook for the global logger.
 | 
			
		||||
func NewGlobal() *Hook {
 | 
			
		||||
 | 
			
		||||
	hook := new(Hook)
 | 
			
		||||
	logrus.AddHook(hook)
 | 
			
		||||
 | 
			
		||||
	return hook
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewLocal installs a test hook for a given local logger.
 | 
			
		||||
func NewLocal(logger *logrus.Logger) *Hook {
 | 
			
		||||
 | 
			
		||||
	hook := new(Hook)
 | 
			
		||||
	logger.Hooks.Add(hook)
 | 
			
		||||
 | 
			
		||||
	return hook
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewNullLogger creates a discarding logger and installs the test hook.
 | 
			
		||||
func NewNullLogger() (*logrus.Logger, *Hook) {
 | 
			
		||||
 | 
			
		||||
	logger := logrus.New()
 | 
			
		||||
	logger.Out = ioutil.Discard
 | 
			
		||||
 | 
			
		||||
	return logger, NewLocal(logger)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Hook) Fire(e *logrus.Entry) error {
 | 
			
		||||
	t.mu.Lock()
 | 
			
		||||
	defer t.mu.Unlock()
 | 
			
		||||
	t.Entries = append(t.Entries, e)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Hook) Levels() []logrus.Level {
 | 
			
		||||
	return logrus.AllLevels
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LastEntry returns the last entry that was logged or nil.
 | 
			
		||||
func (t *Hook) LastEntry() *logrus.Entry {
 | 
			
		||||
	t.mu.RLock()
 | 
			
		||||
	defer t.mu.RUnlock()
 | 
			
		||||
	i := len(t.Entries) - 1
 | 
			
		||||
	if i < 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	// Make a copy, for safety
 | 
			
		||||
	e := *t.Entries[i]
 | 
			
		||||
	return &e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllEntries returns all entries that were logged.
 | 
			
		||||
func (t *Hook) AllEntries() []*logrus.Entry {
 | 
			
		||||
	t.mu.RLock()
 | 
			
		||||
	defer t.mu.RUnlock()
 | 
			
		||||
	// Make a copy so the returned value won't race with future log requests
 | 
			
		||||
	entries := make([]*logrus.Entry, len(t.Entries))
 | 
			
		||||
	for i, entry := range t.Entries {
 | 
			
		||||
		// Make a copy, for safety
 | 
			
		||||
		e := *entry
 | 
			
		||||
		entries[i] = &e
 | 
			
		||||
	}
 | 
			
		||||
	return entries
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reset removes all Entries from this test hook.
 | 
			
		||||
func (t *Hook) Reset() {
 | 
			
		||||
	t.mu.Lock()
 | 
			
		||||
	defer t.mu.Unlock()
 | 
			
		||||
	t.Entries = make([]*logrus.Entry, 0)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/github.com/sirupsen/logrus/hooks/test/test_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/sirupsen/logrus/hooks/test/test_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
package test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestAllHooks(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	assert := assert.New(t)
 | 
			
		||||
 | 
			
		||||
	logger, hook := NewNullLogger()
 | 
			
		||||
	assert.Nil(hook.LastEntry())
 | 
			
		||||
	assert.Equal(0, len(hook.Entries))
 | 
			
		||||
 | 
			
		||||
	logger.Error("Hello error")
 | 
			
		||||
	assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
 | 
			
		||||
	assert.Equal("Hello error", hook.LastEntry().Message)
 | 
			
		||||
	assert.Equal(1, len(hook.Entries))
 | 
			
		||||
 | 
			
		||||
	logger.Warn("Hello warning")
 | 
			
		||||
	assert.Equal(logrus.WarnLevel, hook.LastEntry().Level)
 | 
			
		||||
	assert.Equal("Hello warning", hook.LastEntry().Message)
 | 
			
		||||
	assert.Equal(2, len(hook.Entries))
 | 
			
		||||
 | 
			
		||||
	hook.Reset()
 | 
			
		||||
	assert.Nil(hook.LastEntry())
 | 
			
		||||
	assert.Equal(0, len(hook.Entries))
 | 
			
		||||
 | 
			
		||||
	hook = NewGlobal()
 | 
			
		||||
 | 
			
		||||
	logrus.Error("Hello error")
 | 
			
		||||
	assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
 | 
			
		||||
	assert.Equal("Hello error", hook.LastEntry().Message)
 | 
			
		||||
	assert.Equal(1, len(hook.Entries))
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								vendor/github.com/sirupsen/logrus/json_formatter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/sirupsen/logrus/json_formatter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type fieldKey string
 | 
			
		||||
type FieldMap map[fieldKey]string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	FieldKeyMsg   = "msg"
 | 
			
		||||
	FieldKeyLevel = "level"
 | 
			
		||||
	FieldKeyTime  = "time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (f FieldMap) resolve(key fieldKey) string {
 | 
			
		||||
	if k, ok := f[key]; ok {
 | 
			
		||||
		return k
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type JSONFormatter struct {
 | 
			
		||||
	// TimestampFormat sets the format used for marshaling timestamps.
 | 
			
		||||
	TimestampFormat string
 | 
			
		||||
 | 
			
		||||
	// DisableTimestamp allows disabling automatic timestamps in output
 | 
			
		||||
	DisableTimestamp bool
 | 
			
		||||
 | 
			
		||||
	// FieldMap allows users to customize the names of keys for various fields.
 | 
			
		||||
	// As an example:
 | 
			
		||||
	// formatter := &JSONFormatter{
 | 
			
		||||
	//   	FieldMap: FieldMap{
 | 
			
		||||
	// 		 FieldKeyTime: "@timestamp",
 | 
			
		||||
	// 		 FieldKeyLevel: "@level",
 | 
			
		||||
	// 		 FieldKeyMsg: "@message",
 | 
			
		||||
	//    },
 | 
			
		||||
	// }
 | 
			
		||||
	FieldMap FieldMap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 | 
			
		||||
	data := make(Fields, len(entry.Data)+3)
 | 
			
		||||
	for k, v := range entry.Data {
 | 
			
		||||
		switch v := v.(type) {
 | 
			
		||||
		case error:
 | 
			
		||||
			// Otherwise errors are ignored by `encoding/json`
 | 
			
		||||
			// https://github.com/sirupsen/logrus/issues/137
 | 
			
		||||
			data[k] = v.Error()
 | 
			
		||||
		default:
 | 
			
		||||
			data[k] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	prefixFieldClashes(data)
 | 
			
		||||
 | 
			
		||||
	timestampFormat := f.TimestampFormat
 | 
			
		||||
	if timestampFormat == "" {
 | 
			
		||||
		timestampFormat = DefaultTimestampFormat
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !f.DisableTimestamp {
 | 
			
		||||
		data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
 | 
			
		||||
	}
 | 
			
		||||
	data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
 | 
			
		||||
	data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
 | 
			
		||||
 | 
			
		||||
	serialized, err := json.Marshal(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return append(serialized, '\n'), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										199
									
								
								vendor/github.com/sirupsen/logrus/json_formatter_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								vendor/github.com/sirupsen/logrus/json_formatter_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,199 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"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")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestJSONMessageKey(t *testing.T) {
 | 
			
		||||
	formatter := &JSONFormatter{
 | 
			
		||||
		FieldMap: FieldMap{
 | 
			
		||||
			FieldKeyMsg: "message",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := formatter.Format(&Entry{Message: "oh hai"})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal("Unable to format entry: ", err)
 | 
			
		||||
	}
 | 
			
		||||
	s := string(b)
 | 
			
		||||
	if !(strings.Contains(s, "message") && strings.Contains(s, "oh hai")) {
 | 
			
		||||
		t.Fatal("Expected JSON to format message key")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestJSONLevelKey(t *testing.T) {
 | 
			
		||||
	formatter := &JSONFormatter{
 | 
			
		||||
		FieldMap: FieldMap{
 | 
			
		||||
			FieldKeyLevel: "somelevel",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := formatter.Format(WithField("level", "something"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal("Unable to format entry: ", err)
 | 
			
		||||
	}
 | 
			
		||||
	s := string(b)
 | 
			
		||||
	if !strings.Contains(s, "somelevel") {
 | 
			
		||||
		t.Fatal("Expected JSON to format level key")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestJSONTimeKey(t *testing.T) {
 | 
			
		||||
	formatter := &JSONFormatter{
 | 
			
		||||
		FieldMap: FieldMap{
 | 
			
		||||
			FieldKeyTime: "timeywimey",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := formatter.Format(WithField("level", "something"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal("Unable to format entry: ", err)
 | 
			
		||||
	}
 | 
			
		||||
	s := string(b)
 | 
			
		||||
	if !strings.Contains(s, "timeywimey") {
 | 
			
		||||
		t.Fatal("Expected JSON to format time key")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestJSONDisableTimestamp(t *testing.T) {
 | 
			
		||||
	formatter := &JSONFormatter{
 | 
			
		||||
		DisableTimestamp: true,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := formatter.Format(WithField("level", "something"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal("Unable to format entry: ", err)
 | 
			
		||||
	}
 | 
			
		||||
	s := string(b)
 | 
			
		||||
	if strings.Contains(s, FieldKeyTime) {
 | 
			
		||||
		t.Error("Did not prevent timestamp", s)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestJSONEnableTimestamp(t *testing.T) {
 | 
			
		||||
	formatter := &JSONFormatter{}
 | 
			
		||||
 | 
			
		||||
	b, err := formatter.Format(WithField("level", "something"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal("Unable to format entry: ", err)
 | 
			
		||||
	}
 | 
			
		||||
	s := string(b)
 | 
			
		||||
	if !strings.Contains(s, FieldKeyTime) {
 | 
			
		||||
		t.Error("Timestamp not present", s)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Logger struct {
 | 
			
		||||
@@ -112,7 +113,7 @@ func (logger *Logger) WithError(err error) *Entry {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Debugf(format string, args ...interface{}) {
 | 
			
		||||
	if logger.Level >= DebugLevel {
 | 
			
		||||
	if logger.level() >= DebugLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Debugf(format, args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -120,7 +121,7 @@ func (logger *Logger) Debugf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Infof(format string, args ...interface{}) {
 | 
			
		||||
	if logger.Level >= InfoLevel {
 | 
			
		||||
	if logger.level() >= InfoLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Infof(format, args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -134,7 +135,7 @@ func (logger *Logger) Printf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Warnf(format string, args ...interface{}) {
 | 
			
		||||
	if logger.Level >= WarnLevel {
 | 
			
		||||
	if logger.level() >= WarnLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Warnf(format, args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -142,7 +143,7 @@ func (logger *Logger) Warnf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Warningf(format string, args ...interface{}) {
 | 
			
		||||
	if logger.Level >= WarnLevel {
 | 
			
		||||
	if logger.level() >= WarnLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Warnf(format, args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -150,7 +151,7 @@ func (logger *Logger) Warningf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Errorf(format string, args ...interface{}) {
 | 
			
		||||
	if logger.Level >= ErrorLevel {
 | 
			
		||||
	if logger.level() >= ErrorLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Errorf(format, args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -158,7 +159,7 @@ func (logger *Logger) Errorf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Fatalf(format string, args ...interface{}) {
 | 
			
		||||
	if logger.Level >= FatalLevel {
 | 
			
		||||
	if logger.level() >= FatalLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Fatalf(format, args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -167,7 +168,7 @@ func (logger *Logger) Fatalf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Panicf(format string, args ...interface{}) {
 | 
			
		||||
	if logger.Level >= PanicLevel {
 | 
			
		||||
	if logger.level() >= PanicLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Panicf(format, args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -175,7 +176,7 @@ func (logger *Logger) Panicf(format string, args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Debug(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= DebugLevel {
 | 
			
		||||
	if logger.level() >= DebugLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Debug(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -183,7 +184,7 @@ func (logger *Logger) Debug(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Info(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= InfoLevel {
 | 
			
		||||
	if logger.level() >= InfoLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Info(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -197,7 +198,7 @@ func (logger *Logger) Print(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Warn(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= WarnLevel {
 | 
			
		||||
	if logger.level() >= WarnLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Warn(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -205,7 +206,7 @@ func (logger *Logger) Warn(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Warning(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= WarnLevel {
 | 
			
		||||
	if logger.level() >= WarnLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Warn(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -213,7 +214,7 @@ func (logger *Logger) Warning(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Error(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= ErrorLevel {
 | 
			
		||||
	if logger.level() >= ErrorLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Error(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -221,7 +222,7 @@ func (logger *Logger) Error(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Fatal(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= FatalLevel {
 | 
			
		||||
	if logger.level() >= FatalLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Fatal(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -230,7 +231,7 @@ func (logger *Logger) Fatal(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Panic(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= PanicLevel {
 | 
			
		||||
	if logger.level() >= PanicLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Panic(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -238,7 +239,7 @@ func (logger *Logger) Panic(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Debugln(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= DebugLevel {
 | 
			
		||||
	if logger.level() >= DebugLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Debugln(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -246,7 +247,7 @@ func (logger *Logger) Debugln(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Infoln(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= InfoLevel {
 | 
			
		||||
	if logger.level() >= InfoLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Infoln(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -260,7 +261,7 @@ func (logger *Logger) Println(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Warnln(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= WarnLevel {
 | 
			
		||||
	if logger.level() >= WarnLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Warnln(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -268,7 +269,7 @@ func (logger *Logger) Warnln(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Warningln(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= WarnLevel {
 | 
			
		||||
	if logger.level() >= WarnLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Warnln(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -276,7 +277,7 @@ func (logger *Logger) Warningln(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Errorln(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= ErrorLevel {
 | 
			
		||||
	if logger.level() >= ErrorLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Errorln(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -284,7 +285,7 @@ func (logger *Logger) Errorln(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Fatalln(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= FatalLevel {
 | 
			
		||||
	if logger.level() >= FatalLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Fatalln(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -293,7 +294,7 @@ func (logger *Logger) Fatalln(args ...interface{}) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) Panicln(args ...interface{}) {
 | 
			
		||||
	if logger.Level >= PanicLevel {
 | 
			
		||||
	if logger.level() >= PanicLevel {
 | 
			
		||||
		entry := logger.newEntry()
 | 
			
		||||
		entry.Panicln(args...)
 | 
			
		||||
		logger.releaseEntry(entry)
 | 
			
		||||
@@ -306,3 +307,11 @@ func (logger *Logger) Panicln(args ...interface{}) {
 | 
			
		||||
func (logger *Logger) SetNoLock() {
 | 
			
		||||
	logger.mu.Disable()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) level() Level {
 | 
			
		||||
	return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) setLevel(level Level) {
 | 
			
		||||
	atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								vendor/github.com/sirupsen/logrus/logger_bench_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/sirupsen/logrus/logger_bench_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// smallFields is a small size data set for benchmarking
 | 
			
		||||
var loggerFields = Fields{
 | 
			
		||||
	"foo":   "bar",
 | 
			
		||||
	"baz":   "qux",
 | 
			
		||||
	"one":   "two",
 | 
			
		||||
	"three": "four",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkDummyLogger(b *testing.B) {
 | 
			
		||||
	nullf, err := os.OpenFile("/dev/null", os.O_WRONLY, 0666)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatalf("%v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer nullf.Close()
 | 
			
		||||
	doLoggerBenchmark(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkDummyLoggerNoLock(b *testing.B) {
 | 
			
		||||
	nullf, err := os.OpenFile("/dev/null", os.O_WRONLY|os.O_APPEND, 0666)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatalf("%v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer nullf.Close()
 | 
			
		||||
	doLoggerBenchmarkNoLock(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doLoggerBenchmark(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
 | 
			
		||||
	logger := Logger{
 | 
			
		||||
		Out:       out,
 | 
			
		||||
		Level:     InfoLevel,
 | 
			
		||||
		Formatter: formatter,
 | 
			
		||||
	}
 | 
			
		||||
	entry := logger.WithFields(fields)
 | 
			
		||||
	b.RunParallel(func(pb *testing.PB) {
 | 
			
		||||
		for pb.Next() {
 | 
			
		||||
			entry.Info("aaa")
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doLoggerBenchmarkNoLock(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
 | 
			
		||||
	logger := Logger{
 | 
			
		||||
		Out:       out,
 | 
			
		||||
		Level:     InfoLevel,
 | 
			
		||||
		Formatter: formatter,
 | 
			
		||||
	}
 | 
			
		||||
	logger.SetNoLock()
 | 
			
		||||
	entry := logger.WithFields(fields)
 | 
			
		||||
	b.RunParallel(func(pb *testing.PB) {
 | 
			
		||||
		for pb.Next() {
 | 
			
		||||
			entry.Info("aaa")
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,7 @@ import (
 | 
			
		||||
type Fields map[string]interface{}
 | 
			
		||||
 | 
			
		||||
// Level type
 | 
			
		||||
type Level uint8
 | 
			
		||||
type Level uint32
 | 
			
		||||
 | 
			
		||||
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
 | 
			
		||||
func (level Level) String() string {
 | 
			
		||||
							
								
								
									
										386
									
								
								vendor/github.com/sirupsen/logrus/logrus_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										386
									
								
								vendor/github.com/sirupsen/logrus/logrus_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,386 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	var fields Fields
 | 
			
		||||
 | 
			
		||||
	logger := New()
 | 
			
		||||
	logger.Out = &buffer
 | 
			
		||||
	logger.Formatter = new(JSONFormatter)
 | 
			
		||||
 | 
			
		||||
	log(logger)
 | 
			
		||||
 | 
			
		||||
	err := json.Unmarshal(buffer.Bytes(), &fields)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	assertions(fields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
 | 
			
		||||
	logger := New()
 | 
			
		||||
	logger.Out = &buffer
 | 
			
		||||
	logger.Formatter = &TextFormatter{
 | 
			
		||||
		DisableColors: true,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log(logger)
 | 
			
		||||
 | 
			
		||||
	fields := make(map[string]string)
 | 
			
		||||
	for _, kv := range strings.Split(buffer.String(), " ") {
 | 
			
		||||
		if !strings.Contains(kv, "=") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		kvArr := strings.Split(kv, "=")
 | 
			
		||||
		key := strings.TrimSpace(kvArr[0])
 | 
			
		||||
		val := kvArr[1]
 | 
			
		||||
		if kvArr[1][0] == '"' {
 | 
			
		||||
			var err error
 | 
			
		||||
			val, err = strconv.Unquote(val)
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
		}
 | 
			
		||||
		fields[key] = val
 | 
			
		||||
	}
 | 
			
		||||
	assertions(fields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPrint(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Print("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test")
 | 
			
		||||
		assert.Equal(t, fields["level"], "info")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInfo(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Info("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test")
 | 
			
		||||
		assert.Equal(t, fields["level"], "info")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWarn(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Warn("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test")
 | 
			
		||||
		assert.Equal(t, fields["level"], "warning")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Infoln("test", "test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test test")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Infoln("test", 10)
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test 10")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Infoln(10, 10)
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "10 10")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Infoln(10, 10)
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "10 10")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Info("test", 10)
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test10")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.Info("test", "test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "testtest")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWithFieldsShouldAllowAssignments(t *testing.T) {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	var fields Fields
 | 
			
		||||
 | 
			
		||||
	logger := New()
 | 
			
		||||
	logger.Out = &buffer
 | 
			
		||||
	logger.Formatter = new(JSONFormatter)
 | 
			
		||||
 | 
			
		||||
	localLog := logger.WithFields(Fields{
 | 
			
		||||
		"key1": "value1",
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	localLog.WithField("key2", "value2").Info("test")
 | 
			
		||||
	err := json.Unmarshal(buffer.Bytes(), &fields)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, "value2", fields["key2"])
 | 
			
		||||
	assert.Equal(t, "value1", fields["key1"])
 | 
			
		||||
 | 
			
		||||
	buffer = bytes.Buffer{}
 | 
			
		||||
	fields = Fields{}
 | 
			
		||||
	localLog.Info("test")
 | 
			
		||||
	err = json.Unmarshal(buffer.Bytes(), &fields)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	_, ok := fields["key2"]
 | 
			
		||||
	assert.Equal(t, false, ok)
 | 
			
		||||
	assert.Equal(t, "value1", fields["key1"])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.WithField("msg", "hello").Info("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.WithField("msg", "hello").Info("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["msg"], "test")
 | 
			
		||||
		assert.Equal(t, fields["fields.msg"], "hello")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.WithField("time", "hello").Info("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["fields.time"], "hello")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
 | 
			
		||||
	LogAndAssertJSON(t, func(log *Logger) {
 | 
			
		||||
		log.WithField("level", 1).Info("test")
 | 
			
		||||
	}, func(fields Fields) {
 | 
			
		||||
		assert.Equal(t, fields["level"], "info")
 | 
			
		||||
		assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
 | 
			
		||||
	LogAndAssertText(t, func(log *Logger) {
 | 
			
		||||
		ll := log.WithField("herp", "derp")
 | 
			
		||||
		ll.Info("hello")
 | 
			
		||||
		ll.Info("bye")
 | 
			
		||||
	}, func(fields map[string]string) {
 | 
			
		||||
		for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
 | 
			
		||||
			if _, ok := fields[fieldName]; ok {
 | 
			
		||||
				t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
	assert.Equal(t, "debug", DebugLevel.String())
 | 
			
		||||
	assert.Equal(t, "info", InfoLevel.String())
 | 
			
		||||
	assert.Equal(t, "warning", WarnLevel.String())
 | 
			
		||||
	assert.Equal(t, "error", ErrorLevel.String())
 | 
			
		||||
	assert.Equal(t, "fatal", FatalLevel.String())
 | 
			
		||||
	assert.Equal(t, "panic", PanicLevel.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseLevel(t *testing.T) {
 | 
			
		||||
	l, err := ParseLevel("panic")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, PanicLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("PANIC")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, PanicLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("fatal")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, FatalLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("FATAL")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, FatalLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("error")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, ErrorLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("ERROR")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, ErrorLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("warn")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, WarnLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("WARN")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, WarnLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("warning")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, WarnLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("WARNING")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, WarnLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("info")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, InfoLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("INFO")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, InfoLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("debug")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, DebugLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("DEBUG")
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, DebugLevel, l)
 | 
			
		||||
 | 
			
		||||
	l, err = ParseLevel("invalid")
 | 
			
		||||
	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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLoggingRace(t *testing.T) {
 | 
			
		||||
	logger := New()
 | 
			
		||||
 | 
			
		||||
	var wg sync.WaitGroup
 | 
			
		||||
	wg.Add(100)
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 100; i++ {
 | 
			
		||||
		go func() {
 | 
			
		||||
			logger.Info("info")
 | 
			
		||||
			wg.Done()
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compile test
 | 
			
		||||
func TestLogrusInterface(t *testing.T) {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	fn := func(l FieldLogger) {
 | 
			
		||||
		b := l.WithField("key", "value")
 | 
			
		||||
		b.Debug("Test")
 | 
			
		||||
	}
 | 
			
		||||
	// test logger
 | 
			
		||||
	logger := New()
 | 
			
		||||
	logger.Out = &buffer
 | 
			
		||||
	fn(logger)
 | 
			
		||||
 | 
			
		||||
	// test Entry
 | 
			
		||||
	e := logger.WithField("another", "value")
 | 
			
		||||
	fn(e)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implements io.Writer using channels for synchronization, so we can wait on
 | 
			
		||||
// the Entry.Writer goroutine to write in a non-racey way. This does assume that
 | 
			
		||||
// there is a single call to Logger.Out for each message.
 | 
			
		||||
type channelWriter chan []byte
 | 
			
		||||
 | 
			
		||||
func (cw channelWriter) Write(p []byte) (int, error) {
 | 
			
		||||
	cw <- p
 | 
			
		||||
	return len(p), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEntryWriter(t *testing.T) {
 | 
			
		||||
	cw := channelWriter(make(chan []byte, 1))
 | 
			
		||||
	log := New()
 | 
			
		||||
	log.Out = cw
 | 
			
		||||
	log.Formatter = new(JSONFormatter)
 | 
			
		||||
	log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n"))
 | 
			
		||||
 | 
			
		||||
	bs := <-cw
 | 
			
		||||
	var fields Fields
 | 
			
		||||
	err := json.Unmarshal(bs, &fields)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, fields["foo"], "bar")
 | 
			
		||||
	assert.Equal(t, fields["level"], "warning")
 | 
			
		||||
}
 | 
			
		||||
@@ -2,7 +2,9 @@
 | 
			
		||||
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import "io"
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
 | 
			
		||||
func IsTerminal() bool {
 | 
			
		||||
func IsTerminal(f io.Writer) bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
@@ -9,14 +9,20 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
 | 
			
		||||
func IsTerminal() bool {
 | 
			
		||||
	fd := syscall.Stderr
 | 
			
		||||
func IsTerminal(f io.Writer) bool {
 | 
			
		||||
	var termios Termios
 | 
			
		||||
	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
 | 
			
		||||
	return err == 0
 | 
			
		||||
	switch v := f.(type) {
 | 
			
		||||
	case *os.File:
 | 
			
		||||
		_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(v.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
 | 
			
		||||
		return err == 0
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/sirupsen/logrus/terminal_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/sirupsen/logrus/terminal_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
// +build solaris,!appengine
 | 
			
		||||
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if the given file descriptor is a terminal.
 | 
			
		||||
func IsTerminal(f io.Writer) bool {
 | 
			
		||||
	switch v := f.(type) {
 | 
			
		||||
	case *os.File:
 | 
			
		||||
		_, err := unix.IoctlGetTermios(int(v.Fd()), unix.TCGETA)
 | 
			
		||||
		return err == nil
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								vendor/github.com/sirupsen/logrus/terminal_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								vendor/github.com/sirupsen/logrus/terminal_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
// Based on ssh/terminal:
 | 
			
		||||
// Copyright 2011 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build windows,!appengine
 | 
			
		||||
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
 | 
			
		||||
	procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	enableProcessedOutput           = 0x0001
 | 
			
		||||
	enableWrapAtEolOutput           = 0x0002
 | 
			
		||||
	enableVirtualTerminalProcessing = 0x0004
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getVersion() (float64, error) {
 | 
			
		||||
	stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}
 | 
			
		||||
	cmd := exec.Command("cmd", "ver")
 | 
			
		||||
	cmd.Stdout = stdout
 | 
			
		||||
	cmd.Stderr = stderr
 | 
			
		||||
	err := cmd.Run()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, err
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// The output should be like "Microsoft Windows [Version XX.X.XXXXXX]"
 | 
			
		||||
	version := strings.Replace(stdout.String(), "\n", "", -1)
 | 
			
		||||
	version = strings.Replace(version, "\r\n", "", -1)
 | 
			
		||||
 | 
			
		||||
	x1 := strings.Index(version, "[Version")
 | 
			
		||||
 | 
			
		||||
	if x1 == -1 || strings.Index(version, "]") == -1 {
 | 
			
		||||
		return -1, errors.New("Can't determine Windows version")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return strconv.ParseFloat(version[x1+9:x1+13], 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	ver, err := getVersion()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Activate Virtual Processing for Windows CMD
 | 
			
		||||
	// Info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
 | 
			
		||||
	if ver >= 10 {
 | 
			
		||||
		handle := syscall.Handle(os.Stderr.Fd())
 | 
			
		||||
		procSetConsoleMode.Call(uintptr(handle), enableProcessedOutput|enableWrapAtEolOutput|enableVirtualTerminalProcessing)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
 | 
			
		||||
func IsTerminal(f io.Writer) bool {
 | 
			
		||||
	switch v := f.(type) {
 | 
			
		||||
	case *os.File:
 | 
			
		||||
		var st uint32
 | 
			
		||||
		r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(v.Fd()), uintptr(unsafe.Pointer(&st)), 0)
 | 
			
		||||
		return r != 0 && e == 0
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -3,9 +3,9 @@ package logrus
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -20,16 +20,10 @@ const (
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	baseTimestamp time.Time
 | 
			
		||||
	isTerminal    bool
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	baseTimestamp = time.Now()
 | 
			
		||||
	isTerminal = IsTerminal()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func miniTS() int {
 | 
			
		||||
	return int(time.Since(baseTimestamp) / time.Second)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TextFormatter struct {
 | 
			
		||||
@@ -54,11 +48,32 @@ type TextFormatter struct {
 | 
			
		||||
	// that log extremely frequently and don't use the JSON formatter this may not
 | 
			
		||||
	// be desired.
 | 
			
		||||
	DisableSorting bool
 | 
			
		||||
 | 
			
		||||
	// QuoteEmptyFields will wrap empty fields in quotes if true
 | 
			
		||||
	QuoteEmptyFields bool
 | 
			
		||||
 | 
			
		||||
	// QuoteCharacter can be set to the override the default quoting character "
 | 
			
		||||
	// with something else. For example: ', or `.
 | 
			
		||||
	QuoteCharacter string
 | 
			
		||||
 | 
			
		||||
	// Whether the logger's out is to a terminal
 | 
			
		||||
	isTerminal bool
 | 
			
		||||
 | 
			
		||||
	sync.Once
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *TextFormatter) init(entry *Entry) {
 | 
			
		||||
	if len(f.QuoteCharacter) == 0 {
 | 
			
		||||
		f.QuoteCharacter = "\""
 | 
			
		||||
	}
 | 
			
		||||
	if entry.Logger != nil {
 | 
			
		||||
		f.isTerminal = IsTerminal(entry.Logger.Out)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
 | 
			
		||||
	var b *bytes.Buffer
 | 
			
		||||
	var keys []string = make([]string, 0, len(entry.Data))
 | 
			
		||||
	keys := make([]string, 0, len(entry.Data))
 | 
			
		||||
	for k := range entry.Data {
 | 
			
		||||
		keys = append(keys, k)
 | 
			
		||||
	}
 | 
			
		||||
@@ -74,8 +89,9 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
 | 
			
		||||
 | 
			
		||||
	prefixFieldClashes(entry.Data)
 | 
			
		||||
 | 
			
		||||
	isColorTerminal := isTerminal && (runtime.GOOS != "windows")
 | 
			
		||||
	isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors
 | 
			
		||||
	f.Do(func() { f.init(entry) })
 | 
			
		||||
 | 
			
		||||
	isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
 | 
			
		||||
 | 
			
		||||
	timestampFormat := f.TimestampFormat
 | 
			
		||||
	if timestampFormat == "" {
 | 
			
		||||
@@ -115,8 +131,10 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
 | 
			
		||||
 | 
			
		||||
	levelText := strings.ToUpper(entry.Level.String())[0:4]
 | 
			
		||||
 | 
			
		||||
	if !f.FullTimestamp {
 | 
			
		||||
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
 | 
			
		||||
	if f.DisableTimestamp {
 | 
			
		||||
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
 | 
			
		||||
	} else if !f.FullTimestamp {
 | 
			
		||||
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message)
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
 | 
			
		||||
	}
 | 
			
		||||
@@ -127,7 +145,10 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func needsQuoting(text string) bool {
 | 
			
		||||
func (f *TextFormatter) needsQuoting(text string) bool {
 | 
			
		||||
	if f.QuoteEmptyFields && len(text) == 0 {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	for _, ch := range text {
 | 
			
		||||
		if !((ch >= 'a' && ch <= 'z') ||
 | 
			
		||||
			(ch >= 'A' && ch <= 'Z') ||
 | 
			
		||||
@@ -150,17 +171,17 @@ func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interf
 | 
			
		||||
func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
 | 
			
		||||
	switch value := value.(type) {
 | 
			
		||||
	case string:
 | 
			
		||||
		if !needsQuoting(value) {
 | 
			
		||||
		if !f.needsQuoting(value) {
 | 
			
		||||
			b.WriteString(value)
 | 
			
		||||
		} else {
 | 
			
		||||
			fmt.Fprintf(b, "%q", value)
 | 
			
		||||
			fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, value, f.QuoteCharacter)
 | 
			
		||||
		}
 | 
			
		||||
	case error:
 | 
			
		||||
		errmsg := value.Error()
 | 
			
		||||
		if !needsQuoting(errmsg) {
 | 
			
		||||
		if !f.needsQuoting(errmsg) {
 | 
			
		||||
			b.WriteString(errmsg)
 | 
			
		||||
		} else {
 | 
			
		||||
			fmt.Fprintf(b, "%q", errmsg)
 | 
			
		||||
			fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, errmsg, f.QuoteCharacter)
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		fmt.Fprint(b, value)
 | 
			
		||||
							
								
								
									
										87
									
								
								vendor/github.com/sirupsen/logrus/text_formatter_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								vendor/github.com/sirupsen/logrus/text_formatter_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
package logrus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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(tf.QuoteCharacter))
 | 
			
		||||
		if cont != q {
 | 
			
		||||
			if q {
 | 
			
		||||
				t.Errorf("quoting expected for: %#v", value)
 | 
			
		||||
			} else {
 | 
			
		||||
				t.Errorf("quoting not expected for: %#v", value)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	checkQuoting(false, "")
 | 
			
		||||
	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"))
 | 
			
		||||
 | 
			
		||||
	// Test for custom quote character.
 | 
			
		||||
	tf.QuoteCharacter = "`"
 | 
			
		||||
	checkQuoting(false, "")
 | 
			
		||||
	checkQuoting(false, "abcd")
 | 
			
		||||
	checkQuoting(true, "/foobar")
 | 
			
		||||
	checkQuoting(true, errors.New("invalid argument"))
 | 
			
		||||
 | 
			
		||||
	// Test for multi-character quotes.
 | 
			
		||||
	tf.QuoteCharacter = "§~±"
 | 
			
		||||
	checkQuoting(false, "abcd")
 | 
			
		||||
	checkQuoting(true, errors.New("invalid argument"))
 | 
			
		||||
 | 
			
		||||
	// Test for quoting empty fields.
 | 
			
		||||
	tf.QuoteEmptyFields = true
 | 
			
		||||
	checkQuoting(true, "")
 | 
			
		||||
	checkQuoting(false, "abcd")
 | 
			
		||||
	checkQuoting(true, errors.New("invalid argument"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestTimestampFormat(t *testing.T) {
 | 
			
		||||
	checkTimeStr := func(format string) {
 | 
			
		||||
		customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format}
 | 
			
		||||
		customStr, _ := customFormatter.Format(WithField("test", "test"))
 | 
			
		||||
		timeStart := bytes.Index(customStr, ([]byte)("time="))
 | 
			
		||||
		timeEnd := bytes.Index(customStr, ([]byte)("level="))
 | 
			
		||||
		timeStr := customStr[timeStart+5+len(customFormatter.QuoteCharacter) : timeEnd-1-len(customFormatter.QuoteCharacter)]
 | 
			
		||||
		if format == "" {
 | 
			
		||||
			format = time.RFC3339
 | 
			
		||||
		}
 | 
			
		||||
		_, e := time.Parse(format, (string)(timeStr))
 | 
			
		||||
		if e != nil {
 | 
			
		||||
			t.Errorf("time string \"%s\" did not match provided time format \"%s\": %s", timeStr, format, e)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	checkTimeStr("2006-01-02T15:04:05.000000000Z07:00")
 | 
			
		||||
	checkTimeStr("Mon Jan _2 15:04:05 2006")
 | 
			
		||||
	checkTimeStr("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDisableTimestampWithColoredOutput(t *testing.T) {
 | 
			
		||||
	tf := &TextFormatter{DisableTimestamp: true, ForceColors: true}
 | 
			
		||||
 | 
			
		||||
	b, _ := tf.Format(WithField("test", "test"))
 | 
			
		||||
	if strings.Contains(string(b), "[0000]") {
 | 
			
		||||
		t.Error("timestamp not expected when DisableTimestamp is true")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO add tests for sorting etc., this requires a parser for the text
 | 
			
		||||
// formatter output.
 | 
			
		||||
@@ -11,39 +11,48 @@ func (logger *Logger) Writer() *io.PipeWriter {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
 | 
			
		||||
	return NewEntry(logger).WriterLevel(level)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) Writer() *io.PipeWriter {
 | 
			
		||||
	return entry.WriterLevel(InfoLevel)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
 | 
			
		||||
	reader, writer := io.Pipe()
 | 
			
		||||
 | 
			
		||||
	var printFunc func(args ...interface{})
 | 
			
		||||
 | 
			
		||||
	switch level {
 | 
			
		||||
	case DebugLevel:
 | 
			
		||||
		printFunc = logger.Debug
 | 
			
		||||
		printFunc = entry.Debug
 | 
			
		||||
	case InfoLevel:
 | 
			
		||||
		printFunc = logger.Info
 | 
			
		||||
		printFunc = entry.Info
 | 
			
		||||
	case WarnLevel:
 | 
			
		||||
		printFunc = logger.Warn
 | 
			
		||||
		printFunc = entry.Warn
 | 
			
		||||
	case ErrorLevel:
 | 
			
		||||
		printFunc = logger.Error
 | 
			
		||||
		printFunc = entry.Error
 | 
			
		||||
	case FatalLevel:
 | 
			
		||||
		printFunc = logger.Fatal
 | 
			
		||||
		printFunc = entry.Fatal
 | 
			
		||||
	case PanicLevel:
 | 
			
		||||
		printFunc = logger.Panic
 | 
			
		||||
		printFunc = entry.Panic
 | 
			
		||||
	default:
 | 
			
		||||
		printFunc = logger.Print
 | 
			
		||||
		printFunc = entry.Print
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	go logger.writerScanner(reader, printFunc)
 | 
			
		||||
	go entry.writerScanner(reader, printFunc)
 | 
			
		||||
	runtime.SetFinalizer(writer, writerFinalizer)
 | 
			
		||||
 | 
			
		||||
	return writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
 | 
			
		||||
func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
 | 
			
		||||
	scanner := bufio.NewScanner(reader)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		printFunc(scanner.Text())
 | 
			
		||||
	}
 | 
			
		||||
	if err := scanner.Err(); err != nil {
 | 
			
		||||
		logger.Errorf("Error while reading from Writer: %s", err)
 | 
			
		||||
		entry.Errorf("Error while reading from Writer: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	reader.Close()
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user