hclog

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 14, 2019 License: MIT Imports: 17 Imported by: 9,012

README

go-hclog

Go Documentation

go-hclog is a package for Go that provides a simple key/value logging 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 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.

Stability Note

While this library is fully open source and HashiCorp will be maintaining it (since we are and will be making extensive use of it), the API and output format is subject to minor changes as we fully bake and vet it in our projects. This notice will be removed once it's fully integrated into our major projects and no further changes are anticipated.

Installation and Docs

Install using go get github.com/hashicorp/go-hclog.

Full documentation is available at http://godoc.org/github.com/hashicorp/go-hclog

Usage

Use the global logger
hclog.Default().Info("hello world")
2017-07-05T16:15:55.167-0700 [INFO ] hello world

(Note timestamps are removed in future examples for brevity.)

Create a new logger
appLogger := hclog.New(&hclog.LoggerOptions{
	Name:  "my-app",
	Level: hclog.LevelFromString("DEBUG"),
})
Emit an Info level message with 2 key/value pairs
input := "5.5"
_, err := strconv.ParseInt(input, 10, 32)
if err != nil {
	appLogger.Info("Invalid input for ParseInt", "input", input, "error", err)
}
... [INFO ] my-app: Invalid input for ParseInt: input=5.5 error="strconv.ParseInt: parsing "5.5": invalid syntax"
Create a new Logger for a major subsystem
subsystemLogger := appLogger.Named("transport")
subsystemLogger.Info("we are transporting something")
... [INFO ] my-app.transport: we are transporting something

Notice that logs emitted by subsystemLogger contain my-app.transport, reflecting both the application and subsystem names.

Create a new Logger with fixed key/value pairs

Using With() will include a specific key-value pair in all messages emitted by that logger.

requestID := "5fb446b6-6eba-821d-df1b-cd7501b6a363"
requestLogger := subsystemLogger.With("request", requestID)
requestLogger.Info("we are transporting a request")
... [INFO ] my-app.transport: we are transporting a request: request=5fb446b6-6eba-821d-df1b-cd7501b6a363

This allows sub Loggers to be context specific without having to thread that into all the callers.

Using hclog.Fmt()
var int totalBandwidth = 200
appLogger.Info("total bandwidth exceeded", "bandwidth", hclog.Fmt("%d GB/s", totalBandwidth))
... [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 hclog.Logger by calling the StandardLogger() method. This allows you to use it with the familiar Println(), Printf(), etc. For example:

stdLogger := appLogger.StandardLogger(&hclog.StandardLoggerOptions{
	InferLevels: true,
})
// Printf() is provided by stdlib log.Logger interface, not hclog.Logger
stdLogger.Printf("[DEBUG] %+v", stdLogger)
... [DEBUG] my-app: &{mu:{state:0 sema:0} prefix: flag:0 out:0xc42000a0a0 buf:[]}

Alternatively, you may configure the system-wide logger:

// log the standard logger from 'import "log"'
log.SetOutput(appLogger.Writer(&hclog.StandardLoggerOptions{InferLevels: true}))
log.SetPrefix("")
log.SetFlags(0)

log.Printf("[DEBUG] %d", 42)
... [DEBUG] my-app: 42

Notice that if appLogger is initialized with the INFO log level and you specify InferLevels: true, you will not see any output here. You must change appLogger to DEBUG to see output. See the docs for more information.

Documentation

Index

Constants

View Source
const TimeFormat = "2006-01-02T15:04:05.000Z0700"

The time format to use for logging. This is a version of RFC3339 that contains millisecond precision

Variables

View Source
var (
	DefaultOutput = os.Stderr
	DefaultLevel  = Info
)
View Source
var (

	// The options used to create the Default logger. These are
	// read only when the Default logger is created, so set them
	// as soon as the process starts.
	DefaultOptions = &LoggerOptions{
		Level:  DefaultLevel,
		Output: DefaultOutput,
	}
)

Functions

This section is empty.

Types

type CapturedStacktrace

type CapturedStacktrace string

A stacktrace gathered by a previous call to log.Stacktrace. If passed to a logging function, the stacktrace will be appended.

func Stacktrace

func Stacktrace() CapturedStacktrace

Gather a stacktrace of the current goroutine and return it to be passed to a logging function.

type Format

type Format []interface{}

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.

func Fmt

func Fmt(str string, args ...interface{}) Format

Fmt returns a Format type. This is a convience function for creating a Format type.

type Level

type Level int32
const (
	// This is a special level used to indicate that no level has been
	// set and allow for a default to be used.
	NoLevel Level = 0

	// The most verbose level. Intended to be used for the tracing of actions
	// in code, such as function enters/exits, etc.
	Trace Level = 1

	// For programmer lowlevel analysis.
	Debug Level = 2

	// For information about steady state operations.
	Info Level = 3

	// For information about rare but handled events.
	Warn Level = 4

	// For information about unrecoverable events.
	Error Level = 5
)

func LevelFromString

func LevelFromString(levelStr string) Level

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.

type Logger

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

	// 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

	// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
	StandardWriter(opts *StandardLoggerOptions) io.Writer
}

The main Logger interface. All code should code against this interface only.

func Default

func Default() Logger

Return a logger that is held globally. This can be a good starting place, and then you can use .With() and .Name() to create sub-loggers to be used in more specific contexts.

func L

func L() Logger

A short alias for Default()

func New

func New(opts *LoggerOptions) Logger

Given the options (nil for defaults), create a new Logger

func NewNullLogger

func NewNullLogger() Logger

NewNullLogger instantiates a Logger for which all calls will succeed without doing anything. Useful for testing purposes.

type LoggerOptions

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

	// Where to write the logs to. Defaults to os.Stderr 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

	// Include file and line information in each log line
	IncludeLocation bool

	// The time format to use instead of the default
	TimeFormat string
}

type StandardLoggerOptions

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
}

Directories

Path Synopsis
Vet is a simple checker for static errors in Go source code.
Vet is a simple checker for static errors in Go source code.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL