From 1726e1744a80b3d1f736a74b8b617380ade59a4c Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Sun, 5 Feb 2017 09:21:03 -0500 Subject: [PATCH 01/12] text_formatter: detect tty based on fd --- terminal_appengine.go | 2 +- terminal_notwindows.go | 14 ++++++++++---- terminal_solaris.go | 12 +++++++++--- terminal_windows.go | 14 +++++++++----- text_formatter.go | 15 ++++++++++----- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/terminal_appengine.go b/terminal_appengine.go index 1960169..632ecbe 100644 --- a/terminal_appengine.go +++ b/terminal_appengine.go @@ -3,6 +3,6 @@ package logrus // IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal() bool { +func IsTerminal(f io.Writer) bool { return true } diff --git a/terminal_notwindows.go b/terminal_notwindows.go index 329038f..190297a 100644 --- a/terminal_notwindows.go +++ b/terminal_notwindows.go @@ -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 + } } diff --git a/terminal_solaris.go b/terminal_solaris.go index a3c6f6e..943394c 100644 --- a/terminal_solaris.go +++ b/terminal_solaris.go @@ -9,7 +9,13 @@ import ( ) // 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 +func IsTerminal(f io.Writer) bool { + var termios Termios + switch v := f.(type) { + case *os.File: + _, err := unix.IoctlGetTermios(int(f.Fd()), unix.TCGETA) + return err == nil + default: + return false + } } diff --git a/terminal_windows.go b/terminal_windows.go index 3727e8a..67be1c0 100644 --- a/terminal_windows.go +++ b/terminal_windows.go @@ -19,9 +19,13 @@ var ( ) // 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 +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 + } } diff --git a/text_formatter.go b/text_formatter.go index 076de5d..f75e13e 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -3,7 +3,6 @@ package logrus import ( "bytes" "fmt" - "runtime" "sort" "strings" "time" @@ -20,12 +19,10 @@ const ( var ( baseTimestamp time.Time - isTerminal bool ) func init() { baseTimestamp = time.Now() - isTerminal = IsTerminal() } type TextFormatter struct { @@ -50,6 +47,10 @@ type TextFormatter struct { // that log extremely frequently and don't use the JSON formatter this may not // be desired. DisableSorting bool + + // Whether the logger's out is to a terminal + isTerminal bool + terminalDetermined bool } func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { @@ -70,8 +71,12 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { prefixFieldClashes(entry.Data) - isColorTerminal := isTerminal && (runtime.GOOS != "windows") - isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors + if !f.terminalDetermined { + f.isTerminal = IsTerminal(entry.Logger.Out) + f.terminalDetermined = true + } + + isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors timestampFormat := f.TimestampFormat if timestampFormat == "" { From 11fbf0fa42b837cdd5b234470b53d03bad9e5041 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Sun, 5 Feb 2017 19:10:19 -0500 Subject: [PATCH 02/12] text_formatter: fix race --- examples/basic/basic.go | 1 + formatter_bench_test.go | 3 +++ text_formatter.go | 14 ++++++++------ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/examples/basic/basic.go b/examples/basic/basic.go index a1623ec..ea7e551 100644 --- a/examples/basic/basic.go +++ b/examples/basic/basic.go @@ -2,6 +2,7 @@ package main import ( "github.com/Sirupsen/logrus" + "os" ) var log = logrus.New() diff --git a/formatter_bench_test.go b/formatter_bench_test.go index c6d290c..d948158 100644 --- a/formatter_bench_test.go +++ b/formatter_bench_test.go @@ -80,11 +80,14 @@ func BenchmarkLargeJSONFormatter(b *testing.B) { } 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 diff --git a/text_formatter.go b/text_formatter.go index f75e13e..b4dffa1 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -5,6 +5,7 @@ import ( "fmt" "sort" "strings" + "sync" "time" ) @@ -49,8 +50,8 @@ type TextFormatter struct { DisableSorting bool // Whether the logger's out is to a terminal - isTerminal bool - terminalDetermined bool + isTerminal bool + terminalOnce sync.Once } func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { @@ -71,10 +72,11 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { prefixFieldClashes(entry.Data) - if !f.terminalDetermined { - f.isTerminal = IsTerminal(entry.Logger.Out) - f.terminalDetermined = true - } + f.terminalOnce.Do(func() { + if entry.Logger != nil { + f.isTerminal = IsTerminal(entry.Logger.Out) + } + }) isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors From 141e6dc6a6809c83c4fba8fecb687fd2776de5ed Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Mon, 6 Feb 2017 19:16:20 -0500 Subject: [PATCH 03/12] readme: update with example of logging to file --- README.md | 13 +++++++++++-- examples/basic/basic.go | 10 +++++++++- terminal_solaris.go | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 206c746..3823323 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,8 @@ func init() { // Log as JSON instead of the default ASCII formatter. log.SetFormatter(&log.JSONFormatter{}) - // Output to stdout instead of the default stderr, could also be a file. + // 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. @@ -138,7 +139,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", diff --git a/examples/basic/basic.go b/examples/basic/basic.go index ea7e551..ad703fc 100644 --- a/examples/basic/basic.go +++ b/examples/basic/basic.go @@ -2,7 +2,7 @@ package main import ( "github.com/Sirupsen/logrus" - "os" + // "os" ) var log = logrus.New() @@ -10,6 +10,14 @@ 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 } diff --git a/terminal_solaris.go b/terminal_solaris.go index 943394c..f3d6f96 100644 --- a/terminal_solaris.go +++ b/terminal_solaris.go @@ -13,7 +13,7 @@ func IsTerminal(f io.Writer) bool { var termios Termios switch v := f.(type) { case *os.File: - _, err := unix.IoctlGetTermios(int(f.Fd()), unix.TCGETA) + _, err := unix.IoctlGetTermios(int(v.Fd()), unix.TCGETA) return err == nil default: return false From e2fcfb2fbaf72bc70ae06375da0f4de7b049822f Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Mon, 6 Feb 2017 19:40:31 -0500 Subject: [PATCH 04/12] readme: add some entries from stale PRs --- README.md | 65 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 3823323..eaaea79 100644 --- a/README.md +++ b/README.md @@ -215,42 +215,43 @@ 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. | | [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 | | [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 | -| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) | -| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) | -| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) | +| [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 | | [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. | +| [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. | +| [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 | #### Level logging From 38f1ab305781cc3dd4bf0f7d45f36d5e7db1bfc3 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Mon, 6 Feb 2017 19:40:39 -0500 Subject: [PATCH 05/12] changelog: add for 0.11.0 and 0.11.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c2bc2..47a6c4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +# 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) From b9def5b3c33f812a4f503538d1ee21eeb6787d6d Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Mon, 6 Feb 2017 19:44:51 -0500 Subject: [PATCH 06/12] readme: even more hooks --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index eaaea79..77941d8 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v | ----- | ----------- | | [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. | | [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) | | [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 | @@ -231,6 +232,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v | [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/) | @@ -248,8 +250,10 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v | [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. | +| [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 | From feda23452af05568da16c028ff779b66d95b80db Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Mon, 6 Feb 2017 19:51:07 -0500 Subject: [PATCH 07/12] readme: link to colorable for windows coloring --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 77941d8..a404823 100644 --- a/README.md +++ b/README.md @@ -331,8 +331,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: From 080ca65fb5a85b6f2b42053b9a895d462ed0ddff Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Mon, 6 Feb 2017 19:56:22 -0500 Subject: [PATCH 08/12] readme: add section on overriding stdlib logger --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index a404823..0671464 100644 --- a/README.md +++ b/README.md @@ -384,6 +384,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: + +``` +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 From 5c8f1691bc900a172e4148d528645c7a4caf64f9 Mon Sep 17 00:00:00 2001 From: Majid Arif Siddiqui Date: Tue, 7 Feb 2017 11:28:14 +0800 Subject: [PATCH 09/12] Fixed missing imports for windows terminal --- terminal_windows.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/terminal_windows.go b/terminal_windows.go index 67be1c0..97ad4e0 100644 --- a/terminal_windows.go +++ b/terminal_windows.go @@ -8,6 +8,8 @@ package logrus import ( + "io" + "os" "syscall" "unsafe" ) From ac38cb37a804c3638225558ca89a9ee1fb0d5a5a Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Tue, 7 Feb 2017 06:40:37 -0500 Subject: [PATCH 10/12] readme: fix markdown code syntax for stdlib example --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0671464..361b333 100644 --- a/README.md +++ b/README.md @@ -386,7 +386,7 @@ 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{} @@ -394,7 +394,7 @@ logger.Formatter = &logrus.JSONFormatter{} // Note that `log` here references stdlib's log // Not logrus imported under the name `log`. log.SetOutput(logger.Writer()) -`` +``` #### Rotation From c078b1e43f58d563c74cebe63c85789e76ddb627 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Tue, 7 Feb 2017 06:49:02 -0500 Subject: [PATCH 11/12] changelog: add fixing windows terminal detection --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a6c4b..6cee3c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.11.2 + +* bug: fix windows terminal detection (#476) + # 0.11.1 * bug: fix tty detection with custom out (#471) From 3f603f494d61c73457fb234161d8982b9f0f0b71 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Tue, 7 Feb 2017 13:34:08 -0500 Subject: [PATCH 12/12] readme: add section on default fields --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 361b333..640cf61 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,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