Hello community,
here is the log from the commit of package kured for openSUSE:Factory checked in at 2019-03-29 20:33:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kured (Old)
and /work/SRC/openSUSE:Factory/.kured.new.25356 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kured"
Fri Mar 29 20:33:40 2019 rev:5 rq:689655 version:1.1.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/kured/kured.changes 2019-03-01 16:48:49.877767220 +0100
+++ /work/SRC/openSUSE:Factory/.kured.new.25356/kured.changes 2019-03-29 20:33:41.610628890 +0100
@@ -1,0 +2,11 @@
+Thu Mar 28 17:44:13 UTC 2019 - Jan Engelhardt
+
+- Combine %setup calls.
+
+-------------------------------------------------------------------
+Thu Mar 28 11:48:25 CET 2019 - kukuk@suse.de
+
+- kured-telemetrics.patch: add hooks for telemetrics data
+- Renamed kured-yaml to kured-k8s-yaml to follow new policy
+
+-------------------------------------------------------------------
New:
----
kured-telemetrics.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ kured.spec ++++++
--- /var/tmp/diff_new_pack.AHMk5e/_old 2019-03-29 20:33:42.466628943 +0100
+++ /var/tmp/diff_new_pack.AHMk5e/_new 2019-03-29 20:33:42.470628942 +0100
@@ -32,6 +32,7 @@
URL: https://github.com/weaveworks/kured
Source: %{name}-%{version}.tar.gz
Source1: vendor.tar.gz
+Patch: kured-telemetrics.patch
BuildRequires: fdupes
BuildRequires: go >= 1.10
BuildRequires: go-go-md2man
@@ -53,18 +54,20 @@
- Cordons & drains worker nodes before reboot, uncordoning them after
-%package yaml
-Summary: yaml file to run kured container
+%package k8s-yaml
+Summary: Kubernetes yaml file to run kured container
Group: System/Management
BuildArch: noarch
+Provides: kured-yaml = 1.1.0
+Obsoletes: kured-yaml <= 1.1.0
-%description yaml
+%description k8s-yaml
This package contains the yaml file requried to download and run the
kured container in a kubernetes cluster.
%prep
-%setup -q
-%setup -q -T -D -a 1
+%setup -qa1
+%patch -p0
%build
@@ -97,10 +100,10 @@
rm %{name}.1
# Install provided yaml file to download and run the kured container
-mkdir %{buildroot}%{_datadir}/kured
-cat kured-rbac.yaml kured-ds.yaml > %{buildroot}%{_datadir}/kured/kured-%{version}.yaml
-chmod 644 %{buildroot}%{_datadir}/kured/kured-%{version}.yaml
-sed -i -e 's|image: quay.io/weaveworks/kured|image: registry.opensuse.org/kubic/kured:%{version}|g' %{buildroot}%{_datadir}/kured/kured-%{version}.yaml
+mkdir -p %{buildroot}%{_datadir}/k8s-yaml/kured
+cat kured-rbac.yaml kured-ds.yaml > %{buildroot}%{_datadir}/k8s-yaml/kured/kured.yaml
+chmod 644 %{buildroot}%{_datadir}/k8s-yaml/kured/kured.yaml
+sed -i -e 's|image: quay.io/weaveworks/kured|image: registry.opensuse.org/kubic/kured:%{version}|g' %{buildroot}%{_datadir}/k8s-yaml/kured/kured.yaml
%fdupes %{buildroot}
@@ -110,8 +113,9 @@
%{_bindir}/%{name}
%{_mandir}/man1/kured.1%{?ext_man}
-%files yaml
-%dir %{_datarootdir}/kured
-%{_datarootdir}/kured/kured-%{version}.yaml
+%files k8s-yaml
+%dir %{_datarootdir}/k8s-yaml
+%dir %{_datarootdir}/k8s-yaml/kured
+%{_datarootdir}/k8s-yaml/kured/kured.yaml
%changelog
++++++ kured-telemetrics.patch ++++++
--- cmd/kured/main.go
+++ cmd/kured/main.go 2019/03/13 12:06:12
@@ -8,7 +8,7 @@
"regexp"
"time"
- log "github.com/sirupsen/logrus"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
@@ -20,6 +20,7 @@
"github.com/weaveworks/kured/pkg/daemonsetlock"
"github.com/weaveworks/kured/pkg/delaytick"
"github.com/weaveworks/kured/pkg/notifications/slack"
+ "github.com/weaveworks/kured/pkg/notifications/telemetrics"
)
var (
@@ -35,6 +36,8 @@
rebootSentinel string
slackHookURL string
slackUsername string
+ telemetricsEnabled bool
+ telemetricsLevel int
// Metrics
rebootRequiredGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
@@ -42,6 +45,8 @@
Name: "reboot_required",
Help: "OS requires reboot due to software updates.",
}, []string{"node"})
+
+ log = logrus.New()
)
func init() {
@@ -74,6 +79,11 @@
rootCmd.PersistentFlags().StringVar(&slackUsername, "slack-username", "kured",
"slack username for reboot notfications")
+ rootCmd.PersistentFlags().BoolVarP(&telemetricsEnabled, "telemetrics", "", false,
+ "Enable telemetrics messages")
+ rootCmd.PersistentFlags().IntVarP(&telemetricsLevel, "telemetrics-level", "", 2,
+ "Only telemetrics messages with this or a higher severity level are submitted")
+
if err := rootCmd.Execute(); err != nil {
log.Fatal(err)
}
@@ -83,15 +93,15 @@
func newCommand(name string, arg ...string) *exec.Cmd {
cmd := exec.Command(name, arg...)
- cmd.Stdout = log.NewEntry(log.StandardLogger()).
+ cmd.Stdout = logrus.NewEntry(logrus.StandardLogger()).
WithField("cmd", cmd.Args[0]).
WithField("std", "out").
- WriterLevel(log.InfoLevel)
+ WriterLevel(logrus.InfoLevel)
- cmd.Stderr = log.NewEntry(log.StandardLogger()).
+ cmd.Stderr = logrus.NewEntry(logrus.StandardLogger()).
WithField("cmd", cmd.Args[0]).
WithField("std", "err").
- WriterLevel(log.WarnLevel)
+ WriterLevel(logrus.WarnLevel)
return cmd
}
@@ -186,6 +196,9 @@
log.Warnf("Error notifying slack: %v", err)
}
}
+ if telemetricsEnabled {
+ telemetrics.NotifyDrain(nodeID)
+ }
drainCmd := newCommand("/usr/bin/kubectl", "drain",
"--ignore-daemonsets", "--delete-local-data", "--force", nodeID)
@@ -211,6 +224,9 @@
log.Warnf("Error notifying slack: %v", err)
}
}
+ if telemetricsEnabled {
+ telemetrics.NotifyReboot(nodeID)
+ }
// Relies on hostPID:true and privileged:true to enter host mount space
rebootCmd := newCommand("/usr/bin/nsenter", "-m/proc/1/ns/mnt", "/bin/systemctl", "reboot")
@@ -292,6 +308,13 @@
log.Infof("Lock Annotation: %s/%s:%s", dsNamespace, dsName, lockAnnotation)
log.Infof("Reboot Sentinel: %s every %v", rebootSentinel, period)
+ if telemetricsEnabled {
+ hook, err := telemetrics.NewTelemetricsHook(telemetricsEnabled, telemetricsLevel)
+ if err == nil {
+ log.Hooks.Add(hook)
+ }
+ }
+
go rebootAsRequired(nodeID)
go maintainRebootRequiredMetric(nodeID)
--- kured-ds.yaml
+++ kured-ds.yaml 2019/03/13 11:45:31
@@ -54,3 +54,5 @@
# - --reboot-sentinel=/var/run/reboot-required
# - --slack-hook-url=https://hooks.slack.com/...
# - --slack-username=prod
+# - --telemetrics
+# - --telemetrics-level=2
--- pkg/notifications/telemetrics/telemetrics.go
+++ pkg/notifications/telemetrics/telemetrics.go 2019/03/13 12:17:41
@@ -0,0 +1,70 @@
+package telemetrics
+
+import (
+ "os"
+ "os/exec"
+ "fmt"
+ "github.com/sirupsen/logrus"
+ "strconv"
+)
+
+func notify(severity int, message string) error {
+ // Relies on hostPID:true and privileged:true to enter host mount space
+ telemCmd := exec.Command("/usr/bin/nsenter", "-m/proc/1/ns/mnt",
+ "--", "/usr/bin/telem-record-gen", "-s", strconv.Itoa(severity), "-c",
+ "works.weave/kured/reboot", "--payload", message)
+ if err := telemCmd.Run(); err != nil {
+ fmt.Fprintf(os.Stderr, "Error invoking telm-record-gen command: %v", err)
+ return err
+ }
+ return nil
+}
+
+func NotifyDrain(nodeID string) error {
+ return notify(1, fmt.Sprintf("Draining node %s", nodeID))
+}
+
+func NotifyReboot(nodeID string) error {
+ return notify(1, fmt.Sprintf("Rebooting node %s", nodeID))
+}
+
+type TelemetricsHook struct {
+ enabled bool
+ min_level int
+}
+
+func NewTelemetricsHook(enabled bool, min_level int) (*TelemetricsHook, error) {
+ return &TelemetricsHook{enabled, min_level}, nil
+}
+
+func (hook *TelemetricsHook) Fire(entry *logrus.Entry) error {
+ switch entry.Level {
+ case logrus.PanicLevel, logrus.FatalLevel:
+ if hook.min_level <= 4 {
+ return notify (4, entry.Message)
+ }
+ case logrus.ErrorLevel:
+ if hook.min_level <= 3 {
+ return notify (3, entry.Message)
+ }
+ case logrus.WarnLevel:
+ if hook.min_level <= 2 {
+ return notify (2, entry.Message)
+ }
+ case logrus.InfoLevel:
+ if hook.min_level <= 1 {
+ return notify (1, entry.Message)
+ }
+ case logrus.DebugLevel, logrus.TraceLevel:
+ if hook.min_level == 0 {
+ return notify (1, entry.Message)
+ }
+ default:
+ return nil
+ }
+ return nil
+}
+
+func (hook *TelemetricsHook) Levels() []logrus.Level {
+ return logrus.AllLevels
+}
++++++ vendor.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/alt_exit.go new/vendor/github.com/sirupsen/logrus/alt_exit.go
--- old/vendor/github.com/sirupsen/logrus/alt_exit.go 2018-11-15 20:22:56.986337192 +0100
+++ new/vendor/github.com/sirupsen/logrus/alt_exit.go 2019-03-12 13:15:34.130444171 +0100
@@ -51,9 +51,9 @@
os.Exit(code)
}
-// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
-// all handlers. The handlers will also be invoked when any Fatal log entry is
-// made.
+// RegisterExitHandler appends a Logrus Exit handler to the list of handlers,
+// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
+// any Fatal log entry is made.
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
@@ -62,3 +62,15 @@
func RegisterExitHandler(handler func()) {
handlers = append(handlers, handler)
}
+
+// DeferExitHandler prepends a Logrus Exit handler to the list of handlers,
+// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
+// any Fatal log entry is made.
+//
+// This method is useful when a caller wishes to use logrus to log a fatal
+// message but also needs to gracefully shutdown. An example usecase could be
+// closing database connections, or sending a alert that the application is
+// closing.
+func DeferExitHandler(handler func()) {
+ handlers = append([]func(){handler}, handlers...)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/entry.go new/vendor/github.com/sirupsen/logrus/entry.go
--- old/vendor/github.com/sirupsen/logrus/entry.go 2018-11-15 20:22:56.986337192 +0100
+++ new/vendor/github.com/sirupsen/logrus/entry.go 2019-03-12 13:15:34.130444171 +0100
@@ -2,14 +2,33 @@
import (
"bytes"
+ "context"
"fmt"
"os"
"reflect"
+ "runtime"
+ "strings"
"sync"
"time"
)
-var bufferPool *sync.Pool
+var (
+ bufferPool *sync.Pool
+
+ // qualified package name, cached at first use
+ logrusPackage string
+
+ // Positions in the call stack when tracing to report the calling method
+ minimumCallerDepth int
+
+ // Used for caller information initialisation
+ callerInitOnce sync.Once
+)
+
+const (
+ maximumCallerDepth int = 25
+ knownLogrusFrames int = 4
+)
func init() {
bufferPool = &sync.Pool{
@@ -17,15 +36,18 @@
return new(bytes.Buffer)
},
}
+
+ // start at the bottom of the stack before the package-name cache is primed
+ minimumCallerDepth = 1
}
// Defines the key when adding errors using WithError.
var ErrorKey = "error"
// An entry is the final or intermediate Logrus logging entry. It contains all
-// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
-// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
-// passed around as much as you wish to avoid field duplication.
+// the fields passed with WithField{,s}. It's finally logged when Trace, Debug,
+// Info, Warn, Error, Fatal or Panic is called on it. These objects can be
+// reused and passed around as much as you wish to avoid field duplication.
type Entry struct {
Logger *Logger
@@ -35,16 +57,22 @@
// Time at which the log entry was created
Time time.Time
- // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
+ // Level the log entry was logged at: Trace, 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
+ // Calling method, with package name
+ Caller *runtime.Frame
+
+ // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
Message string
// When formatter is called in entry.log(), a Buffer may be set to entry
Buffer *bytes.Buffer
+ // Contains the context set by the user. Useful for hook processing etc.
+ Context context.Context
+
// err may contain a field formatting error
err string
}
@@ -52,8 +80,8 @@
func NewEntry(logger *Logger) *Entry {
return &Entry{
Logger: logger,
- // Default is five fields, give a little extra room
- Data: make(Fields, 5),
+ // Default is three fields, plus one optional. Give a little extra room.
+ Data: make(Fields, 6),
}
}
@@ -73,6 +101,12 @@
return entry.WithField(ErrorKey, err)
}
+// Add a context to the Entry.
+func (entry *Entry) WithContext(ctx context.Context) *Entry {
+ entry.Context = ctx
+ return entry
+}
+
// Add a single field to the Entry.
func (entry *Entry) WithField(key string, value interface{}) *Entry {
return entry.WithFields(Fields{key: value})
@@ -84,23 +118,88 @@
for k, v := range entry.Data {
data[k] = v
}
- var field_err string
+ fieldErr := entry.err
for k, v := range fields {
- if t := reflect.TypeOf(v); t != nil && t.Kind() == reflect.Func {
- field_err = fmt.Sprintf("can not add field %q", k)
- if entry.err != "" {
- field_err = entry.err + ", " + field_err
+ isErrField := false
+ if t := reflect.TypeOf(v); t != nil {
+ switch t.Kind() {
+ case reflect.Func:
+ isErrField = true
+ case reflect.Ptr:
+ isErrField = t.Elem().Kind() == reflect.Func
+ }
+ }
+ if isErrField {
+ tmp := fmt.Sprintf("can not add field %q", k)
+ if fieldErr != "" {
+ fieldErr = entry.err + ", " + tmp
+ } else {
+ fieldErr = tmp
}
} else {
data[k] = v
}
}
- return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: field_err}
+ return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
}
// Overrides the time of the Entry.
func (entry *Entry) WithTime(t time.Time) *Entry {
- return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t}
+ return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err, Context: entry.Context}
+}
+
+// getPackageName reduces a fully qualified function name to the package name
+// There really ought to be to be a better way...
+func getPackageName(f string) string {
+ for {
+ lastPeriod := strings.LastIndex(f, ".")
+ lastSlash := strings.LastIndex(f, "/")
+ if lastPeriod > lastSlash {
+ f = f[:lastPeriod]
+ } else {
+ break
+ }
+ }
+
+ return f
+}
+
+// getCaller retrieves the name of the first non-logrus calling function
+func getCaller() *runtime.Frame {
+
+ // cache this package's fully-qualified name
+ callerInitOnce.Do(func() {
+ pcs := make([]uintptr, 2)
+ _ = runtime.Callers(0, pcs)
+ logrusPackage = getPackageName(runtime.FuncForPC(pcs[1]).Name())
+
+ // now that we have the cache, we can skip a minimum count of known-logrus functions
+ // XXX this is dubious, the number of frames may vary
+ minimumCallerDepth = knownLogrusFrames
+ })
+
+ // Restrict the lookback frames to avoid runaway lookups
+ pcs := make([]uintptr, maximumCallerDepth)
+ depth := runtime.Callers(minimumCallerDepth, pcs)
+ frames := runtime.CallersFrames(pcs[:depth])
+
+ for f, again := frames.Next(); again; f, again = frames.Next() {
+ pkg := getPackageName(f.Function)
+
+ // If the caller isn't part of this package, we're done
+ if pkg != logrusPackage {
+ return &f
+ }
+ }
+
+ // if we got here, we failed to find the caller's context
+ return nil
+}
+
+func (entry Entry) HasCaller() (has bool) {
+ return entry.Logger != nil &&
+ entry.Logger.ReportCaller &&
+ entry.Caller != nil
}
// This function is not declared with a pointer value because otherwise
@@ -119,6 +218,9 @@
entry.Level = level
entry.Message = msg
+ if entry.Logger.ReportCaller {
+ entry.Caller = getCaller()
+ }
entry.fireHooks()
@@ -162,26 +264,30 @@
}
}
-func (entry *Entry) Debug(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(DebugLevel) {
- entry.log(DebugLevel, fmt.Sprint(args...))
+func (entry *Entry) Log(level Level, args ...interface{}) {
+ if entry.Logger.IsLevelEnabled(level) {
+ entry.log(level, fmt.Sprint(args...))
}
}
+func (entry *Entry) Trace(args ...interface{}) {
+ entry.Log(TraceLevel, args...)
+}
+
+func (entry *Entry) Debug(args ...interface{}) {
+ entry.Log(DebugLevel, args...)
+}
+
func (entry *Entry) Print(args ...interface{}) {
entry.Info(args...)
}
func (entry *Entry) Info(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(InfoLevel) {
- entry.log(InfoLevel, fmt.Sprint(args...))
- }
+ entry.Log(InfoLevel, args...)
}
func (entry *Entry) Warn(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(WarnLevel) {
- entry.log(WarnLevel, fmt.Sprint(args...))
- }
+ entry.Log(WarnLevel, args...)
}
func (entry *Entry) Warning(args ...interface{}) {
@@ -189,37 +295,37 @@
}
func (entry *Entry) Error(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(ErrorLevel) {
- entry.log(ErrorLevel, fmt.Sprint(args...))
- }
+ entry.Log(ErrorLevel, args...)
}
func (entry *Entry) Fatal(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(FatalLevel) {
- entry.log(FatalLevel, fmt.Sprint(args...))
- }
- Exit(1)
+ entry.Log(FatalLevel, args...)
+ entry.Logger.Exit(1)
}
func (entry *Entry) Panic(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(PanicLevel) {
- entry.log(PanicLevel, fmt.Sprint(args...))
- }
+ entry.Log(PanicLevel, args...)
panic(fmt.Sprint(args...))
}
// Entry Printf family functions
-func (entry *Entry) Debugf(format string, args ...interface{}) {
- if entry.Logger.IsLevelEnabled(DebugLevel) {
- entry.Debug(fmt.Sprintf(format, args...))
+func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
+ if entry.Logger.IsLevelEnabled(level) {
+ entry.Log(level, fmt.Sprintf(format, args...))
}
}
+func (entry *Entry) Tracef(format string, args ...interface{}) {
+ entry.Logf(TraceLevel, format, args...)
+}
+
+func (entry *Entry) Debugf(format string, args ...interface{}) {
+ entry.Logf(DebugLevel, format, args...)
+}
+
func (entry *Entry) Infof(format string, args ...interface{}) {
- if entry.Logger.IsLevelEnabled(InfoLevel) {
- entry.Info(fmt.Sprintf(format, args...))
- }
+ entry.Logf(InfoLevel, format, args...)
}
func (entry *Entry) Printf(format string, args ...interface{}) {
@@ -227,9 +333,7 @@
}
func (entry *Entry) Warnf(format string, args ...interface{}) {
- if entry.Logger.IsLevelEnabled(WarnLevel) {
- entry.Warn(fmt.Sprintf(format, args...))
- }
+ entry.Logf(WarnLevel, format, args...)
}
func (entry *Entry) Warningf(format string, args ...interface{}) {
@@ -237,36 +341,36 @@
}
func (entry *Entry) Errorf(format string, args ...interface{}) {
- if entry.Logger.IsLevelEnabled(ErrorLevel) {
- entry.Error(fmt.Sprintf(format, args...))
- }
+ entry.Logf(ErrorLevel, format, args...)
}
func (entry *Entry) Fatalf(format string, args ...interface{}) {
- if entry.Logger.IsLevelEnabled(FatalLevel) {
- entry.Fatal(fmt.Sprintf(format, args...))
- }
- Exit(1)
+ entry.Logf(FatalLevel, format, args...)
+ entry.Logger.Exit(1)
}
func (entry *Entry) Panicf(format string, args ...interface{}) {
- if entry.Logger.IsLevelEnabled(PanicLevel) {
- entry.Panic(fmt.Sprintf(format, args...))
- }
+ entry.Logf(PanicLevel, format, args...)
}
// Entry Println family functions
-func (entry *Entry) Debugln(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(DebugLevel) {
- entry.Debug(entry.sprintlnn(args...))
+func (entry *Entry) Logln(level Level, args ...interface{}) {
+ if entry.Logger.IsLevelEnabled(level) {
+ entry.Log(level, entry.sprintlnn(args...))
}
}
+func (entry *Entry) Traceln(args ...interface{}) {
+ entry.Logln(TraceLevel, args...)
+}
+
+func (entry *Entry) Debugln(args ...interface{}) {
+ entry.Logln(DebugLevel, args...)
+}
+
func (entry *Entry) Infoln(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(InfoLevel) {
- entry.Info(entry.sprintlnn(args...))
- }
+ entry.Logln(InfoLevel, args...)
}
func (entry *Entry) Println(args ...interface{}) {
@@ -274,9 +378,7 @@
}
func (entry *Entry) Warnln(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(WarnLevel) {
- entry.Warn(entry.sprintlnn(args...))
- }
+ entry.Logln(WarnLevel, args...)
}
func (entry *Entry) Warningln(args ...interface{}) {
@@ -284,22 +386,16 @@
}
func (entry *Entry) Errorln(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(ErrorLevel) {
- entry.Error(entry.sprintlnn(args...))
- }
+ entry.Logln(ErrorLevel, args...)
}
func (entry *Entry) Fatalln(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(FatalLevel) {
- entry.Fatal(entry.sprintlnn(args...))
- }
- Exit(1)
+ entry.Logln(FatalLevel, args...)
+ entry.Logger.Exit(1)
}
func (entry *Entry) Panicln(args ...interface{}) {
- if entry.Logger.IsLevelEnabled(PanicLevel) {
- entry.Panic(entry.sprintlnn(args...))
- }
+ entry.Logln(PanicLevel, args...)
}
// Sprintlnn => Sprint no newline. This is to get the behavior of how
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/exported.go new/vendor/github.com/sirupsen/logrus/exported.go
--- old/vendor/github.com/sirupsen/logrus/exported.go 2018-11-15 20:22:56.986337192 +0100
+++ new/vendor/github.com/sirupsen/logrus/exported.go 2019-03-12 13:15:34.130444171 +0100
@@ -1,6 +1,7 @@
package logrus
import (
+ "context"
"io"
"time"
)
@@ -24,6 +25,12 @@
std.SetFormatter(formatter)
}
+// SetReportCaller sets whether the standard logger will include the calling
+// method as a field.
+func SetReportCaller(include bool) {
+ std.SetReportCaller(include)
+}
+
// SetLevel sets the standard logger level.
func SetLevel(level Level) {
std.SetLevel(level)
@@ -49,6 +56,11 @@
return std.WithField(ErrorKey, err)
}
+// WithContext creates an entry from the standard logger and adds a context to it.
+func WithContext(ctx context.Context) *Entry {
+ return std.WithContext(ctx)
+}
+
// WithField creates an entry from the standard logger and adds a field to
// it. If you want multiple fields, use `WithFields`.
//
@@ -77,6 +89,11 @@
return std.WithTime(t)
}
+// Trace logs a message at level Trace on the standard logger.
+func Trace(args ...interface{}) {
+ std.Trace(args...)
+}
+
// Debug logs a message at level Debug on the standard logger.
func Debug(args ...interface{}) {
std.Debug(args...)
@@ -117,6 +134,11 @@
std.Fatal(args...)
}
+// Tracef logs a message at level Trace on the standard logger.
+func Tracef(format string, args ...interface{}) {
+ std.Tracef(format, args...)
+}
+
// Debugf logs a message at level Debug on the standard logger.
func Debugf(format string, args ...interface{}) {
std.Debugf(format, args...)
@@ -157,6 +179,11 @@
std.Fatalf(format, args...)
}
+// Traceln logs a message at level Trace on the standard logger.
+func Traceln(args ...interface{}) {
+ std.Traceln(args...)
+}
+
// Debugln logs a message at level Debug on the standard logger.
func Debugln(args ...interface{}) {
std.Debugln(args...)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/formatter.go new/vendor/github.com/sirupsen/logrus/formatter.go
--- old/vendor/github.com/sirupsen/logrus/formatter.go 2018-11-15 20:22:56.986337192 +0100
+++ new/vendor/github.com/sirupsen/logrus/formatter.go 2019-03-12 13:15:34.130444171 +0100
@@ -9,6 +9,8 @@
FieldKeyLevel = "level"
FieldKeyTime = "time"
FieldKeyLogrusError = "logrus_error"
+ FieldKeyFunc = "func"
+ FieldKeyFile = "file"
)
// The Formatter interface is used to implement a custom Formatter. It takes an
@@ -25,7 +27,7 @@
Format(*Entry) ([]byte, error)
}
-// This is to not silently overwrite `time`, `msg` and `level` fields when
+// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when
// dumping it. If this code wasn't there doing:
//
// logrus.WithField("level", 1).Info("hello")
@@ -37,7 +39,7 @@
//
// It's not exported because it's still using Data in an opinionated way. It's to
// avoid code duplication between the two default formatters.
-func prefixFieldClashes(data Fields, fieldMap FieldMap) {
+func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) {
timeKey := fieldMap.resolve(FieldKeyTime)
if t, ok := data[timeKey]; ok {
data["fields."+timeKey] = t
@@ -61,4 +63,16 @@
data["fields."+logrusErrKey] = l
delete(data, logrusErrKey)
}
+
+ // If reportCaller is not set, 'func' will not conflict.
+ if reportCaller {
+ funcKey := fieldMap.resolve(FieldKeyFunc)
+ if l, ok := data[funcKey]; ok {
+ data["fields."+funcKey] = l
+ }
+ fileKey := fieldMap.resolve(FieldKeyFile)
+ if l, ok := data[fileKey]; ok {
+ data["fields."+fileKey] = l
+ }
+ }
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/json_formatter.go new/vendor/github.com/sirupsen/logrus/json_formatter.go
--- old/vendor/github.com/sirupsen/logrus/json_formatter.go 2018-11-15 20:22:56.990337177 +0100
+++ new/vendor/github.com/sirupsen/logrus/json_formatter.go 2019-03-12 13:15:34.130444171 +0100
@@ -4,6 +4,7 @@
"bytes"
"encoding/json"
"fmt"
+ "runtime"
)
type fieldKey string
@@ -34,20 +35,27 @@
// As an example:
// formatter := &JSONFormatter{
// FieldMap: FieldMap{
- // FieldKeyTime: "@timestamp",
+ // FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
- // FieldKeyMsg: "@message",
+ // FieldKeyMsg: "@message",
+ // FieldKeyFunc: "@caller",
// },
// }
FieldMap FieldMap
+ // CallerPrettyfier can be set by the user to modify the content
+ // of the function and file keys in the json data when ReportCaller is
+ // activated. If any of the returned value is the empty string the
+ // corresponding key will be removed from json fields.
+ CallerPrettyfier func(*runtime.Frame) (function string, file string)
+
// PrettyPrint will indent all json logs
PrettyPrint bool
}
// Format renders a single log entry
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
- data := make(Fields, len(entry.Data)+3)
+ data := make(Fields, len(entry.Data)+4)
for k, v := range entry.Data {
switch v := v.(type) {
case error:
@@ -65,7 +73,7 @@
data = newData
}
- prefixFieldClashes(data, f.FieldMap)
+ prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
timestampFormat := f.TimestampFormat
if timestampFormat == "" {
@@ -80,6 +88,19 @@
}
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
+ if entry.HasCaller() {
+ funcVal := entry.Caller.Function
+ fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+ if f.CallerPrettyfier != nil {
+ funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ }
+ if funcVal != "" {
+ data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
+ }
+ if fileVal != "" {
+ data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
+ }
+ }
var b *bytes.Buffer
if entry.Buffer != nil {
@@ -93,7 +114,7 @@
encoder.SetIndent("", " ")
}
if err := encoder.Encode(data); err != nil {
- return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
+ return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err)
}
return b.Bytes(), nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/logger.go new/vendor/github.com/sirupsen/logrus/logger.go
--- old/vendor/github.com/sirupsen/logrus/logger.go 2018-11-15 20:22:56.990337177 +0100
+++ new/vendor/github.com/sirupsen/logrus/logger.go 2019-03-12 13:15:34.130444171 +0100
@@ -1,6 +1,7 @@
package logrus
import (
+ "context"
"io"
"os"
"sync"
@@ -24,6 +25,10 @@
// own that implements the `Formatter` interface, see the `README` or included
// formatters for examples.
Formatter Formatter
+
+ // Flag for whether to log caller info (off by default)
+ ReportCaller bool
+
// 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.
@@ -32,8 +37,12 @@
mu MutexWrap
// Reusable empty entry
entryPool sync.Pool
+ // Function to exit the application, defaults to `os.Exit()`
+ ExitFunc exitFunc
}
+type exitFunc func(int)
+
type MutexWrap struct {
lock sync.Mutex
disabled bool
@@ -69,10 +78,12 @@
// It's recommended to make this a global instance called `log`.
func New() *Logger {
return &Logger{
- Out: os.Stderr,
- Formatter: new(TextFormatter),
- Hooks: make(LevelHooks),
- Level: InfoLevel,
+ Out: os.Stderr,
+ Formatter: new(TextFormatter),
+ Hooks: make(LevelHooks),
+ Level: InfoLevel,
+ ExitFunc: os.Exit,
+ ReportCaller: false,
}
}
@@ -114,6 +125,13 @@
return entry.WithError(err)
}
+// Add a context to the log entry.
+func (logger *Logger) WithContext(ctx context.Context) *Entry {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ return entry.WithContext(ctx)
+}
+
// Overrides the time of the log entry.
func (logger *Logger) WithTime(t time.Time) *Entry {
entry := logger.newEntry()
@@ -121,20 +139,24 @@
return entry.WithTime(t)
}
-func (logger *Logger) Debugf(format string, args ...interface{}) {
- if logger.IsLevelEnabled(DebugLevel) {
+func (logger *Logger) Logf(level Level, format string, args ...interface{}) {
+ if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
- entry.Debugf(format, args...)
+ entry.Logf(level, format, args...)
logger.releaseEntry(entry)
}
}
+func (logger *Logger) Tracef(format string, args ...interface{}) {
+ logger.Logf(TraceLevel, format, args...)
+}
+
+func (logger *Logger) Debugf(format string, args ...interface{}) {
+ logger.Logf(DebugLevel, format, args...)
+}
+
func (logger *Logger) Infof(format string, args ...interface{}) {
- if logger.IsLevelEnabled(InfoLevel) {
- entry := logger.newEntry()
- entry.Infof(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Logf(InfoLevel, format, args...)
}
func (logger *Logger) Printf(format string, args ...interface{}) {
@@ -144,123 +166,91 @@
}
func (logger *Logger) Warnf(format string, args ...interface{}) {
- if logger.IsLevelEnabled(WarnLevel) {
- entry := logger.newEntry()
- entry.Warnf(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Logf(WarnLevel, format, args...)
}
func (logger *Logger) Warningf(format string, args ...interface{}) {
- if logger.IsLevelEnabled(WarnLevel) {
- entry := logger.newEntry()
- entry.Warnf(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Warnf(format, args...)
}
func (logger *Logger) Errorf(format string, args ...interface{}) {
- if logger.IsLevelEnabled(ErrorLevel) {
- entry := logger.newEntry()
- entry.Errorf(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Logf(ErrorLevel, format, args...)
}
func (logger *Logger) Fatalf(format string, args ...interface{}) {
- if logger.IsLevelEnabled(FatalLevel) {
- entry := logger.newEntry()
- entry.Fatalf(format, args...)
- logger.releaseEntry(entry)
- }
- Exit(1)
+ logger.Logf(FatalLevel, format, args...)
+ logger.Exit(1)
}
func (logger *Logger) Panicf(format string, args ...interface{}) {
- if logger.IsLevelEnabled(PanicLevel) {
+ logger.Logf(PanicLevel, format, args...)
+}
+
+func (logger *Logger) Log(level Level, args ...interface{}) {
+ if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
- entry.Panicf(format, args...)
+ entry.Log(level, args...)
logger.releaseEntry(entry)
}
}
+func (logger *Logger) Trace(args ...interface{}) {
+ logger.Log(TraceLevel, args...)
+}
+
func (logger *Logger) Debug(args ...interface{}) {
- if logger.IsLevelEnabled(DebugLevel) {
- entry := logger.newEntry()
- entry.Debug(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(DebugLevel, args...)
}
func (logger *Logger) Info(args ...interface{}) {
- if logger.IsLevelEnabled(InfoLevel) {
- entry := logger.newEntry()
- entry.Info(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(InfoLevel, args...)
}
func (logger *Logger) Print(args ...interface{}) {
entry := logger.newEntry()
- entry.Info(args...)
+ entry.Print(args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warn(args ...interface{}) {
- if logger.IsLevelEnabled(WarnLevel) {
- entry := logger.newEntry()
- entry.Warn(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(WarnLevel, args...)
}
func (logger *Logger) Warning(args ...interface{}) {
- if logger.IsLevelEnabled(WarnLevel) {
- entry := logger.newEntry()
- entry.Warn(args...)
- logger.releaseEntry(entry)
- }
+ logger.Warn(args...)
}
func (logger *Logger) Error(args ...interface{}) {
- if logger.IsLevelEnabled(ErrorLevel) {
- entry := logger.newEntry()
- entry.Error(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(ErrorLevel, args...)
}
func (logger *Logger) Fatal(args ...interface{}) {
- if logger.IsLevelEnabled(FatalLevel) {
- entry := logger.newEntry()
- entry.Fatal(args...)
- logger.releaseEntry(entry)
- }
- Exit(1)
+ logger.Log(FatalLevel, args...)
+ logger.Exit(1)
}
func (logger *Logger) Panic(args ...interface{}) {
- if logger.IsLevelEnabled(PanicLevel) {
+ logger.Log(PanicLevel, args...)
+}
+
+func (logger *Logger) Logln(level Level, args ...interface{}) {
+ if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
- entry.Panic(args...)
+ entry.Logln(level, args...)
logger.releaseEntry(entry)
}
}
+func (logger *Logger) Traceln(args ...interface{}) {
+ logger.Logln(TraceLevel, args...)
+}
+
func (logger *Logger) Debugln(args ...interface{}) {
- if logger.IsLevelEnabled(DebugLevel) {
- entry := logger.newEntry()
- entry.Debugln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(DebugLevel, args...)
}
func (logger *Logger) Infoln(args ...interface{}) {
- if logger.IsLevelEnabled(InfoLevel) {
- entry := logger.newEntry()
- entry.Infoln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(InfoLevel, args...)
}
func (logger *Logger) Println(args ...interface{}) {
@@ -270,44 +260,32 @@
}
func (logger *Logger) Warnln(args ...interface{}) {
- if logger.IsLevelEnabled(WarnLevel) {
- entry := logger.newEntry()
- entry.Warnln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(WarnLevel, args...)
}
func (logger *Logger) Warningln(args ...interface{}) {
- if logger.IsLevelEnabled(WarnLevel) {
- entry := logger.newEntry()
- entry.Warnln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Warnln(args...)
}
func (logger *Logger) Errorln(args ...interface{}) {
- if logger.IsLevelEnabled(ErrorLevel) {
- entry := logger.newEntry()
- entry.Errorln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(ErrorLevel, args...)
}
func (logger *Logger) Fatalln(args ...interface{}) {
- if logger.IsLevelEnabled(FatalLevel) {
- entry := logger.newEntry()
- entry.Fatalln(args...)
- logger.releaseEntry(entry)
- }
- Exit(1)
+ logger.Logln(FatalLevel, args...)
+ logger.Exit(1)
}
func (logger *Logger) Panicln(args ...interface{}) {
- if logger.IsLevelEnabled(PanicLevel) {
- entry := logger.newEntry()
- entry.Panicln(args...)
- logger.releaseEntry(entry)
+ logger.Logln(PanicLevel, args...)
+}
+
+func (logger *Logger) Exit(code int) {
+ runHandlers()
+ if logger.ExitFunc == nil {
+ logger.ExitFunc = os.Exit
}
+ logger.ExitFunc(code)
}
//When file is opened with appending mode, it's safe to
@@ -357,6 +335,12 @@
logger.Out = output
}
+func (logger *Logger) SetReportCaller(reportCaller bool) {
+ logger.mu.Lock()
+ defer logger.mu.Unlock()
+ logger.ReportCaller = reportCaller
+}
+
// ReplaceHooks replaces the logger hooks and returns the old ones
func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
logger.mu.Lock()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/logrus.go new/vendor/github.com/sirupsen/logrus/logrus.go
--- old/vendor/github.com/sirupsen/logrus/logrus.go 2018-11-15 20:22:56.990337177 +0100
+++ new/vendor/github.com/sirupsen/logrus/logrus.go 2019-03-12 13:15:34.130444171 +0100
@@ -14,22 +14,11 @@
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
func (level Level) String() string {
- switch level {
- case DebugLevel:
- return "debug"
- case InfoLevel:
- return "info"
- case WarnLevel:
- return "warning"
- case ErrorLevel:
- return "error"
- case FatalLevel:
- return "fatal"
- case PanicLevel:
- return "panic"
+ if b, err := level.MarshalText(); err == nil {
+ return string(b)
+ } else {
+ return "unknown"
}
-
- return "unknown"
}
// ParseLevel takes a string level and returns the Logrus log level constant.
@@ -47,12 +36,47 @@
return InfoLevel, nil
case "debug":
return DebugLevel, nil
+ case "trace":
+ return TraceLevel, nil
}
var l Level
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
}
+// UnmarshalText implements encoding.TextUnmarshaler.
+func (level *Level) UnmarshalText(text []byte) error {
+ l, err := ParseLevel(string(text))
+ if err != nil {
+ return err
+ }
+
+ *level = Level(l)
+
+ return nil
+}
+
+func (level Level) MarshalText() ([]byte, error) {
+ switch level {
+ case TraceLevel:
+ return []byte("trace"), nil
+ case DebugLevel:
+ return []byte("debug"), nil
+ case InfoLevel:
+ return []byte("info"), nil
+ case WarnLevel:
+ return []byte("warning"), nil
+ case ErrorLevel:
+ return []byte("error"), nil
+ case FatalLevel:
+ return []byte("fatal"), nil
+ case PanicLevel:
+ return []byte("panic"), nil
+ }
+
+ return nil, fmt.Errorf("not a valid logrus level %d", level)
+}
+
// A constant exposing all logging levels
var AllLevels = []Level{
PanicLevel,
@@ -61,6 +85,7 @@
WarnLevel,
InfoLevel,
DebugLevel,
+ TraceLevel,
}
// These are the different logging levels. You can set the logging level to log
@@ -69,7 +94,7 @@
// PanicLevel level, highest level of severity. Logs and then calls panic with the
// message passed to Debug, Info, ...
PanicLevel Level = iota
- // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
+ // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the
// logging level is set to Panic.
FatalLevel
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
@@ -82,6 +107,8 @@
InfoLevel
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
DebugLevel
+ // TraceLevel level. Designates finer-grained informational events than the Debug.
+ TraceLevel
)
// Won't compile if StdLogger can't be realized by a log.Logger
@@ -148,3 +175,12 @@
// IsFatalEnabled() bool
// IsPanicEnabled() bool
}
+
+// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is
+// here for consistancy. Do not use. Use Logger or Entry instead.
+type Ext1FieldLogger interface {
+ FieldLogger
+ Tracef(format string, args ...interface{})
+ Trace(args ...interface{})
+ Traceln(args ...interface{})
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go new/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
--- old/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go 2018-11-15 20:22:56.990337177 +0100
+++ new/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go 2019-03-12 13:15:34.130444171 +0100
@@ -1,4 +1,4 @@
-// +build !appengine,!js,!windows
+// +build !appengine,!js,!windows,!aix
package logrus
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/text_formatter.go new/vendor/github.com/sirupsen/logrus/text_formatter.go
--- old/vendor/github.com/sirupsen/logrus/text_formatter.go 2018-11-15 20:22:56.990337177 +0100
+++ new/vendor/github.com/sirupsen/logrus/text_formatter.go 2019-03-12 13:15:34.130444171 +0100
@@ -4,6 +4,7 @@
"bytes"
"fmt"
"os"
+ "runtime"
"sort"
"strings"
"sync"
@@ -11,18 +12,13 @@
)
const (
- nocolor = 0
- red = 31
- green = 32
- yellow = 33
- blue = 36
- gray = 37
+ red = 31
+ yellow = 33
+ blue = 36
+ gray = 37
)
-var (
- baseTimestamp time.Time
- emptyFieldMap FieldMap
-)
+var baseTimestamp time.Time
func init() {
baseTimestamp = time.Now()
@@ -76,6 +72,12 @@
// FieldKeyMsg: "@message"}}
FieldMap FieldMap
+ // CallerPrettyfier can be set by the user to modify the content
+ // of the function and file keys in the json data when ReportCaller is
+ // activated. If any of the returned value is the empty string the
+ // corresponding key will be removed from json fields.
+ CallerPrettyfier func(*runtime.Frame) (function string, file string)
+
terminalInitOnce sync.Once
}
@@ -90,7 +92,7 @@
}
func (f *TextFormatter) isColored() bool {
- isColored := f.ForceColors || f.isTerminal
+ isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows"))
if f.EnvironmentOverrideColors {
if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok && force != "0" {
@@ -107,14 +109,19 @@
// Format renders a single log entry
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
- prefixFieldClashes(entry.Data, f.FieldMap)
-
- keys := make([]string, 0, len(entry.Data))
- for k := range entry.Data {
+ data := make(Fields)
+ for k, v := range entry.Data {
+ data[k] = v
+ }
+ prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
+ keys := make([]string, 0, len(data))
+ for k := range data {
keys = append(keys, k)
}
- fixedKeys := make([]string, 0, 4+len(entry.Data))
+ var funcVal, fileVal string
+
+ fixedKeys := make([]string, 0, 4+len(data))
if !f.DisableTimestamp {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
}
@@ -125,6 +132,16 @@
if entry.err != "" {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError))
}
+ if entry.HasCaller() {
+ fixedKeys = append(fixedKeys,
+ f.FieldMap.resolve(FieldKeyFunc), f.FieldMap.resolve(FieldKeyFile))
+ if f.CallerPrettyfier != nil {
+ funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ } else {
+ funcVal = entry.Caller.Function
+ fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+ }
+ }
if !f.DisableSorting {
if f.SortingFunc == nil {
@@ -156,21 +173,26 @@
timestampFormat = defaultTimestampFormat
}
if f.isColored() {
- f.printColored(b, entry, keys, timestampFormat)
+ f.printColored(b, entry, keys, data, timestampFormat)
} else {
+
for _, key := range fixedKeys {
var value interface{}
- switch key {
- case f.FieldMap.resolve(FieldKeyTime):
+ switch {
+ case key == f.FieldMap.resolve(FieldKeyTime):
value = entry.Time.Format(timestampFormat)
- case f.FieldMap.resolve(FieldKeyLevel):
+ case key == f.FieldMap.resolve(FieldKeyLevel):
value = entry.Level.String()
- case f.FieldMap.resolve(FieldKeyMsg):
+ case key == f.FieldMap.resolve(FieldKeyMsg):
value = entry.Message
- case f.FieldMap.resolve(FieldKeyLogrusError):
+ case key == f.FieldMap.resolve(FieldKeyLogrusError):
value = entry.err
+ case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller():
+ value = funcVal
+ case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller():
+ value = fileVal
default:
- value = entry.Data[key]
+ value = data[key]
}
f.appendKeyValue(b, key, value)
}
@@ -180,10 +202,10 @@
return b.Bytes(), nil
}
-func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
+func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) {
var levelColor int
switch entry.Level {
- case DebugLevel:
+ case DebugLevel, TraceLevel:
levelColor = gray
case WarnLevel:
levelColor = yellow
@@ -202,15 +224,27 @@
// the behavior of logrus text_formatter the same as the stdlib log package
entry.Message = strings.TrimSuffix(entry.Message, "\n")
+ caller := ""
+
+ if entry.HasCaller() {
+ funcVal := fmt.Sprintf("%s()", entry.Caller.Function)
+ fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+
+ if f.CallerPrettyfier != nil {
+ funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ }
+ caller = fileVal + " " + funcVal
+ }
+
if f.DisableTimestamp {
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, 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)
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message)
} else {
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message)
}
for _, k := range keys {
- v := entry.Data[k]
+ v := data[k]
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
f.appendValue(b, v)
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/sirupsen/logrus/writer.go new/vendor/github.com/sirupsen/logrus/writer.go
--- old/vendor/github.com/sirupsen/logrus/writer.go 2018-11-15 20:22:56.990337177 +0100
+++ new/vendor/github.com/sirupsen/logrus/writer.go 2019-03-12 13:15:34.130444171 +0100
@@ -24,6 +24,8 @@
var printFunc func(args ...interface{})
switch level {
+ case TraceLevel:
+ printFunc = entry.Trace
case DebugLevel:
printFunc = entry.Debug
case InfoLevel: