Merge pull request #13715 from LK4D4/update_logrus

Update github.com/Sirupsen/logrus to 0.8.2
This commit is contained in:
Arnaud Porterie 2015-06-03 14:24:37 -07:00
commit babf751e1b
11 changed files with 62 additions and 15 deletions

View File

@ -43,7 +43,7 @@ clone() {
} }
# the following lines are in sorted order, FYI # the following lines are in sorted order, FYI
clone git github.com/Sirupsen/logrus v0.7.3 # logrus is a common dependency among multiple deps clone git github.com/Sirupsen/logrus v0.8.2 # logrus is a common dependency among multiple deps
clone git github.com/docker/libtrust 230dfd18c232 clone git github.com/docker/libtrust 230dfd18c232
clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673 clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673
clone git github.com/gorilla/context 14f550f51a clone git github.com/gorilla/context 14f550f51a

View File

@ -1,3 +1,17 @@
# 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 # 0.7.3
formatter/\*: allow configuration of timestamp layout formatter/\*: allow configuration of timestamp layout

View File

@ -32,7 +32,7 @@ ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} "time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
``` ```
With the default `log.Formatter = new(logrus.TextFormatter)` when a TTY is not With the default `log.Formatter = new(&log.TextFormatter{})` when a TTY is not
attached, the output is compatible with the attached, the output is compatible with the
[logfmt](http://godoc.org/github.com/kr/logfmt) format: [logfmt](http://godoc.org/github.com/kr/logfmt) format:
@ -211,6 +211,7 @@ func init() {
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | | [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | | [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
| [Graylog](https://github.com/gemnasium/logrus-hooks/tree/master/graylog) | Hook for logging to [Graylog](http://graylog2.org/) | | [Graylog](https://github.com/gemnasium/logrus-hooks/tree/master/graylog) | 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/) |
#### Level logging #### Level logging
@ -269,7 +270,7 @@ init() {
log.SetFormatter(logrus.JSONFormatter) log.SetFormatter(logrus.JSONFormatter)
} else { } else {
// The TextFormatter is default, you don't actually have to do this. // The TextFormatter is default, you don't actually have to do this.
log.SetFormatter(logrus.TextFormatter) log.SetFormatter(&log.TextFormatter{})
} }
} }
``` ```

View File

@ -188,6 +188,7 @@ func (entry *Entry) Fatalf(format string, args ...interface{}) {
if entry.Logger.Level >= FatalLevel { if entry.Logger.Level >= FatalLevel {
entry.Fatal(fmt.Sprintf(format, args...)) entry.Fatal(fmt.Sprintf(format, args...))
} }
os.Exit(1)
} }
func (entry *Entry) Panicf(format string, args ...interface{}) { func (entry *Entry) Panicf(format string, args ...interface{}) {
@ -234,6 +235,7 @@ func (entry *Entry) Fatalln(args ...interface{}) {
if entry.Logger.Level >= FatalLevel { if entry.Logger.Level >= FatalLevel {
entry.Fatal(entry.sprintlnn(args...)) entry.Fatal(entry.sprintlnn(args...))
} }
os.Exit(1)
} }
func (entry *Entry) Panicln(args ...interface{}) { func (entry *Entry) Panicln(args ...interface{}) {

View File

@ -34,12 +34,13 @@ func main() {
## Special fields ## Special fields
Some logrus fields have a special meaning in this hook, Some logrus fields have a special meaning in this hook,
these are server_name and logger. these are `server_name`, `logger` and `http_request`.
When logs are sent to sentry these fields are treated differently. When logs are sent to sentry these fields are treated differently.
- server_name (also known as hostname) is the name of the server which - `server_name` (also known as hostname) is the name of the server which
is logging the event (hostname.example.com) is logging the event (hostname.example.com)
- logger is the part of the application which is logging the event. - `logger` is the part of the application which is logging the event.
In go this usually means setting it to the name of the package. In go this usually means setting it to the name of the package.
- `http_request` is the in-coming request(*http.Request). The detailed request data are sent to Sentry.
## Timeout ## Timeout

View File

@ -3,6 +3,7 @@ package logrus_sentry
import ( import (
"fmt" "fmt"
"time" "time"
"net/http"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/getsentry/raven-go" "github.com/getsentry/raven-go"
@ -36,6 +37,22 @@ func getAndDel(d logrus.Fields, key string) (string, bool) {
return val, true return val, true
} }
func getAndDelRequest(d logrus.Fields, key string) (*http.Request, bool) {
var (
ok bool
v interface{}
req *http.Request
)
if v, ok = d[key]; !ok {
return nil, false
}
if req, ok = v.(*http.Request); !ok || req == nil {
return nil, false
}
delete(d, key)
return req, true
}
// SentryHook delivers logs to a sentry server. // SentryHook delivers logs to a sentry server.
type SentryHook struct { type SentryHook struct {
// Timeout sets the time to wait for a delivery error from the sentry server. // Timeout sets the time to wait for a delivery error from the sentry server.
@ -61,7 +78,7 @@ func NewSentryHook(DSN string, levels []logrus.Level) (*SentryHook, error) {
// Called when an event should be sent to sentry // Called when an event should be sent to sentry
// Special fields that sentry uses to give more information to the server // Special fields that sentry uses to give more information to the server
// are extracted from entry.Data (if they are found) // are extracted from entry.Data (if they are found)
// These fields are: logger and server_name // These fields are: logger, server_name and http_request
func (hook *SentryHook) Fire(entry *logrus.Entry) error { func (hook *SentryHook) Fire(entry *logrus.Entry) error {
packet := &raven.Packet{ packet := &raven.Packet{
Message: entry.Message, Message: entry.Message,
@ -78,6 +95,9 @@ func (hook *SentryHook) Fire(entry *logrus.Entry) error {
if serverName, ok := getAndDel(d, "server_name"); ok { if serverName, ok := getAndDel(d, "server_name"); ok {
packet.ServerName = serverName packet.ServerName = serverName
} }
if req, ok := getAndDelRequest(d, "http_request"); ok {
packet.Interfaces = append(packet.Interfaces, raven.NewHttp(req))
}
packet.Extra = map[string]interface{}(d) packet.Extra = map[string]interface{}(d)
_, errCh := hook.client.Capture(packet, nil) _, errCh := hook.client.Capture(packet, nil)

View File

@ -61,9 +61,12 @@ func TestSpecialFields(t *testing.T) {
t.Fatal(err.Error()) t.Fatal(err.Error())
} }
logger.Hooks.Add(hook) logger.Hooks.Add(hook)
req, _ := http.NewRequest("GET", "url", nil)
logger.WithFields(logrus.Fields{ logger.WithFields(logrus.Fields{
"server_name": server_name, "server_name": server_name,
"logger": logger_name, "logger": logger_name,
"http_request": req,
}).Error(message) }).Error(message)
packet := <-pch packet := <-pch

View File

@ -24,11 +24,12 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
} }
prefixFieldClashes(data) prefixFieldClashes(data)
if f.TimestampFormat == "" { timestampFormat := f.TimestampFormat
f.TimestampFormat = DefaultTimestampFormat if timestampFormat == "" {
timestampFormat = DefaultTimestampFormat
} }
data["time"] = entry.Time.Format(f.TimestampFormat) data["time"] = entry.Time.Format(timestampFormat)
data["msg"] = entry.Message data["msg"] = entry.Message
data["level"] = entry.Level.String() data["level"] = entry.Level.String()

View File

@ -44,7 +44,7 @@ type Logger struct {
// It's recommended to make this a global instance called `log`. // It's recommended to make this a global instance called `log`.
func New() *Logger { func New() *Logger {
return &Logger{ return &Logger{
Out: os.Stdout, Out: os.Stderr,
Formatter: new(TextFormatter), Formatter: new(TextFormatter),
Hooks: make(levelHooks), Hooks: make(levelHooks),
Level: InfoLevel, Level: InfoLevel,
@ -102,6 +102,7 @@ func (logger *Logger) Fatalf(format string, args ...interface{}) {
if logger.Level >= FatalLevel { if logger.Level >= FatalLevel {
NewEntry(logger).Fatalf(format, args...) NewEntry(logger).Fatalf(format, args...)
} }
os.Exit(1)
} }
func (logger *Logger) Panicf(format string, args ...interface{}) { func (logger *Logger) Panicf(format string, args ...interface{}) {
@ -148,6 +149,7 @@ func (logger *Logger) Fatal(args ...interface{}) {
if logger.Level >= FatalLevel { if logger.Level >= FatalLevel {
NewEntry(logger).Fatal(args...) NewEntry(logger).Fatal(args...)
} }
os.Exit(1)
} }
func (logger *Logger) Panic(args ...interface{}) { func (logger *Logger) Panic(args ...interface{}) {
@ -194,6 +196,7 @@ func (logger *Logger) Fatalln(args ...interface{}) {
if logger.Level >= FatalLevel { if logger.Level >= FatalLevel {
NewEntry(logger).Fatalln(args...) NewEntry(logger).Fatalln(args...)
} }
os.Exit(1)
} }
func (logger *Logger) Panicln(args ...interface{}) { func (logger *Logger) Panicln(args ...interface{}) {

View File

@ -191,7 +191,7 @@ func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
log.WithField("level", 1).Info("test") log.WithField("level", 1).Info("test")
}, func(fields Fields) { }, func(fields Fields) {
assert.Equal(t, fields["level"], "info") assert.Equal(t, fields["level"], "info")
assert.Equal(t, fields["fields.level"], 1) assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only
}) })
} }

View File

@ -3,6 +3,7 @@ package logrus
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"runtime"
"sort" "sort"
"strings" "strings"
"time" "time"
@ -69,7 +70,8 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
prefixFieldClashes(entry.Data) prefixFieldClashes(entry.Data)
isColored := (f.ForceColors || isTerminal) && !f.DisableColors isColorTerminal := isTerminal && (runtime.GOOS != "windows")
isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors
if f.TimestampFormat == "" { if f.TimestampFormat == "" {
f.TimestampFormat = DefaultTimestampFormat f.TimestampFormat = DefaultTimestampFormat