diff -Nru golang-logrus-1.0.2/alt_exit_test.go golang-logrus-1.0.5/alt_exit_test.go --- golang-logrus-1.0.2/alt_exit_test.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/alt_exit_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -2,7 +2,10 @@ import ( "io/ioutil" + "log" + "os" "os/exec" + "path/filepath" "testing" "time" ) @@ -11,30 +14,36 @@ current := len(handlers) RegisterExitHandler(func() {}) if len(handlers) != current+1 { - t.Fatalf("can't add handler") + t.Fatalf("expected %d handlers, got %d", current+1, len(handlers)) } } func TestHandler(t *testing.T) { - gofile := "/tmp/testprog.go" + tempDir, err := ioutil.TempDir("", "test_handler") + if err != nil { + log.Fatalf("can't create temp dir. %q", err) + } + defer os.RemoveAll(tempDir) + + gofile := filepath.Join(tempDir, "gofile.go") if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil { - t.Fatalf("can't create go file") + t.Fatalf("can't create go file. %q", err) } - outfile := "/tmp/testprog.out" + outfile := filepath.Join(tempDir, "outfile.out") arg := time.Now().UTC().String() - err := exec.Command("go", "run", gofile, outfile, arg).Run() + 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) + t.Fatalf("can't read output file %s. %q", outfile, err) } if string(data) != arg { - t.Fatalf("bad data") + t.Fatalf("bad data. Expected %q, got %q", data, arg) } } diff -Nru golang-logrus-1.0.2/appveyor.yml golang-logrus-1.0.5/appveyor.yml --- golang-logrus-1.0.2/appveyor.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/appveyor.yml 2018-03-11 22:51:37.000000000 +0000 @@ -0,0 +1,14 @@ +version: "{build}" +platform: x64 +clone_folder: c:\gopath\src\github.com\sirupsen\logrus +environment: + GOPATH: c:\gopath +branches: + only: + - master +install: + - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% + - go version +build_script: + - go get -t + - go test diff -Nru golang-logrus-1.0.2/CHANGELOG.md golang-logrus-1.0.5/CHANGELOG.md --- golang-logrus-1.0.2/CHANGELOG.md 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/CHANGELOG.md 2018-03-11 22:51:37.000000000 +0000 @@ -1,3 +1,17 @@ +# 1.0.5 + +* Fix hooks race (#707) +* Fix panic deadlock (#695) + +# 1.0.4 + +* Fix race when adding hooks (#612) +* Fix terminal check in AppEngine (#635) + +# 1.0.3 + +* Replace example files with testable examples + # 1.0.2 * bug: quote non-string values in text formatter (#583) diff -Nru golang-logrus-1.0.2/debian/changelog golang-logrus-1.0.5/debian/changelog --- golang-logrus-1.0.2/debian/changelog 2017-08-17 05:52:43.000000000 +0000 +++ golang-logrus-1.0.5/debian/changelog 2018-05-18 15:33:36.000000000 +0000 @@ -1,3 +1,30 @@ +golang-logrus (1.0.5-2) unstable; urgency=medium + + * Team upload. + * Cherry-pick "Fix a race condition in TestLoggingWithHooksRace" from + upstream because autopkgtest was failing randomly for 1.0.5-1. + See https://ci.debian.net/data/autopkgtest/testing/amd64/g/golang-logrus/286167/log.gz + and https://github.com/sirupsen/logrus/issues/740 + + -- Anthony Fok Fri, 18 May 2018 09:33:36 -0600 + +golang-logrus (1.0.5-1) unstable; urgency=medium + + * Team upload. + + [ Alexandre Viau ] + * Point Vcs-* urls to salsa.debian.org. + + [ Dmitry Smirnov ] + * New upstream release. + * (Build-)Depends: + + golang-golang-x-crypto-dev + + golang-golang-x-sys-dev + * Priority: optional. + * Standards-Version: 4.1.4. + + -- Dmitry Smirnov Sun, 06 May 2018 01:55:29 +1000 + golang-logrus (1.0.2-2) unstable; urgency=high * Add maintscript to handle symlink to dir conversions. diff -Nru golang-logrus-1.0.2/debian/clean golang-logrus-1.0.5/debian/clean --- golang-logrus-1.0.2/debian/clean 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/debian/clean 2018-05-18 15:07:34.000000000 +0000 @@ -0,0 +1,2 @@ +# Un-buildable example (# cannot find package "gopkg.in/gemnasium/logrus-airbrake-hook.v2"): +example_hook_test.go diff -Nru golang-logrus-1.0.2/debian/control golang-logrus-1.0.5/debian/control --- golang-logrus-1.0.2/debian/control 2017-08-17 05:52:43.000000000 +0000 +++ golang-logrus-1.0.5/debian/control 2018-05-18 15:07:34.000000000 +0000 @@ -1,6 +1,6 @@ Source: golang-logrus Section: devel -Priority: extra +Priority: optional Maintainer: Debian Go Packaging Team Uploaders: Martín Ferrari , Tianon Gravi , @@ -8,17 +8,22 @@ dh-golang (>= 1.10), golang-any, golang-github-stretchr-testify-dev, -Standards-Version: 4.0.0 + golang-golang-x-crypto-dev, + golang-golang-x-sys-dev, +Standards-Version: 4.1.4 Homepage: https://github.com/sirupsen/logrus -Vcs-Git: https://anonscm.debian.org/git/pkg-go/packages/golang-logrus.git -Vcs-Browser: https://anonscm.debian.org/cgit/pkg-go/packages/golang-logrus.git +Vcs-Git: https://salsa.debian.org/go-team/packages/golang-logrus.git +Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-logrus XS-Go-Import-Path: github.com/sirupsen/logrus Testsuite: autopkgtest-pkg-go Package: golang-github-sirupsen-logrus-dev Architecture: all Pre-Depends: dpkg (>= 1.17.14) -Depends: golang-github-stretchr-testify-dev, ${misc:Depends} +Depends: ${misc:Depends} + ,golang-github-stretchr-testify-dev + ,golang-golang-x-crypto-dev + ,golang-golang-x-sys-dev Replaces: golang-logrus-dev (<< 0.7.3-2~) Breaks: golang-logrus-dev (<< 0.7.3-2~) Provides: golang-logrus-dev diff -Nru golang-logrus-1.0.2/debian/copyright golang-logrus-1.0.5/debian/copyright --- golang-logrus-1.0.2/debian/copyright 2017-08-17 05:52:43.000000000 +0000 +++ golang-logrus-1.0.5/debian/copyright 2018-05-18 15:07:34.000000000 +0000 @@ -1,4 +1,4 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: sirupsen/logrus Source: https://github.com/sirupsen/logrus @@ -7,8 +7,6 @@ License: Expat Files: terminal_linux.go - terminal_notwindows.go - terminal_windows.go Copyright: 2011-2013 The Go Authors License: Expat diff -Nru golang-logrus-1.0.2/debian/examples golang-logrus-1.0.5/debian/examples --- golang-logrus-1.0.2/debian/examples 2017-08-17 05:52:43.000000000 +0000 +++ golang-logrus-1.0.5/debian/examples 2018-05-18 15:07:34.000000000 +0000 @@ -1,2 +1 @@ -examples/basic -examples/hook +example_basic_test.go diff -Nru golang-logrus-1.0.2/debian/gitlab-ci.yml golang-logrus-1.0.5/debian/gitlab-ci.yml --- golang-logrus-1.0.2/debian/gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/debian/gitlab-ci.yml 2018-05-18 15:06:41.000000000 +0000 @@ -0,0 +1,28 @@ + +# auto-generated, DO NOT MODIFY. +# The authoritative copy of this file lives at: +# https://salsa.debian.org/go-team/ci/blob/master/cmd/ci/gitlabciyml.go + +# TODO: publish under debian-go-team/ci +image: stapelberg/ci2 + +test_the_archive: + artifacts: + paths: + - before-applying-commit.json + - after-applying-commit.json + script: + # Create an overlay to discard writes to /srv/gopath/src after the build: + - "rm -rf /cache/overlay/{upper,work}" + - "mkdir -p /cache/overlay/{upper,work}" + - "mount -t overlay overlay -o lowerdir=/srv/gopath/src,upperdir=/cache/overlay/upper,workdir=/cache/overlay/work /srv/gopath/src" + - "export GOPATH=/srv/gopath" + - "export GOCACHE=/cache/go" + # Build the world as-is: + - "ci-build -exemptions=/var/lib/ci-build/exemptions.json > before-applying-commit.json" + # Copy this package into the overlay: + - "GBP_CONF_FILES=:debian/gbp.conf gbp buildpackage --git-no-pristine-tar --git-ignore-branch --git-ignore-new --git-export-dir=/tmp/export --git-no-overlay --git-tarball-dir=/nonexistant --git-cleaner=/bin/true --git-builder='dpkg-buildpackage -S -d --no-sign'" + - "pgt-gopath -dsc /tmp/export/*.dsc" + # Rebuild the world: + - "ci-build -exemptions=/var/lib/ci-build/exemptions.json > after-applying-commit.json" + - "ci-diff before-applying-commit.json after-applying-commit.json" diff -Nru golang-logrus-1.0.2/debian/patches/fix-a-race-condition-in-TestLoggingWithHooksRace-752.patch golang-logrus-1.0.5/debian/patches/fix-a-race-condition-in-TestLoggingWithHooksRace-752.patch --- golang-logrus-1.0.2/debian/patches/fix-a-race-condition-in-TestLoggingWithHooksRace-752.patch 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/debian/patches/fix-a-race-condition-in-TestLoggingWithHooksRace-752.patch 2018-05-18 15:26:11.000000000 +0000 @@ -0,0 +1,33 @@ +From 8369e2f077642788e2ef31f342a0a4621b2b4607 Mon Sep 17 00:00:00 2001 +From: David Bariod +Date: Sat, 12 May 2018 15:51:19 +0200 +Subject: [PATCH] Fix a race condition in TestLoggingWithHooksRace + +--- + hooks/test/test_test.go | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Origin: upstream, https://github.com/sirupsen/logrus/commit/8369e2f077642788e2ef31f342a0a4621b2b4607.patch +Bug: https://github.com/sirupsen/logrus/issues/751 +Reviewed-by: Simon Eskildsen +Reviewed-by: Anthony Fok +Last-Update: 2018-05-18 + +diff --git a/hooks/test/test_test.go b/hooks/test/test_test.go +index dea768e6..742be553 100644 +--- a/hooks/test/test_test.go ++++ b/hooks/test/test_test.go +@@ -51,11 +51,11 @@ func TestLoggingWithHooksRace(t *testing.T) { + }() + } + ++ wg.Wait() ++ + assert.Equal(logrus.InfoLevel, hook.LastEntry().Level) + assert.Equal("info", hook.LastEntry().Message) + +- wg.Wait() +- + entries := hook.AllEntries() + assert.Equal(100, len(entries)) + } diff -Nru golang-logrus-1.0.2/debian/patches/series golang-logrus-1.0.5/debian/patches/series --- golang-logrus-1.0.2/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/debian/patches/series 2018-05-18 15:19:05.000000000 +0000 @@ -0,0 +1 @@ +fix-a-race-condition-in-TestLoggingWithHooksRace-752.patch diff -Nru golang-logrus-1.0.2/entry.go golang-logrus-1.0.5/entry.go --- golang-logrus-1.0.2/entry.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/entry.go 2018-03-11 22:51:37.000000000 +0000 @@ -35,6 +35,7 @@ Time time.Time // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic + // This field will be set on entry firing and the value will be equal to the one in Logger struct field. Level Level // Message passed to Debug, Info, Warn, Error, Fatal or Panic @@ -93,35 +94,47 @@ entry.Level = level entry.Message = msg - if err := entry.Logger.Hooks.Fire(level, &entry); err != nil { - entry.Logger.mu.Lock() - fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) - entry.Logger.mu.Unlock() - } + entry.fireHooks() + buffer = bufferPool.Get().(*bytes.Buffer) buffer.Reset() defer bufferPool.Put(buffer) entry.Buffer = buffer - serialized, err := entry.Logger.Formatter.Format(&entry) + + entry.write() + entry.Buffer = nil + + // To avoid Entry#log() returning a value that only would make sense for + // panic() to use in Entry#Panic(), we avoid the allocation by checking + // directly here. + if level <= PanicLevel { + panic(&entry) + } +} + +// This function is not declared with a pointer value because otherwise +// race conditions will occur when using multiple goroutines +func (entry Entry) fireHooks() { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + err := entry.Logger.Hooks.Fire(entry.Level, &entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) + } +} + +func (entry *Entry) write() { + serialized, err := entry.Logger.Formatter.Format(entry) + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() if err != nil { - entry.Logger.mu.Lock() fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) - entry.Logger.mu.Unlock() } else { - entry.Logger.mu.Lock() _, err = entry.Logger.Out.Write(serialized) if err != nil { fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) } - entry.Logger.mu.Unlock() - } - - // To avoid Entry#log() returning a value that only would make sense for - // panic() to use in Entry#Panic(), we avoid the allocation by checking - // directly here. - if level <= PanicLevel { - panic(&entry) } } diff -Nru golang-logrus-1.0.2/entry_test.go golang-logrus-1.0.5/entry_test.go --- golang-logrus-1.0.2/entry_test.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/entry_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -75,3 +75,41 @@ entry := NewEntry(logger) entry.WithField("err", errBoom).Panicf("kaboom %v", true) } + +const ( + badMessage = "this is going to panic" + panicMessage = "this is broken" +) + +type panickyHook struct{} + +func (p *panickyHook) Levels() []Level { + return []Level{InfoLevel} +} + +func (p *panickyHook) Fire(entry *Entry) error { + if entry.Message == badMessage { + panic(panicMessage) + } + + return nil +} + +func TestEntryHooksPanic(t *testing.T) { + logger := New() + logger.Out = &bytes.Buffer{} + logger.Level = InfoLevel + logger.Hooks.Add(&panickyHook{}) + + defer func() { + p := recover() + assert.NotNil(t, p) + assert.Equal(t, panicMessage, p) + + entry := NewEntry(logger) + entry.Info("another message") + }() + + entry := NewEntry(logger) + entry.Info(badMessage) +} diff -Nru golang-logrus-1.0.2/example_basic_test.go golang-logrus-1.0.5/example_basic_test.go --- golang-logrus-1.0.2/example_basic_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/example_basic_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -0,0 +1,69 @@ +package logrus_test + +import ( + "github.com/sirupsen/logrus" + "os" +) + +func Example_basic() { + var log = logrus.New() + log.Formatter = new(logrus.JSONFormatter) + log.Formatter = new(logrus.TextFormatter) //default + log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output + log.Level = logrus.DebugLevel + log.Out = os.Stdout + + // 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") + // } + + defer func() { + err := recover() + if err != nil { + entry := err.(*logrus.Entry) + log.WithFields(logrus.Fields{ + "omg": true, + "err_animal": entry.Data["animal"], + "err_size": entry.Data["size"], + "err_level": entry.Level, + "err_message": entry.Message, + "number": 100, + }).Error("The ice breaks!") // or use Fatal() to force the process to exit with a nonzero code + } + }() + + 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!") + + // Output: + // level=debug msg="Started observing beach" animal=walrus number=8 + // level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 + // level=warning msg="The group's number increased tremendously!" number=122 omg=true + // level=debug msg="Temperature changes" temperature=-4 + // level=panic msg="It's over 9000!" animal=orca size=9009 + // level=error msg="The ice breaks!" err_animal=orca err_level=panic err_message="It's over 9000!" err_size=9009 number=100 omg=true +} diff -Nru golang-logrus-1.0.2/example_hook_test.go golang-logrus-1.0.5/example_hook_test.go --- golang-logrus-1.0.2/example_hook_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/example_hook_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -0,0 +1,35 @@ +package logrus_test + +import ( + "github.com/sirupsen/logrus" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" + "os" +) + +func Example_hook() { + var log = logrus.New() + log.Formatter = new(logrus.TextFormatter) // default + log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output + log.Hooks.Add(airbrake.NewHook(123, "xyz", "development")) + log.Out = os.Stdout + + 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, + }).Error("The ice breaks!") + + // Output: + // level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 + // level=warning msg="The group's number increased tremendously!" number=122 omg=true + // level=error msg="The ice breaks!" number=100 omg=true +} diff -Nru golang-logrus-1.0.2/examples/basic/basic.go golang-logrus-1.0.5/examples/basic/basic.go --- golang-logrus-1.0.2/examples/basic/basic.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/examples/basic/basic.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -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!") -} diff -Nru golang-logrus-1.0.2/examples/hook/hook.go golang-logrus-1.0.5/examples/hook/hook.go --- golang-logrus-1.0.2/examples/hook/hook.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/examples/hook/hook.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -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!") -} diff -Nru golang-logrus-1.0.2/formatter.go golang-logrus-1.0.5/formatter.go --- golang-logrus-1.0.2/formatter.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/formatter.go 2018-03-11 22:51:37.000000000 +0000 @@ -2,7 +2,7 @@ import "time" -const DefaultTimestampFormat = time.RFC3339 +const defaultTimestampFormat = time.RFC3339 // The Formatter interface is used to implement a custom Formatter. It takes an // `Entry`. It exposes all the fields, including the default ones: diff -Nru golang-logrus-1.0.2/hooks/syslog/README.md golang-logrus-1.0.5/hooks/syslog/README.md --- golang-logrus-1.0.2/hooks/syslog/README.md 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/hooks/syslog/README.md 2018-03-11 22:51:37.000000000 +0000 @@ -6,12 +6,12 @@ import ( "log/syslog" "github.com/sirupsen/logrus" - logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" + lSyslog "github.com/sirupsen/logrus/hooks/syslog" ) func main() { log := logrus.New() - hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + hook, err := lSyslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") if err == nil { log.Hooks.Add(hook) @@ -25,12 +25,12 @@ import ( "log/syslog" "github.com/sirupsen/logrus" - logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" + lSyslog "github.com/sirupsen/logrus/hooks/syslog" ) func main() { log := logrus.New() - hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "") + hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "") if err == nil { log.Hooks.Add(hook) diff -Nru golang-logrus-1.0.2/hooks/syslog/syslog.go golang-logrus-1.0.5/hooks/syslog/syslog.go --- golang-logrus-1.0.2/hooks/syslog/syslog.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/hooks/syslog/syslog.go 2018-03-11 22:51:37.000000000 +0000 @@ -1,12 +1,13 @@ // +build !windows,!nacl,!plan9 -package logrus_syslog +package syslog import ( "fmt" - "github.com/sirupsen/logrus" "log/syslog" "os" + + "github.com/sirupsen/logrus" ) // SyslogHook to send logs via syslog. diff -Nru golang-logrus-1.0.2/hooks/syslog/syslog_test.go golang-logrus-1.0.5/hooks/syslog/syslog_test.go --- golang-logrus-1.0.2/hooks/syslog/syslog_test.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/hooks/syslog/syslog_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -1,9 +1,10 @@ -package logrus_syslog +package syslog import ( - "github.com/sirupsen/logrus" "log/syslog" "testing" + + "github.com/sirupsen/logrus" ) func TestLocalhostAddAndPrint(t *testing.T) { diff -Nru golang-logrus-1.0.2/hooks/test/test_test.go golang-logrus-1.0.5/hooks/test/test_test.go --- golang-logrus-1.0.2/hooks/test/test_test.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/hooks/test/test_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -1,6 +1,7 @@ package test import ( + "sync" "testing" "github.com/sirupsen/logrus" @@ -8,7 +9,6 @@ ) func TestAllHooks(t *testing.T) { - assert := assert.New(t) logger, hook := NewNullLogger() @@ -35,5 +35,27 @@ assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level) assert.Equal("Hello error", hook.LastEntry().Message) assert.Equal(1, len(hook.Entries)) +} + +func TestLoggingWithHooksRace(t *testing.T) { + assert := assert.New(t) + logger, hook := NewNullLogger() + + var wg sync.WaitGroup + wg.Add(100) + + for i := 0; i < 100; i++ { + go func() { + logger.Info("info") + wg.Done() + }() + } + + assert.Equal(logrus.InfoLevel, hook.LastEntry().Level) + assert.Equal("info", hook.LastEntry().Message) + + wg.Wait() + entries := hook.AllEntries() + assert.Equal(100, len(entries)) } diff -Nru golang-logrus-1.0.2/hook_test.go golang-logrus-1.0.5/hook_test.go --- golang-logrus-1.0.2/hook_test.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/hook_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -1,6 +1,7 @@ package logrus import ( + "sync" "testing" "github.com/stretchr/testify/assert" @@ -120,3 +121,24 @@ assert.Equal(t, hook.Fired, true) }) } + +func TestAddHookRace(t *testing.T) { + var wg sync.WaitGroup + wg.Add(2) + hook := new(ErrorHook) + LogAndAssertJSON(t, func(log *Logger) { + go func() { + defer wg.Done() + log.AddHook(hook) + }() + go func() { + defer wg.Done() + log.Error("test") + }() + wg.Wait() + }, func(fields Fields) { + // the line may have been logged + // before the hook was added, so we can't + // actually assert on the hook + }) +} diff -Nru golang-logrus-1.0.2/json_formatter.go golang-logrus-1.0.5/json_formatter.go --- golang-logrus-1.0.2/json_formatter.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/json_formatter.go 2018-03-11 22:51:37.000000000 +0000 @@ -6,8 +6,11 @@ ) type fieldKey string + +// FieldMap allows customization of the key names for default fields. type FieldMap map[fieldKey]string +// Default key names for the default fields const ( FieldKeyMsg = "msg" FieldKeyLevel = "level" @@ -22,6 +25,7 @@ return string(key) } +// JSONFormatter formats logs into parsable json type JSONFormatter struct { // TimestampFormat sets the format used for marshaling timestamps. TimestampFormat string @@ -29,7 +33,7 @@ // DisableTimestamp allows disabling automatic timestamps in output DisableTimestamp bool - // FieldMap allows users to customize the names of keys for various fields. + // FieldMap allows users to customize the names of keys for default fields. // As an example: // formatter := &JSONFormatter{ // FieldMap: FieldMap{ @@ -41,6 +45,7 @@ FieldMap FieldMap } +// Format renders a single log entry func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { data := make(Fields, len(entry.Data)+3) for k, v := range entry.Data { @@ -57,7 +62,7 @@ timestampFormat := f.TimestampFormat if timestampFormat == "" { - timestampFormat = DefaultTimestampFormat + timestampFormat = defaultTimestampFormat } if !f.DisableTimestamp { diff -Nru golang-logrus-1.0.2/logger.go golang-logrus-1.0.5/logger.go --- golang-logrus-1.0.2/logger.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/logger.go 2018-03-11 22:51:37.000000000 +0000 @@ -25,7 +25,7 @@ Formatter Formatter // The logging level the logger should log at. This is typically (and defaults // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be - // logged. `logrus.Debug` is useful in + // logged. Level Level // Used to sync writing to the log. Locking is enabled by Default mu MutexWrap @@ -315,3 +315,9 @@ func (logger *Logger) SetLevel(level Level) { atomic.StoreUint32((*uint32)(&logger.Level), uint32(level)) } + +func (logger *Logger) AddHook(hook Hook) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Hooks.Add(hook) +} diff -Nru golang-logrus-1.0.2/README.md golang-logrus-1.0.5/README.md --- golang-logrus-1.0.2/README.md 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/README.md 2018-03-11 22:51:37.000000000 +0000 @@ -1,7 +1,7 @@ # Logrus :walrus: [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](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]. +the standard library logger. **Seeing weird case-sensitive problems?** It's in the past been possible to import Logrus as both upper- and lower-case. Due to the Go package environment, @@ -220,7 +220,7 @@ ```go import ( log "github.com/sirupsen/logrus" - "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake" logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" "log/syslog" ) @@ -247,6 +247,8 @@ | [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) | +| [Application Insights](https://github.com/jjcollinge/logrus-appinsights) | Hook for logging to [Application Insights](https://azure.microsoft.com/en-us/services/application-insights/) +| [AzureTableHook](https://github.com/kpfaulkner/azuretablehook/) | Hook for logging to Azure Table Storage| | [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/) | @@ -260,8 +262,10 @@ | [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 | +| [KafkaLogrus](https://github.com/tracer0tong/kafkalogrus) | Hook for logging to Kafka | +| [Kafka REST Proxy](https://github.com/Nordstrom/logrus-kafka-rest-proxy) | Hook for logging to [Kafka REST Proxy](https://docs.confluent.io/current/kafka-rest/docs) | | [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem | +| [Logbeat](https://github.com/macandmia/logbeat) | Hook for logging to [Opbeat](https://opbeat.com/) | | [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/) | @@ -274,6 +278,7 @@ | [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) | +| [Promrus](https://github.com/weaveworks/promrus) | Expose number of log messages as [Prometheus](https://prometheus.io/) metrics | | [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) | @@ -285,6 +290,7 @@ | [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. | +| [Telegram](https://github.com/rossmcdonald/telegram_hook) | Hook for logging errors to [Telegram](https://telegram.org/) | | [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 | @@ -372,6 +378,7 @@ Third party logging formatters: +* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine. * [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. * [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. * [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. diff -Nru golang-logrus-1.0.2/terminal_appengine.go golang-logrus-1.0.5/terminal_appengine.go --- golang-logrus-1.0.2/terminal_appengine.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/terminal_appengine.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -// +build appengine - -package logrus - -import "io" - -// IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal(f io.Writer) bool { - return true -} diff -Nru golang-logrus-1.0.2/terminal_bsd.go golang-logrus-1.0.5/terminal_bsd.go --- golang-logrus-1.0.2/terminal_bsd.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/terminal_bsd.go 2018-03-11 22:51:37.000000000 +0000 @@ -1,10 +1,10 @@ // +build darwin freebsd openbsd netbsd dragonfly -// +build !appengine +// +build !appengine,!gopherjs package logrus -import "syscall" +import "golang.org/x/sys/unix" -const ioctlReadTermios = syscall.TIOCGETA +const ioctlReadTermios = unix.TIOCGETA -type Termios syscall.Termios +type Termios unix.Termios diff -Nru golang-logrus-1.0.2/terminal_check_appengine.go golang-logrus-1.0.5/terminal_check_appengine.go --- golang-logrus-1.0.2/terminal_check_appengine.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/terminal_check_appengine.go 2018-03-11 22:51:37.000000000 +0000 @@ -0,0 +1,11 @@ +// +build appengine gopherjs + +package logrus + +import ( + "io" +) + +func checkIfTerminal(w io.Writer) bool { + return true +} diff -Nru golang-logrus-1.0.2/terminal_check_notappengine.go golang-logrus-1.0.5/terminal_check_notappengine.go --- golang-logrus-1.0.2/terminal_check_notappengine.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-logrus-1.0.5/terminal_check_notappengine.go 2018-03-11 22:51:37.000000000 +0000 @@ -0,0 +1,19 @@ +// +build !appengine,!gopherjs + +package logrus + +import ( + "io" + "os" + + "golang.org/x/crypto/ssh/terminal" +) + +func checkIfTerminal(w io.Writer) bool { + switch v := w.(type) { + case *os.File: + return terminal.IsTerminal(int(v.Fd())) + default: + return false + } +} diff -Nru golang-logrus-1.0.2/terminal_linux.go golang-logrus-1.0.5/terminal_linux.go --- golang-logrus-1.0.2/terminal_linux.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/terminal_linux.go 2018-03-11 22:51:37.000000000 +0000 @@ -3,12 +3,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !appengine +// +build !appengine,!gopherjs package logrus -import "syscall" +import "golang.org/x/sys/unix" -const ioctlReadTermios = syscall.TCGETS +const ioctlReadTermios = unix.TCGETS -type Termios syscall.Termios +type Termios unix.Termios diff -Nru golang-logrus-1.0.2/terminal_notwindows.go golang-logrus-1.0.5/terminal_notwindows.go --- golang-logrus-1.0.2/terminal_notwindows.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/terminal_notwindows.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +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 linux darwin freebsd openbsd netbsd dragonfly -// +build !appengine - -package logrus - -import ( - "io" - "os" - "syscall" - "unsafe" -) - -// IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal(f io.Writer) bool { - var termios Termios - 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 -Nru golang-logrus-1.0.2/terminal_solaris.go golang-logrus-1.0.5/terminal_solaris.go --- golang-logrus-1.0.2/terminal_solaris.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/terminal_solaris.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -// +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 - } -} diff -Nru golang-logrus-1.0.2/terminal_windows.go golang-logrus-1.0.5/terminal_windows.go --- golang-logrus-1.0.2/terminal_windows.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/terminal_windows.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +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 ( - "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 - } -} diff -Nru golang-logrus-1.0.2/text_formatter.go golang-logrus-1.0.5/text_formatter.go --- golang-logrus-1.0.2/text_formatter.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/text_formatter.go 2018-03-11 22:51:37.000000000 +0000 @@ -26,6 +26,7 @@ baseTimestamp = time.Now() } +// TextFormatter formats logs into text type TextFormatter struct { // Set to true to bypass checking for a TTY before outputting colors. ForceColors bool @@ -52,10 +53,6 @@ // 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 @@ -63,14 +60,12 @@ } func (f *TextFormatter) init(entry *Entry) { - if len(f.QuoteCharacter) == 0 { - f.QuoteCharacter = "\"" - } if entry.Logger != nil { - f.isTerminal = IsTerminal(entry.Logger.Out) + f.isTerminal = checkIfTerminal(entry.Logger.Out) } } +// Format renders a single log entry func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { var b *bytes.Buffer keys := make([]string, 0, len(entry.Data)) @@ -95,7 +90,7 @@ timestampFormat := f.TimestampFormat if timestampFormat == "" { - timestampFormat = DefaultTimestampFormat + timestampFormat = defaultTimestampFormat } if isColored { f.printColored(b, entry, keys, timestampFormat) @@ -161,11 +156,12 @@ } func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { - + if b.Len() > 0 { + b.WriteByte(' ') + } b.WriteString(key) b.WriteByte('=') f.appendValue(b, value) - b.WriteByte(' ') } func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { @@ -177,13 +173,6 @@ if !f.needsQuoting(stringVal) { b.WriteString(stringVal) } else { - b.WriteString(f.quoteString(stringVal)) + b.WriteString(fmt.Sprintf("%q", stringVal)) } } - -func (f *TextFormatter) quoteString(v string) string { - escapedQuote := fmt.Sprintf("\\%s", f.QuoteCharacter) - escapedValue := strings.Replace(v, f.QuoteCharacter, escapedQuote, -1) - - return fmt.Sprintf("%s%v%s", f.QuoteCharacter, escapedValue, f.QuoteCharacter) -} diff -Nru golang-logrus-1.0.2/text_formatter_test.go golang-logrus-1.0.5/text_formatter_test.go --- golang-logrus-1.0.2/text_formatter_test.go 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/text_formatter_test.go 2018-03-11 22:51:37.000000000 +0000 @@ -3,19 +3,38 @@ import ( "bytes" "errors" + "fmt" "strings" "testing" "time" - "fmt" ) +func TestFormatting(t *testing.T) { + tf := &TextFormatter{DisableColors: true} + + testCases := []struct { + value string + expected string + }{ + {`foo`, "time=\"0001-01-01T00:00:00Z\" level=panic test=foo\n"}, + } + + for _, tc := range testCases { + b, _ := tf.Format(WithField("test", tc.value)) + + if string(b) != tc.expected { + t.Errorf("formatting expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected) + } + } +} + 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)) + cont := bytes.Contains(b[idx+5:], []byte("\"")) if cont != q { if q { t.Errorf("quoting expected for: %#v", value) @@ -41,23 +60,6 @@ checkQuoting(false, errors.New("invalid")) checkQuoting(true, errors.New("invalid argument")) - // Test for custom quote character. - tf.QuoteCharacter = "`" - checkQuoting(false, "") - checkQuoting(false, "abcd") - checkQuoting(false, "/foobar") - checkQuoting(false, "foo_bar") - checkQuoting(false, "foo@bar") - checkQuoting(false, "foobar^") - checkQuoting(true, "foobar$") - 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, "") @@ -65,7 +67,7 @@ checkQuoting(true, errors.New("invalid argument")) } -func TestEscaping_DefaultQuoteCharacter(t *testing.T) { +func TestEscaping(t *testing.T) { tf := &TextFormatter{DisableColors: true} testCases := []struct { @@ -105,35 +107,13 @@ } } -func TestEscaping_CustomQuoteCharacter(t *testing.T) { - tf := &TextFormatter{DisableColors: true} - - testCases := []struct { - value string - expected string - quoteChar string - }{ - {`ba"r`, `ba"r`, `'`}, - {`ba'r`, `ba\'r`, `'`}, - {`ba'r`, `ba'r`, `^`}, - } - - for _, tc := range testCases { - tf.QuoteCharacter = tc.quoteChar - b, _ := tf.Format(WithField("test", tc.value)) - if !bytes.Contains(b, []byte(tc.expected)) { - t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected) - } - } -} - 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)] + timeStr := customStr[timeStart+5+len("\"") : timeEnd-1-len("\"")] if format == "" { format = time.RFC3339 } diff -Nru golang-logrus-1.0.2/.travis.yml golang-logrus-1.0.5/.travis.yml --- golang-logrus-1.0.2/.travis.yml 2017-07-13 11:42:50.000000000 +0000 +++ golang-logrus-1.0.5/.travis.yml 2018-03-11 22:51:37.000000000 +0000 @@ -8,5 +8,8 @@ - GOMAXPROCS=4 GORACE=halt_on_error=1 install: - go get github.com/stretchr/testify/assert + - go get gopkg.in/gemnasium/logrus-airbrake-hook.v2 + - go get golang.org/x/sys/unix + - go get golang.org/x/sys/windows script: - - go test -race -v . + - go test -race -v ./...