vendor: update github.com/hashicorp/go-hclog

This commit is contained in:
Nick Ethier 2018-07-26 22:26:04 -04:00
parent 8abf4f9e25
commit bba732b2c3
No known key found for this signature in database
GPG Key ID: 07C1A3ECED90D24A
5 changed files with 177 additions and 25 deletions

View File

@ -10,8 +10,7 @@ interface for use in development and production environments.
It provides logging levels that provide decreased output based upon the
desired amount of output, unlike the standard library `log` package.
It does not provide `Printf` style logging, only key/value logging that is
exposed as arguments to the logging functions for simplicity.
It provides `Printf` style logging of values via `hclog.Fmt()`.
It provides a human readable output mode for use in development as well as
JSON output mode for production.
@ -100,6 +99,17 @@ requestLogger.Info("we are transporting a request")
This allows sub Loggers to be context specific without having to thread that
into all the callers.
### Using `hclog.Fmt()`
```go
var int totalBandwidth = 200
appLogger.Info("total bandwidth exceeded", "bandwidth", hclog.Fmt("%d GB/s", totalBandwidth))
```
```text
... [INFO ] my-app: total bandwidth exceeded: bandwidth="200 GB/s"
```
### Use this with code that uses the standard library logger
If you want to use the standard library's `log.Logger` interface you can wrap

View File

@ -2,14 +2,17 @@ package hclog
import (
"bufio"
"encoding"
"encoding/json"
"fmt"
"log"
"os"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
@ -39,28 +42,40 @@ func New(opts *LoggerOptions) Logger {
level = DefaultLevel
}
return &intLogger{
m: new(sync.Mutex),
json: opts.JSONFormat,
caller: opts.IncludeLocation,
name: opts.Name,
w: bufio.NewWriter(output),
level: level,
mtx := opts.Mutex
if mtx == nil {
mtx = new(sync.Mutex)
}
ret := &intLogger{
m: mtx,
json: opts.JSONFormat,
caller: opts.IncludeLocation,
name: opts.Name,
timeFormat: TimeFormat,
w: bufio.NewWriter(output),
level: new(int32),
}
if opts.TimeFormat != "" {
ret.timeFormat = opts.TimeFormat
}
atomic.StoreInt32(ret.level, int32(level))
return ret
}
// The internal logger implementation. Internal in that it is defined entirely
// by this package.
type intLogger struct {
json bool
caller bool
name string
json bool
caller bool
name string
timeFormat string
// this is a pointer so that it's shared by any derived loggers, since
// those derived loggers share the bufio.Writer as well.
m *sync.Mutex
w *bufio.Writer
level Level
level *int32
implied []interface{}
}
@ -75,7 +90,7 @@ const TimeFormat = "2006-01-02T15:04:05.000Z0700"
// 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 (z *intLogger) Log(level Level, msg string, args ...interface{}) {
if level < z.level {
if level < Level(atomic.LoadInt32(z.level)) {
return
}
@ -126,7 +141,7 @@ func trimCallerPath(path string) string {
// Non-JSON logging format function
func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{}) {
z.w.WriteString(t.Format(TimeFormat))
z.w.WriteString(t.Format(z.timeFormat))
z.w.WriteByte(' ')
s, ok := _levelToBracket[level]
@ -202,6 +217,8 @@ func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{
case CapturedStacktrace:
stacktrace = st
continue FOR
case Format:
val = fmt.Sprintf(st[0].(string), st[1:]...)
default:
val = fmt.Sprintf("%v", st)
}
@ -262,6 +279,8 @@ func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interf
}
}
args = append(z.implied, args...)
if args != nil && len(args) > 0 {
if len(args)%2 != 0 {
cs, ok := args[len(args)-1].(CapturedStacktrace)
@ -279,7 +298,22 @@ func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interf
// without injecting into logs...
continue
}
vals[args[i].(string)] = args[i+1]
val := args[i+1]
switch sv := val.(type) {
case error:
// Check if val is of type error. If error type doesn't
// implement json.Marshaler or encoding.TextMarshaler
// then set val to err.Error() so that it gets marshaled
switch sv.(type) {
case json.Marshaler, encoding.TextMarshaler:
default:
val = sv.Error()
}
case Format:
val = fmt.Sprintf(sv[0].(string), sv[1:]...)
}
vals[args[i].(string)] = val
}
}
@ -316,36 +350,66 @@ func (z *intLogger) Error(msg string, args ...interface{}) {
// Indicate that the logger would emit TRACE level logs
func (z *intLogger) IsTrace() bool {
return z.level == Trace
return Level(atomic.LoadInt32(z.level)) == Trace
}
// Indicate that the logger would emit DEBUG level logs
func (z *intLogger) IsDebug() bool {
return z.level <= Debug
return Level(atomic.LoadInt32(z.level)) <= Debug
}
// Indicate that the logger would emit INFO level logs
func (z *intLogger) IsInfo() bool {
return z.level <= Info
return Level(atomic.LoadInt32(z.level)) <= Info
}
// Indicate that the logger would emit WARN level logs
func (z *intLogger) IsWarn() bool {
return z.level <= Warn
return Level(atomic.LoadInt32(z.level)) <= Warn
}
// Indicate that the logger would emit ERROR level logs
func (z *intLogger) IsError() bool {
return z.level <= Error
return Level(atomic.LoadInt32(z.level)) <= Error
}
// Return a sub-Logger for which every emitted log message will contain
// the given key/value pairs. This is used to create a context specific
// Logger.
func (z *intLogger) With(args ...interface{}) Logger {
if len(args)%2 != 0 {
panic("With() call requires paired arguments")
}
var nz intLogger = *z
nz.implied = append(nz.implied, args...)
result := make(map[string]interface{}, len(z.implied)+len(args))
keys := make([]string, 0, len(z.implied)+len(args))
// Read existing args, store map and key for consistent sorting
for i := 0; i < len(z.implied); i += 2 {
key := z.implied[i].(string)
keys = append(keys, key)
result[key] = z.implied[i+1]
}
// Read new args, store map and key for consistent sorting
for i := 0; i < len(args); i += 2 {
key := args[i].(string)
_, exists := result[key]
if !exists {
keys = append(keys, key)
}
result[key] = args[i+1]
}
// Sort keys to be consistent
sort.Strings(keys)
nz.implied = make([]interface{}, 0, len(z.implied)+len(args))
for _, k := range keys {
nz.implied = append(nz.implied, k)
nz.implied = append(nz.implied, result[k])
}
return &nz
}
@ -357,6 +421,8 @@ func (z *intLogger) Named(name string) Logger {
if nz.name != "" {
nz.name = nz.name + "." + name
} else {
nz.name = name
}
return &nz
@ -373,6 +439,12 @@ func (z *intLogger) ResetNamed(name string) Logger {
return &nz
}
// Update the logging level on-the-fly. This will affect all subloggers as
// well.
func (z *intLogger) SetLevel(level Level) {
atomic.StoreInt32(z.level, int32(level))
}
// Create a *log.Logger that will send it's data through this Logger. This
// allows packages that expect to be using the standard library log to actually
// use this logger.

View File

@ -5,6 +5,7 @@ import (
"log"
"os"
"strings"
"sync"
)
var (
@ -12,7 +13,7 @@ var (
DefaultLevel = Info
)
type Level int
type Level int32
const (
// This is a special level used to indicate that no level has been
@ -36,6 +37,18 @@ const (
Error Level = 5
)
// When processing a value of this type, the logger automatically treats the first
// argument as a Printf formatting string and passes the rest as the values to be
// formatted. For example: L.Info(Fmt{"%d beans/day", beans}). This is a simple
// convience type for when formatting is required.
type Format []interface{}
// Fmt returns a Format type. This is a convience function for creating a Format
// type.
func Fmt(str string, args ...interface{}) Format {
return append(Format{str}, args...)
}
// LevelFromString returns a Level type for the named log level, or "NoLevel" if
// the level string is invalid. This facilitates setting the log level via
// config or environment variable by name in a predictable way.
@ -108,6 +121,10 @@ 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
// implementation cannot update the level on the fly, it should no-op.
SetLevel(level Level)
// Return a value that conforms to the stdlib log.Logger interface
StandardLogger(opts *StandardLoggerOptions) *log.Logger
}
@ -130,9 +147,15 @@ type LoggerOptions struct {
// Where to write the logs to. Defaults to os.Stdout if nil
Output io.Writer
// An optional mutex pointer in case Output is shared
Mutex *sync.Mutex
// Control if the output should be in JSON.
JSONFormat bool
// Intclude file and line information in each log line
// Include file and line information in each log line
IncludeLocation bool
// The time format to use instead of the default
TimeFormat string
}

47
vendor/github.com/hashicorp/go-hclog/nulllogger.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
package hclog
import (
"io/ioutil"
"log"
)
// NewNullLogger instantiates a Logger for which all calls
// will succeed without doing anything.
// Useful for testing purposes.
func NewNullLogger() Logger {
return &nullLogger{}
}
type nullLogger struct{}
func (l *nullLogger) Trace(msg string, args ...interface{}) {}
func (l *nullLogger) Debug(msg string, args ...interface{}) {}
func (l *nullLogger) Info(msg string, args ...interface{}) {}
func (l *nullLogger) Warn(msg string, args ...interface{}) {}
func (l *nullLogger) Error(msg string, args ...interface{}) {}
func (l *nullLogger) IsTrace() bool { return false }
func (l *nullLogger) IsDebug() bool { return false }
func (l *nullLogger) IsInfo() bool { return false }
func (l *nullLogger) IsWarn() bool { return false }
func (l *nullLogger) IsError() bool { return false }
func (l *nullLogger) With(args ...interface{}) Logger { return l }
func (l *nullLogger) Named(name string) Logger { return l }
func (l *nullLogger) ResetNamed(name string) Logger { return l }
func (l *nullLogger) SetLevel(level Level) {}
func (l *nullLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger {
return log.New(ioutil.Discard, "", log.LstdFlags)
}

2
vendor/vendor.json vendored
View File

@ -150,7 +150,7 @@
{"path":"github.com/hashicorp/go-envparse","checksumSHA1":"FKmqR4DC3nCXtnT9pe02z5CLNWo=","revision":"310ca1881b22af3522e3a8638c0b426629886196","revisionTime":"2018-01-19T21:58:41Z"},
{"path":"github.com/hashicorp/go-getter","checksumSHA1":"uGH6AI982csQJoRPsSooK7FoWqo=","revision":"3f60ec5cfbb2a39731571b9ddae54b303bb0a969","revisionTime":"2018-04-25T22:41:30Z"},
{"path":"github.com/hashicorp/go-getter/helper/url","checksumSHA1":"9J+kDr29yDrwsdu2ULzewmqGjpA=","revision":"b345bfcec894fb7ff3fdf9b21baf2f56ea423d98","revisionTime":"2018-04-10T17:49:45Z"},
{"path":"github.com/hashicorp/go-hclog","checksumSHA1":"miVF4/7JP0lRwZvFJGKwZWk7aAQ=","revision":"b4e5765d1e5f00a0550911084f45f8214b5b83b9","revisionTime":"2017-07-16T17:45:23Z"},
{"path":"github.com/hashicorp/go-hclog","checksumSHA1":"dOP7kCX3dACHc9mU79826N411QA=","revision":"ff2cf002a8dd750586d91dddd4470c341f981fe1","revisionTime":"2018-07-09T16:53:50Z"},
{"path":"github.com/hashicorp/go-immutable-radix","checksumSHA1":"Cas2nprG6pWzf05A2F/OlnjUu2Y=","revision":"8aac2701530899b64bdea735a1de8da899815220","revisionTime":"2017-07-25T22:12:15Z"},
{"path":"github.com/hashicorp/go-memdb","checksumSHA1":"FMAvwDar2bQyYAW4XMFhAt0J5xA=","revision":"20ff6434c1cc49b80963d45bf5c6aa89c78d8d57","revisionTime":"2017-08-31T20:15:40Z"},
{"path":"github.com/hashicorp/go-msgpack/codec","revision":"fa3f63826f7c23912c15263591e65d54d080b458"},