rebase: update vault/api to v1.1.1

Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
Niels de Vos
2021-09-28 17:05:57 +02:00
committed by mergify[bot]
parent b85076365c
commit bb68cc9bee
32 changed files with 1399 additions and 350 deletions

View File

@ -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,

View File

@ -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
}
if l.json {
l.timeFormat = TimeFormatJSON
}
if opts.TimeFormat != "" {
l.timeFormat = opts.TimeFormat
}
l.setColorization(opts)
if opts.DisableTime {
l.timeFormat = ""
} else if opts.TimeFormat != "" {
l.timeFormat = opts.TimeFormat
}
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:
@ -292,20 +305,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 +340,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 +379,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 +457,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 +485,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 +561,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 +595,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 +609,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 +676,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 +714,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
}

View File

@ -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
@ -96,6 +99,8 @@ func LevelFromString(levelStr string) Level {
return Warn
case "error":
return Error
case "off":
return Off
default:
return NoLevel
}
@ -115,6 +120,8 @@ func (l Level) String() string {
return "error"
case NoLevel:
return "none"
case Off:
return "off"
default:
return "unknown"
}
@ -179,7 +186,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 +235,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 +255,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 +289,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
}