Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text_formatter: detect tty based on fd #471

Merged
merged 3 commits into from
Feb 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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",
Expand Down
9 changes: 9 additions & 0 deletions examples/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@ 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
}

Expand Down
3 changes: 3 additions & 0 deletions formatter_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion terminal_appengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
14 changes: 10 additions & 4 deletions terminal_notwindows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
12 changes: 9 additions & 3 deletions terminal_solaris.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(v.Fd()), unix.TCGETA)
return err == nil
default:
return false
}
}
14 changes: 9 additions & 5 deletions terminal_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
17 changes: 12 additions & 5 deletions text_formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package logrus
import (
"bytes"
"fmt"
"runtime"
"sort"
"strings"
"sync"
"time"
)

Expand All @@ -20,12 +20,10 @@ const (

var (
baseTimestamp time.Time
isTerminal bool
)

func init() {
baseTimestamp = time.Now()
isTerminal = IsTerminal()
}

type TextFormatter struct {
Expand All @@ -50,6 +48,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
terminalOnce sync.Once
}

func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
Expand All @@ -70,8 +72,13 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {

prefixFieldClashes(entry.Data)

isColorTerminal := isTerminal && (runtime.GOOS != "windows")
isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors
f.terminalOnce.Do(func() {
if entry.Logger != nil {
f.isTerminal = IsTerminal(entry.Logger.Out)
}
})

isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors

timestampFormat := f.TimestampFormat
if timestampFormat == "" {
Expand Down