diff --git a/go.mod b/go.mod index b800919f..6fe5ec78 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/hashicorp/go-hclog v0.14.1 // indirect + github.com/hashicorp/go-hclog v0.16.2 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 305c3ac9..a6bf31c2 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= +github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= diff --git a/vendor/github.com/hashicorp/go-hclog/interceptlogger.go b/vendor/github.com/hashicorp/go-hclog/interceptlogger.go index 08a6677e..631baf2f 100644 --- a/vendor/github.com/hashicorp/go-hclog/interceptlogger.go +++ b/vendor/github.com/hashicorp/go-hclog/interceptlogger.go @@ -18,8 +18,13 @@ type interceptLogger struct { } func NewInterceptLogger(opts *LoggerOptions) InterceptLogger { + l := newLogger(opts) + if l.callerOffset > 0 { + // extra frames for interceptLogger.{Warn,Info,Log,etc...}, and interceptLogger.log + l.callerOffset += 2 + } intercept := &interceptLogger{ - Logger: New(opts), + Logger: l, mu: new(sync.Mutex), sinkCount: new(int32), Sinks: make(map[SinkAdapter]struct{}), @@ -31,6 +36,14 @@ func NewInterceptLogger(opts *LoggerOptions) InterceptLogger { } func (i *interceptLogger) Log(level Level, msg string, args ...interface{}) { + i.log(level, msg, args...) +} + +// log is used to make the caller stack frame lookup consistent. If Warn,Info,etc +// all called Log then direct calls to Log would have a different stack frame +// depth. By having all the methods call the same helper we ensure the stack +// frame depth is the same. +func (i *interceptLogger) log(level Level, msg string, args ...interface{}) { i.Logger.Log(level, msg, args...) if atomic.LoadInt32(i.sinkCount) == 0 { return @@ -45,72 +58,27 @@ func (i *interceptLogger) Log(level Level, msg string, args ...interface{}) { // Emit the message and args at TRACE level to log and sinks func (i *interceptLogger) Trace(msg string, args ...interface{}) { - i.Logger.Trace(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Trace, msg, i.retrieveImplied(args...)...) - } + i.log(Trace, msg, args...) } // Emit the message and args at DEBUG level to log and sinks func (i *interceptLogger) Debug(msg string, args ...interface{}) { - i.Logger.Debug(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Debug, msg, i.retrieveImplied(args...)...) - } + i.log(Debug, msg, args...) } // Emit the message and args at INFO level to log and sinks func (i *interceptLogger) Info(msg string, args ...interface{}) { - i.Logger.Info(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Info, msg, i.retrieveImplied(args...)...) - } + i.log(Info, msg, args...) } // Emit the message and args at WARN level to log and sinks func (i *interceptLogger) Warn(msg string, args ...interface{}) { - i.Logger.Warn(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Warn, msg, i.retrieveImplied(args...)...) - } + i.log(Warn, msg, args...) } // Emit the message and args at ERROR level to log and sinks func (i *interceptLogger) Error(msg string, args ...interface{}) { - i.Logger.Error(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Error, msg, i.retrieveImplied(args...)...) - } + i.log(Error, msg, args...) } func (i *interceptLogger) retrieveImplied(args ...interface{}) []interface{} { @@ -123,17 +91,11 @@ func (i *interceptLogger) retrieveImplied(args ...interface{}) []interface{} { return cp } -// Create a new sub-Logger that a name decending from the current name. +// Create a new sub-Logger that a name descending from the current name. // This is used to create a subsystem specific Logger. // Registered sinks will subscribe to these messages as well. func (i *interceptLogger) Named(name string) Logger { - var sub interceptLogger - - sub = *i - - sub.Logger = i.Logger.Named(name) - - return &sub + return i.NamedIntercept(name) } // Create a new sub-Logger with an explicit name. This ignores the current @@ -141,13 +103,7 @@ func (i *interceptLogger) Named(name string) Logger { // within the normal hierarchy. Registered sinks will subscribe // to these messages as well. func (i *interceptLogger) ResetNamed(name string) Logger { - var sub interceptLogger - - sub = *i - - sub.Logger = i.Logger.ResetNamed(name) - - return &sub + return i.ResetNamedIntercept(name) } // Create a new sub-Logger that a name decending from the current name. @@ -157,9 +113,7 @@ func (i *interceptLogger) NamedIntercept(name string) InterceptLogger { var sub interceptLogger sub = *i - sub.Logger = i.Logger.Named(name) - return &sub } @@ -171,9 +125,7 @@ func (i *interceptLogger) ResetNamedIntercept(name string) InterceptLogger { var sub interceptLogger sub = *i - sub.Logger = i.Logger.ResetNamed(name) - return &sub } @@ -210,18 +162,23 @@ func (i *interceptLogger) DeregisterSink(sink SinkAdapter) { atomic.AddInt32(i.sinkCount, -1) } -// Create a *log.Logger that will send it's data through this Logger. This -// allows packages that expect to be using the standard library to log to -// actually use this logger, which will also send to any registered sinks. func (i *interceptLogger) StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger { + return i.StandardLogger(opts) +} + +func (i *interceptLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { if opts == nil { opts = &StandardLoggerOptions{} } - return log.New(i.StandardWriterIntercept(opts), "", 0) + return log.New(i.StandardWriter(opts), "", 0) } func (i *interceptLogger) StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer { + return i.StandardWriter(opts) +} + +func (i *interceptLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer { return &stdlogAdapter{ log: i, inferLevels: opts.InferLevels, diff --git a/vendor/github.com/hashicorp/go-hclog/intlogger.go b/vendor/github.com/hashicorp/go-hclog/intlogger.go index 7158125d..d491ae8f 100644 --- a/vendor/github.com/hashicorp/go-hclog/intlogger.go +++ b/vendor/github.com/hashicorp/go-hclog/intlogger.go @@ -10,7 +10,6 @@ import ( "log" "os" "reflect" - "regexp" "runtime" "sort" "strconv" @@ -22,10 +21,14 @@ import ( "github.com/fatih/color" ) -// TimeFormat to use for logging. This is a version of RFC3339 that contains -// contains millisecond precision +// TimeFormat is the time format to use for plain (non-JSON) output. +// This is a version of RFC3339 that contains millisecond precision. const TimeFormat = "2006-01-02T15:04:05.000Z0700" +// TimeFormatJSON is the time format to use for JSON output. +// This is a version of RFC3339 that contains microsecond precision. +const TimeFormatJSON = "2006-01-02T15:04:05.000000Z07:00" + // errJsonUnsupportedTypeMsg is included in log json entries, if an arg cannot be serialized to json const errJsonUnsupportedTypeMsg = "logging contained values that don't serialize to json" @@ -53,10 +56,11 @@ var _ Logger = &intLogger{} // intLogger is an internal logger implementation. Internal in that it is // defined entirely by this package. type intLogger struct { - json bool - caller bool - name string - timeFormat string + json bool + callerOffset int + name string + timeFormat string + disableTime bool // This is an interface so that it's shared by any derived loggers, since // those derived loggers share the bufio.Writer as well. @@ -67,6 +71,9 @@ type intLogger struct { implied []interface{} exclude func(level Level, msg string, args ...interface{}) bool + + // create subloggers with their own level setting + independentLevels bool } // New returns a configured logger. @@ -77,7 +84,12 @@ func New(opts *LoggerOptions) Logger { // NewSinkAdapter returns a SinkAdapter with configured settings // defined by LoggerOptions func NewSinkAdapter(opts *LoggerOptions) SinkAdapter { - return newLogger(opts) + l := newLogger(opts) + if l.callerOffset > 0 { + // extra frames for interceptLogger.{Warn,Info,Log,etc...}, and SinkAdapter.Accept + l.callerOffset += 2 + } + return l } func newLogger(opts *LoggerOptions) *intLogger { @@ -101,29 +113,38 @@ func newLogger(opts *LoggerOptions) *intLogger { } l := &intLogger{ - json: opts.JSONFormat, - caller: opts.IncludeLocation, - name: opts.Name, - timeFormat: TimeFormat, - mutex: mutex, - writer: newWriter(output, opts.Color), - level: new(int32), - exclude: opts.Exclude, + json: opts.JSONFormat, + name: opts.Name, + timeFormat: TimeFormat, + disableTime: opts.DisableTime, + mutex: mutex, + writer: newWriter(output, opts.Color), + level: new(int32), + exclude: opts.Exclude, + independentLevels: opts.IndependentLevels, + } + if opts.IncludeLocation { + l.callerOffset = offsetIntLogger + opts.AdditionalLocationOffset } - l.setColorization(opts) - - if opts.DisableTime { - l.timeFormat = "" - } else if opts.TimeFormat != "" { + if l.json { + l.timeFormat = TimeFormatJSON + } + if opts.TimeFormat != "" { l.timeFormat = opts.TimeFormat } + l.setColorization(opts) + atomic.StoreInt32(l.level, int32(level)) return l } +// offsetIntLogger is the stack frame offset in the call stack for the caller to +// one of the Warn,Info,Log,etc methods. +const offsetIntLogger = 3 + // Log a message and a set of key/value pairs if the given level is at // or more severe that the threshold configured in the Logger. func (l *intLogger) log(name string, level Level, msg string, args ...interface{}) { @@ -178,11 +199,10 @@ func trimCallerPath(path string) string { return path[idx+1:] } -var logImplFile = regexp.MustCompile(`.+intlogger.go|.+interceptlogger.go$`) - // Non-JSON logging format function func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, args ...interface{}) { - if len(l.timeFormat) > 0 { + + if !l.disableTime { l.writer.WriteString(t.Format(l.timeFormat)) l.writer.WriteByte(' ') } @@ -194,18 +214,8 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, l.writer.WriteString("[?????]") } - offset := 3 - if l.caller { - // Check if the caller is inside our package and inside - // a logger implementation file - if _, file, _, ok := runtime.Caller(3); ok { - match := logImplFile.MatchString(file) - if match { - offset = 4 - } - } - - if _, file, line, ok := runtime.Caller(offset); ok { + if l.callerOffset > 0 { + if _, file, line, ok := runtime.Caller(l.callerOffset); ok { l.writer.WriteByte(' ') l.writer.WriteString(trimCallerPath(file)) l.writer.WriteByte(':') @@ -251,6 +261,9 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, switch st := args[i+1].(type) { case string: val = st + if st == "" { + val = `""` + } case int: val = strconv.FormatInt(int64(st), 10) case int64: @@ -282,6 +295,9 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, continue FOR case Format: val = fmt.Sprintf(st[0].(string), st[1:]...) + case Quote: + raw = true + val = strconv.Quote(string(st)) default: v := reflect.ValueOf(st) if v.Kind() == reflect.Slice { @@ -292,20 +308,32 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, } } - l.writer.WriteByte(' ') + var key string + switch st := args[i].(type) { case string: - l.writer.WriteString(st) + key = st default: - l.writer.WriteString(fmt.Sprintf("%s", st)) + key = fmt.Sprintf("%s", st) } - l.writer.WriteByte('=') - if !raw && strings.ContainsAny(val, " \t\n\r") { + if strings.Contains(val, "\n") { + l.writer.WriteString("\n ") + l.writer.WriteString(key) + l.writer.WriteString("=\n") + writeIndent(l.writer, val, " | ") + l.writer.WriteString(" ") + } else if !raw && strings.ContainsAny(val, " \t") { + l.writer.WriteByte(' ') + l.writer.WriteString(key) + l.writer.WriteByte('=') l.writer.WriteByte('"') l.writer.WriteString(val) l.writer.WriteByte('"') } else { + l.writer.WriteByte(' ') + l.writer.WriteString(key) + l.writer.WriteByte('=') l.writer.WriteString(val) } } @@ -315,6 +343,26 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, if stacktrace != "" { l.writer.WriteString(string(stacktrace)) + l.writer.WriteString("\n") + } +} + +func writeIndent(w *writer, str string, indent string) { + for { + nl := strings.IndexByte(str, "\n"[0]) + if nl == -1 { + if str != "" { + w.WriteString(indent) + w.WriteString(str) + w.WriteString("\n") + } + return + } + + w.WriteString(indent) + w.WriteString(str[:nl]) + w.WriteString("\n") + str = str[nl+1:] } } @@ -334,22 +382,19 @@ func (l *intLogger) renderSlice(v reflect.Value) string { switch sv.Kind() { case reflect.String: - val = sv.String() + val = strconv.Quote(sv.String()) case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: val = strconv.FormatInt(sv.Int(), 10) case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: val = strconv.FormatUint(sv.Uint(), 10) default: val = fmt.Sprintf("%v", sv.Interface()) + if strings.ContainsAny(val, " \t\n\r") { + val = strconv.Quote(val) + } } - if strings.ContainsAny(val, " \t\n\r") { - buf.WriteByte('"') - buf.WriteString(val) - buf.WriteByte('"') - } else { - buf.WriteString(val) - } + buf.WriteString(val) } buf.WriteRune(']') @@ -415,8 +460,10 @@ func (l *intLogger) logJSON(t time.Time, name string, level Level, msg string, a func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg string) map[string]interface{} { vals := map[string]interface{}{ - "@message": msg, - "@timestamp": t.Format("2006-01-02T15:04:05.000000Z07:00"), + "@message": msg, + } + if !l.disableTime { + vals["@timestamp"] = t.Format(l.timeFormat) } var levelStr string @@ -441,8 +488,8 @@ func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg strin vals["@module"] = name } - if l.caller { - if _, file, line, ok := runtime.Caller(4); ok { + if l.callerOffset > 0 { + if _, file, line, ok := runtime.Caller(l.callerOffset + 1); ok { vals["@caller"] = fmt.Sprintf("%s:%d", file, line) } } @@ -517,7 +564,7 @@ func (l *intLogger) With(args ...interface{}) Logger { args = args[:len(args)-1] } - sl := *l + sl := l.copy() result := make(map[string]interface{}, len(l.implied)+len(args)) keys := make([]string, 0, len(l.implied)+len(args)) @@ -551,13 +598,13 @@ func (l *intLogger) With(args ...interface{}) Logger { sl.implied = append(sl.implied, MissingKey, extra) } - return &sl + return sl } // Create a new sub-Logger that a name decending from the current name. // This is used to create a subsystem specific Logger. func (l *intLogger) Named(name string) Logger { - sl := *l + sl := l.copy() if sl.name != "" { sl.name = sl.name + "." + name @@ -565,18 +612,18 @@ func (l *intLogger) Named(name string) Logger { sl.name = name } - return &sl + return sl } // Create a new sub-Logger with an explicit name. This ignores the current // name. This is used to create a standalone logger that doesn't fall // within the normal hierarchy. func (l *intLogger) ResetNamed(name string) Logger { - sl := *l + sl := l.copy() sl.name = name - return &sl + return sl } func (l *intLogger) ResetOutput(opts *LoggerOptions) error { @@ -632,8 +679,15 @@ func (l *intLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { } func (l *intLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer { + newLog := *l + if l.callerOffset > 0 { + // the stack is + // logger.printf() -> l.Output() ->l.out.writer(hclog:stdlogAdaptor.write) -> hclog:stdlogAdaptor.dispatch() + // So plus 4. + newLog.callerOffset = l.callerOffset + 4 + } return &stdlogAdapter{ - log: l, + log: &newLog, inferLevels: opts.InferLevels, forceLevel: opts.ForceLevel, } @@ -663,3 +717,16 @@ func (i *intLogger) ImpliedArgs() []interface{} { func (i *intLogger) Name() string { return i.name } + +// copy returns a shallow copy of the intLogger, replacing the level pointer +// when necessary +func (l *intLogger) copy() *intLogger { + sl := *l + + if l.independentLevels { + sl.level = new(int32) + *sl.level = *l.level + } + + return &sl +} diff --git a/vendor/github.com/hashicorp/go-hclog/logger.go b/vendor/github.com/hashicorp/go-hclog/logger.go index 8d5eed76..6a4665ba 100644 --- a/vendor/github.com/hashicorp/go-hclog/logger.go +++ b/vendor/github.com/hashicorp/go-hclog/logger.go @@ -38,6 +38,9 @@ const ( // Error information about unrecoverable events. Error Level = 5 + + // Off disables all logging output. + Off Level = 6 ) // Format is a simple convience type for when formatting is required. When @@ -64,6 +67,12 @@ type Octal int // text output. For example: L.Info("bits", Binary(17)) type Binary int +// A simple shortcut to format strings with Go quoting. Control and +// non-printable characters will be escaped with their backslash equivalents in +// output. Intended for untrusted or multiline strings which should be logged +// as concisely as possible. +type Quote string + // ColorOption expresses how the output should be colored, if at all. type ColorOption uint8 @@ -96,6 +105,8 @@ func LevelFromString(levelStr string) Level { return Warn case "error": return Error + case "off": + return Off default: return NoLevel } @@ -115,6 +126,8 @@ func (l Level) String() string { return "error" case NoLevel: return "none" + case Off: + return "off" default: return "unknown" } @@ -179,7 +192,8 @@ type Logger interface { // the current name as well. ResetNamed(name string) Logger - // Updates the level. This should affect all sub-loggers as well. If an + // Updates the level. This should affect all related loggers as well, + // unless they were created with IndependentLevels. If an // implementation cannot update the level on the fly, it should no-op. SetLevel(level Level) @@ -227,6 +241,10 @@ type LoggerOptions struct { // Include file and line information in each log line IncludeLocation bool + // AdditionalLocationOffset is the number of additional stack levels to skip + // when finding the file and line information for the log line + AdditionalLocationOffset int + // The time format to use instead of the default TimeFormat string @@ -243,6 +261,12 @@ type LoggerOptions struct { // This is useful when interacting with a system that you wish to suppress the log // message for (because it's too noisy, etc) Exclude func(level Level, msg string, args ...interface{}) bool + + // IndependentLevels causes subloggers to be created with an independent + // copy of this logger's level. This means that using SetLevel on this + // logger will not effect any subloggers, and SetLevel on any subloggers + // will not effect the parent or sibling loggers. + IndependentLevels bool } // InterceptLogger describes the interface for using a logger @@ -271,10 +295,10 @@ type InterceptLogger interface { // the current name as well. ResetNamedIntercept(name string) InterceptLogger - // Return a value that conforms to the stdlib log.Logger interface + // Deprecated: use StandardLogger StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger - // Return a value that conforms to io.Writer, which can be passed into log.SetOutput() + // Deprecated: use StandardWriter StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer } diff --git a/vendor/github.com/hashicorp/go-hclog/stdlog.go b/vendor/github.com/hashicorp/go-hclog/stdlog.go index f35d875d..271d546d 100644 --- a/vendor/github.com/hashicorp/go-hclog/stdlog.go +++ b/vendor/github.com/hashicorp/go-hclog/stdlog.go @@ -64,7 +64,7 @@ func (s *stdlogAdapter) pickLevel(str string) (Level, string) { case strings.HasPrefix(str, "[INFO]"): return Info, strings.TrimSpace(str[6:]) case strings.HasPrefix(str, "[WARN]"): - return Warn, strings.TrimSpace(str[7:]) + return Warn, strings.TrimSpace(str[6:]) case strings.HasPrefix(str, "[ERROR]"): return Error, strings.TrimSpace(str[7:]) case strings.HasPrefix(str, "[ERR]"): diff --git a/vendor/modules.txt b/vendor/modules.txt index 5a473528..9278cb07 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -77,7 +77,7 @@ github.com/google/gofuzz/bytesource # github.com/google/uuid v1.6.0 ## explicit github.com/google/uuid -# github.com/hashicorp/go-hclog v0.14.1 +# github.com/hashicorp/go-hclog v0.16.2 ## explicit; go 1.13 github.com/hashicorp/go-hclog # github.com/hashicorp/go-plugin v1.6.0