# go-hclog [![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] [godocs]: https://godoc.org/github.com/hashicorp/go-hclog `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 This library has reached 1.0 stability. Its API can be considered solidified and promised through future versions. ## 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 ```go hclog.Default().Info("hello world") ``` ```text 2017-07-05T16:15:55.167-0700 [INFO ] hello world ``` (Note timestamps are removed in future examples for brevity.) ### Create a new logger ```go appLogger := hclog.New(&hclog.LoggerOptions{ Name: "my-app", Level: hclog.LevelFromString("DEBUG"), }) ``` ### Emit an Info level message with 2 key/value pairs ```go input := "5.5" _, err := strconv.ParseInt(input, 10, 32) if err != nil { appLogger.Info("Invalid input for ParseInt", "input", input, "error", err) } ``` ```text ... [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 ```go subsystemLogger := appLogger.Named("transport") subsystemLogger.Info("we are transporting something") ``` ```text ... [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. ```go requestID := "5fb446b6-6eba-821d-df1b-cd7501b6a363" requestLogger := subsystemLogger.With("request", requestID) requestLogger.Info("we are transporting a request") ``` ```text ... [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()` ```go 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 `hclog.Logger` by calling the `StandardLogger()` method. This allows you to use it with the familiar `Println()`, `Printf()`, etc. For example: ```go stdLogger := appLogger.StandardLogger(&hclog.StandardLoggerOptions{ InferLevels: true, }) // Printf() is provided by stdlib log.Logger interface, not hclog.Logger stdLogger.Printf("[DEBUG] %+v", stdLogger) ``` ```text ... [DEBUG] my-app: &{mu:{state:0 sema:0} prefix: flag:0 out:0xc42000a0a0 buf:[]} ``` Alternatively, you may configure the system-wide logger: ```go // log the standard logger from 'import "log"' log.SetOutput(appLogger.StandardWriter(&hclog.StandardLoggerOptions{InferLevels: true})) log.SetPrefix("") log.SetFlags(0) log.Printf("[DEBUG] %d", 42) ``` ```text ... [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. If the log lines start with a timestamp you can use the `InferLevelsWithTimestamp` option to try and ignore them. Please note that in order for `InferLevelsWithTimestamp` to be relevant, `InferLevels` must be set to `true`.