2018-06-21 14:49:35 +00:00
|
|
|
package hclog
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2019-06-19 12:50:48 +00:00
|
|
|
//DefaultOutput is used as the default log output.
|
|
|
|
DefaultOutput io.Writer = os.Stderr
|
|
|
|
|
|
|
|
// DefaultLevel is used as the default log level.
|
|
|
|
DefaultLevel = Info
|
2018-06-21 14:49:35 +00:00
|
|
|
)
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Level represents a log level.
|
|
|
|
type Level int32
|
2018-06-21 14:49:35 +00:00
|
|
|
|
|
|
|
const (
|
2019-06-19 12:50:48 +00:00
|
|
|
// NoLevel is a special level used to indicate that no level has been
|
2018-06-21 14:49:35 +00:00
|
|
|
// set and allow for a default to be used.
|
|
|
|
NoLevel Level = 0
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Trace is the most verbose level. Intended to be used for the tracing
|
|
|
|
// of actions in code, such as function enters/exits, etc.
|
2018-06-21 14:49:35 +00:00
|
|
|
Trace Level = 1
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Debug information for programmer lowlevel analysis.
|
2018-06-21 14:49:35 +00:00
|
|
|
Debug Level = 2
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Info information about steady state operations.
|
2018-06-21 14:49:35 +00:00
|
|
|
Info Level = 3
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Warn information about rare but handled events.
|
2018-06-21 14:49:35 +00:00
|
|
|
Warn Level = 4
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Error information about unrecoverable events.
|
2018-06-21 14:49:35 +00:00
|
|
|
Error Level = 5
|
|
|
|
)
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Format is a simple convience type for when formatting is required. 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}).
|
2018-06-21 14:49:35 +00:00
|
|
|
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.
|
|
|
|
func LevelFromString(levelStr string) Level {
|
2019-06-19 12:50:48 +00:00
|
|
|
// We don't care about case. Accept both "INFO" and "info".
|
2018-06-21 14:49:35 +00:00
|
|
|
levelStr = strings.ToLower(strings.TrimSpace(levelStr))
|
|
|
|
switch levelStr {
|
|
|
|
case "trace":
|
|
|
|
return Trace
|
|
|
|
case "debug":
|
|
|
|
return Debug
|
|
|
|
case "info":
|
|
|
|
return Info
|
|
|
|
case "warn":
|
|
|
|
return Warn
|
|
|
|
case "error":
|
|
|
|
return Error
|
|
|
|
default:
|
|
|
|
return NoLevel
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Logger describes the interface that must be implemeted by all loggers.
|
2018-06-21 14:49:35 +00:00
|
|
|
type Logger interface {
|
|
|
|
// Args are alternating key, val pairs
|
|
|
|
// keys must be strings
|
|
|
|
// vals can be any type, but display is implementation specific
|
|
|
|
// Emit a message and key/value pairs at the TRACE level
|
|
|
|
Trace(msg string, args ...interface{})
|
|
|
|
|
|
|
|
// Emit a message and key/value pairs at the DEBUG level
|
|
|
|
Debug(msg string, args ...interface{})
|
|
|
|
|
|
|
|
// Emit a message and key/value pairs at the INFO level
|
|
|
|
Info(msg string, args ...interface{})
|
|
|
|
|
|
|
|
// Emit a message and key/value pairs at the WARN level
|
|
|
|
Warn(msg string, args ...interface{})
|
|
|
|
|
|
|
|
// Emit a message and key/value pairs at the ERROR level
|
|
|
|
Error(msg string, args ...interface{})
|
|
|
|
|
|
|
|
// Indicate if TRACE logs would be emitted. This and the other Is* guards
|
|
|
|
// are used to elide expensive logging code based on the current level.
|
|
|
|
IsTrace() bool
|
|
|
|
|
|
|
|
// Indicate if DEBUG logs would be emitted. This and the other Is* guards
|
|
|
|
IsDebug() bool
|
|
|
|
|
|
|
|
// Indicate if INFO logs would be emitted. This and the other Is* guards
|
|
|
|
IsInfo() bool
|
|
|
|
|
|
|
|
// Indicate if WARN logs would be emitted. This and the other Is* guards
|
|
|
|
IsWarn() bool
|
|
|
|
|
|
|
|
// Indicate if ERROR logs would be emitted. This and the other Is* guards
|
|
|
|
IsError() bool
|
|
|
|
|
|
|
|
// Creates a sublogger that will always have the given key/value pairs
|
|
|
|
With(args ...interface{}) Logger
|
|
|
|
|
|
|
|
// Create a logger that will prepend the name string on the front of all messages.
|
|
|
|
// If the logger already has a name, the new value will be appended to the current
|
|
|
|
// name. That way, a major subsystem can use this to decorate all it's own logs
|
|
|
|
// without losing context.
|
|
|
|
Named(name string) Logger
|
|
|
|
|
|
|
|
// Create a logger that will prepend the name string on the front of all messages.
|
|
|
|
// This sets the name of the logger to the value directly, unlike Named which honor
|
|
|
|
// the current name as well.
|
|
|
|
ResetNamed(name string) Logger
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// 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)
|
|
|
|
|
2018-06-21 14:49:35 +00:00
|
|
|
// Return a value that conforms to the stdlib log.Logger interface
|
|
|
|
StandardLogger(opts *StandardLoggerOptions) *log.Logger
|
2019-06-19 12:50:48 +00:00
|
|
|
|
|
|
|
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
|
|
|
StandardWriter(opts *StandardLoggerOptions) io.Writer
|
2018-06-21 14:49:35 +00:00
|
|
|
}
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// StandardLoggerOptions can be used to configure a new standard logger.
|
2018-06-21 14:49:35 +00:00
|
|
|
type StandardLoggerOptions struct {
|
|
|
|
// Indicate that some minimal parsing should be done on strings to try
|
|
|
|
// and detect their level and re-emit them.
|
|
|
|
// This supports the strings like [ERROR], [ERR] [TRACE], [WARN], [INFO],
|
|
|
|
// [DEBUG] and strip it off before reapplying it.
|
|
|
|
InferLevels bool
|
2019-06-19 12:50:48 +00:00
|
|
|
|
|
|
|
// ForceLevel is used to force all output from the standard logger to be at
|
|
|
|
// the specified level. Similar to InferLevels, this will strip any level
|
|
|
|
// prefix contained in the logged string before applying the forced level.
|
|
|
|
// If set, this override InferLevels.
|
|
|
|
ForceLevel Level
|
2018-06-21 14:49:35 +00:00
|
|
|
}
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// LoggerOptions can be used to configure a new logger.
|
2018-06-21 14:49:35 +00:00
|
|
|
type LoggerOptions struct {
|
|
|
|
// Name of the subsystem to prefix logs with
|
|
|
|
Name string
|
|
|
|
|
|
|
|
// The threshold for the logger. Anything less severe is supressed
|
|
|
|
Level Level
|
|
|
|
|
2019-06-19 12:50:48 +00:00
|
|
|
// Where to write the logs to. Defaults to os.Stderr if nil
|
2018-06-21 14:49:35 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
// Include file and line information in each log line
|
|
|
|
IncludeLocation bool
|
|
|
|
|
|
|
|
// The time format to use instead of the default
|
|
|
|
TimeFormat string
|
|
|
|
}
|