Documentation ¶
Overview ¶
Logs that are easy for computers to parse, easy for people to read, and easy for programmers to generate. The logs are written in JSON format but the order of the data in each line is controlled to make the logs quite nice for humans to read even with no processing or tooling.
lager.Fail(ctx).List("Can't reach", dest, err)
could output:
["2018-12-31 23:59:59.860Z", "FAIL", "Can't reach", "localhost", "refused"]
unless the Fail log level had been disabled. While:
lager.Info().Map("Err", err, "for", obj)
logs nothing by default. But if Info log level is enabled, it might log:
["2018-12-31 23:59:59.870Z", "INFO", {"Err":"bad cost", "for":{"cost":-1}}]
There are 9 log levels and 7 can be separately enabled or diabled. You usually use them via code similar to:
lager.Panic().List(args...) // Calls panic(), always enabled. lager.Exit().Map(pairs...) // To Stderr, calls os.Exit(1), always enabled. lager.Fail().List(args...) // For non-normal failures (default on). lager.Warn().Map(pairs...) // For warnings (default on). lager.Note().Map(pairs...) // For normal, important notices (default on). lager.Acc().Map(pairs...) // For access logs (default on). lager.Info().List(args...) // For normal events (default off). laber.Trace().List(args...) // For tracing code flow (default off). laber.Debug().Map(pairs...) // For debugging details (default off). laber.Obj().List(args....) // For object dumps (default off). lager.Guts().Map(pairs...) // For volumious data dumps (default off).
The Panic and Exit levels cannot be disabled. Of the others, only Fail, Warn, Note, and Acc levels are enabled by default. When the Lager module is initialized, the following code is called:
lager.Init(os.Getenv("LAGER_LEVELS"))
and lager.Init("") is the same as lager.Init("Fail Warn Note Acc") [which is the same as lager.Init("FWNA")]. So you can set the LAGER_LEVELS environment variable to change which log levels are enabled. Application code can also choose to support other ways to override those defaults.
If you want to decorate each log line with additional key/value pairs, then you can accumulate those in a context.Context value that gets passed around and then pass that Context in when logging:
// In a method dispatcher, for example: ctx = lager.AddPairs(ctx, "srcIP", ip, "user", username) // In a method or code that a method calls, for example: lager.Info(ctx).Map(pairs...) // Or, if you have multiple log lines at the same level: debug := lager.Debug(ctx) debug.Map(pairs...) debug.List(args...)
Most log archiving systems expect JSON log lines to be a hash not a list. This is globally enabled by specifying the keys to use for the items that can be included in a log line: timestamp, level, single item, list data, context, and module.
// Example choice of logging keys: lager.Keys("t", "l", "msg", "a", "", "mod") // Sample usage of List(): lager.Fail(ctx).List("Conn", dest, err) // Example log line from above code: {"t":"2018-12-31 23:59:59.860Z", "l":"FAIL", "a":["Conn", "mx", "reset"]} // Sample usage of Map(): lager.Warn().Map("Err", err, "for", obj) // Example log line from above code: {"t":"2018-12-31 23:59:59.870Z", "l":"WARN", "Err":"<0", "for":{"cost":-1}}
Index ¶
- Variables
- func GcpLevelName(lev string) string
- func GetModuleLevels(name string) string
- func GetModules() map[string]string
- func Init(levels string)
- func Keys(when, lev, msg, args, ctx, mod string)
- func S(arg interface{}) string
- func SetModuleLevels(name, levels string) bool
- func Unless(cond bool, label string) interface{}
- type AList
- type AMap
- type Ctx
- type KVPairs
- type Lager
- func Acc(cs ...Ctx) Lager
- func Debug(cs ...Ctx) Lager
- func Exit(cs ...Ctx) Lager
- func Fail(cs ...Ctx) Lager
- func Guts(cs ...Ctx) Lager
- func Info(cs ...Ctx) Lager
- func Level(lev byte, cs ...Ctx) Lager
- func Note(cs ...Ctx) Lager
- func Obj(cs ...Ctx) Lager
- func Panic(cs ...Ctx) Lager
- func Trace(cs ...Ctx) Lager
- func Warn(cs ...Ctx) Lager
- type Module
- func (m *Module) Acc(cs ...Ctx) Lager
- func (m *Module) Debug(cs ...Ctx) Lager
- func (m *Module) Exit(cs ...Ctx) Lager
- func (m *Module) Fail(cs ...Ctx) Lager
- func (m *Module) Guts(cs ...Ctx) Lager
- func (m *Module) Info(cs ...Ctx) Lager
- func (m *Module) Init(levels string) *Module
- func (m *Module) Level(lev byte, cs ...Ctx) Lager
- func (m *Module) Note(cs ...Ctx) Lager
- func (m *Module) Obj(cs ...Ctx) Lager
- func (m *Module) Panic(cs ...Ctx) Lager
- func (m *Module) Trace(cs ...Ctx) Lager
- func (m *Module) Warn(cs ...Ctx) Lager
- type RawMap
- type Stringer
Constants ¶
This section is empty.
Variables ¶
var LevelNotation = func(lev string) string { return lev }
LevelNotation takes a log level name (like "DEBUG") and returns how that level should be shown in the log. This defaults to not changing the level name. If the environment variable LAGER_GCP is non-empty, then it instead defaults to using GcpLevelName().
var OutputDest io.Writer
Set OutputDest to a non-nil io.Writer to not write logs to os.Stdout and os.Stderr.
var PathParts = 0
'pathParts' to use when -1 is passed to WithCaller() or WithStack().
var SkipThisPair = skipThisPair("")
Functions ¶
func GcpLevelName ¶ added in v1.1.2
GcpLevelName takes a Lager level name (only the first letter matters and it must be upper case) and returns the corresponding value GCP uses in structured logging to represent the severity of such logs. Levels are mapped as:
Not used: Alert ("700") and Emergency ("800") Panic, Exit - Critical ("600") Fail - Error ("500") Warn - Warning ("400") Note - Notice ("300") Access, Info - Info ("200") Trace, Debug, Obj, Guts - Debug ("100") Not possible (except due to bug in Lager): Default ("0")
If the environment variable LAGER_GCP is not empty, then lager.LevelNotation will be initalized to lager.GcpLevelName.
func GetModuleLevels ¶
En-/disables log levels for the named module. If no module by that name exists yet, then "n/a" is returned. Otherwise returns the enabled levels.
func GetModules ¶
Returns a map[string]string where the keys are all of the module names and the values are their enabled levels.
func Init ¶
func Init(levels string)
En-/disables log levels. Pass in a string of letters from "FWNAITDOG" to indicate which log levels should be the only ones that produce output. Each letter is the first letter of a log level (Fail, Warn, Note, Acc, Info, Trace, Debug, Obj, or Guts). Levels Panic and Exit are always enabled. Init("") acts like Init("FWNA"), the default setting. To disable all optional logs, you can use Init("-") as any characters not from "FWNAITDOG" are silently ignored. So you can also call Init("Fail Warn Note Acc Info").
func Keys ¶
func Keys(when, lev, msg, args, ctx, mod string)
Output each future log line as a JSON hash ("object") using the given keys. 'when' is used for the timestamp. 'lev' is used for the log level name. 'msg' is either "" or will be used when a single argument is passed to List(). 'msg' is also used for the first argument to MMap() and MList(). 'args' is used for the arguments to List() when 'msg' is not. 'mod' is used for the module name (if any).
'ctx' is used for the hash context values (if any). Specify "" for 'ctx' to have any context key/value pairs included in-line in the top-level JSON hash (care should be taken to avoid duplicate key names).
If the environment variable LAGER_KEYS is set it must contain 6 key names separated by commas and those become the default keys to use. Otherwise, if the environment variable LAGER_GCP is not empty, then it is as if you had the following set (among other changes):
LAGER_KEYS="timestamp,severity,message,data,,module"
Pass in 6 empty strings to revert to logging a JSON list (array).
func S ¶
func S(arg interface{}) string
Converts an arbitrary value to a string. Very similar to fmt.Sprintf("%v",arg) but treats []byte values the same as strings rather then dumping them as a list of byte values in base 10.
func SetModuleLevels ¶
En-/disables log levels for the named module. If no module by that name exists yet, then false is returned.
func Unless ¶ added in v1.1.2
Unless() is used to pass an optional label+value pair to Map(). Use Unless() to specify the label and, if the value is unsafe to compute, then wrap it in a deferring function:
lager.Debug().Map( "Ran", stage, // Don't include `"Error": null,` in the log: lager.Unless(nil == err, "Error"), err, // Don't call config.Proxy() if config is nil: lager.Unless(nil == config, "Proxy"), func() interface{} { return config.Proxy() }, )
Types ¶
type AMap ¶
type AMap = *KVPairs
A processed list of key/value pairs we can efficiently convert to JSON.
func ContextPairs ¶
Fetches the lager key/value pairs stored in a context.Context.
func Pairs ¶
func Pairs(pairs ...interface{}) AMap
Returns a (processed) list of key/value pairs (lager.AMap) that can be added to a context.Context to specify additional data to append to each log line.
func (AMap) AddPairs ¶
Return an AMap with the passed-in key/value pairs added to and/or replacing the keys/values from the method receiver.
type Ctx ¶
Just an alias for context.Context that takes up less space in function signatures. You never need to use lager.Ctx in your code.
type KVPairs ¶
type KVPairs struct {
// contains filtered or unexported fields
}
Storage for an ordered list of key/value pairs (without duplicate keys).
type Lager ¶
type Lager interface { // Writes a single log line to Stdout in JSON format encoding a UTC time- // stamp followed by the log level and the passed-in values. For example: // lager.Warn().List("Timeout", dest, secs) // might output: // ["2018-12-31 23:59:59.086Z", "WARN", ["Timeout", "dbhost", 5]] // Or logs nothing if the corresponding log level is not enabled. List(args ...interface{}) // Same as '.WithCaller(0,-1).List(...)'. Good to use when your data does // not contain a fairly unique string to search for in the code. CList(args ...interface{}) // If Keys() have not been set, then acts similar to List(). // // If Keys() have been set, then acts similar to: // Map("msg", message, "args", lager.List(args...)) // except the "msg" and "data" keys are taken from the Keys() config. // // Prefer MList() or List() with a single argument over List() with // multiple arguments if using log parsers that expect to always have // a "message" string (such as GCP logging). But try to avoid // interpretting data into your message string as this can make // structured logs less useful. MList(message string, args ...interface{}) // Same as '.WithCaller(0,-1).MList(...)'. CMList(message string, args ...interface{}) // Writes a single log line to Stdout in JSON format encoding a list of // a UTC timestamp (string), the log level (string), and a map composed // of the key/value pairs passed in. For example: // lager.Warn().Map("Err", err, "for", obj) // might output: // ["2018-12-31 23:59:59.086Z", "WARN", {"Err":"no cost", "for":{"c":-1}}] // Or logs nothing if the corresponding log level is not enabled. Map(pairs ...interface{}) // Same as '.WithCaller(0,-1).Map(...)'. Good to use when your data does // not contain a fairly unique string to search for in the code. CMap(pairs ...interface{}) // The same as Map("message", message, pairs...) except instead of using // the hard-coded "message" key, it uses the corresponding key configured // via Keys(). // // Prefer MMap() over Map() if using log parsers that expect to always // have a "message" string (such as GCP logging). MMap(message string, pairs ...interface{}) // Same as '.WithCaller(0,-1).MMap(...)'. CMMap(message string, pairs ...interface{}) // Gets a new Lager that adds to each log line the key/value pairs from // zero or more context.Context values. With(ctxs ...context.Context) Lager // Does this Lager log anything? Enabled() bool // Adds a "_stack" key/value pair to the logged context. The value // is a list of strings where each string is a line number (base 10) // followed by a space and then the code file name (shortened to the last // 'pathParts' components). // // If 'stackLen' is 0 (or negative), then the full stack trace will be // included. Otherwise, the list will contain at most 'stackLen' strings. // The first string will always be for depth 'minDepth'. // // See WithCaller() for details on usage of 'minDepth' and 'pathParts'. WithStack(minDepth, stackLen, pathParts int) Lager // Adds "_file" and "_line" key/value pairs to the logged context. // 'depth' of 0 means the line where WithCaller() was called. 'depth' // of 1 would be the line of the caller of the caller of WithCaller(). // // 'pathParts' indicates how many directories to include in the code file // name. A 0 'pathParts' includes the full path. A 1 would only include // the file name. A 2 would include the file name and the deepest sub- // directory name. A -1 uses the value of lager.PathParts. WithCaller(depth, pathParts int) Lager // The Println() method is provided for minimal compatibility with // log.Logger, as this method is the one most used by other modules. // It is just an alias for the List() method. Println(...interface{}) }
The interface returned from lager.Warn() and the other log-level selectors.
func Acc ¶
Returns a Lager object. If Acc log level has been disabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to write access logs. The level is recorded as "ACCESS".
func Debug ¶
Returns a Lager object. If Debug log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to log important details that may help in debugging.
func Exit ¶
Returns a Lager object that writes to os.Stderr then calls os.Exit(1). This log level is often called "Fatal" but loggers are inconsistent as to whether logging at the Fatal level causes the process to exit. By naming this level Exit, that ambiguity is removed.
func Fail ¶
Returns a Lager object. If Fail log level has been disabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to report errors that are not part of the normal flow.
func Guts ¶
Returns a Lager object. If Guts log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level for debugging data that is too voluminous to always include when debugging.
func Info ¶
Returns a Lager object. If Info log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to report minor milestones that are part of normal flow.
func Level ¶
Pass in one character from "PEFWNAITDOG" to get a Lager object that either logs or doesn't, depending on whether the specified log level is enabled.
func Note ¶ added in v1.1.2
Returns a Lager object. If Note log level has been disabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to report major milestones that are part of normal flow.
func Obj ¶
Returns a Lager object. If Obj log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to log the details of internal data structures.
func Panic ¶
Returns a Lager object that calls panic(). The JSON log line is first output to os.Stderr and then
panic("lager.Panic() logged (see above)")
is called.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
A named module that allows separate log levels to be en-/disabled.
func NewModule ¶
Create a new Module with the given name. Default log levels can also be passed in as an optional second argument. The initial log levels enabled are taken from the last item in the list that is not "":
The current globally enabled levels. The (optional) passed-in defaultLevels. The value of the LAGER_{module_name}_LEVELS environment variable.
If you wish to ignore the LAGER_{module_name}_LEVELS environment varible, then write code similar to:
mod := lager.NewModule("mymod").Init("FW")
func (*Module) Acc ¶
Returns a Lager object. If Acc log level has been disabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to write access logs.
func (*Module) Debug ¶
Returns a Lager object. If Debug log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to log important details that may help in debugging.
func (*Module) Exit ¶
Returns a Lager object that writes to os.Stderr then calls os.Exit(1). This log level is often called "Fatal" but loggers are inconsistent as to whether logging at the Fatal level causes the process to exit. By naming this level Exit, that ambiguity is removed.
func (*Module) Fail ¶
Returns a Lager object. If Fail log level has been disabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to report errors that are not part of the normal flow.
func (*Module) Guts ¶
Returns a Lager object. If Guts log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level for debugging data that is too voluminous to always include when debugging.
func (*Module) Info ¶
Returns a Lager object. If Info log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to report minor milestones that are part of normal flow.
func (*Module) Init ¶
En-/disables log levels. Pass in a string of letters from "FWNAITDOG" to indicate which log levels should be the only ones that produce output. Each letter is the first letter of a log level (Fail, Warn, Note, Acc, Info, Trace, Debug, Obj, or Guts). Levels Panic and Exit are always enabled. Init("") copies the current globally enabled levels. To disable all optional logs, you can use Init("-") as any characters not from "FWNAITDOG" are silently ignored. So you can also call Init("Fail Warn Note Acc Info").
func (*Module) Level ¶
Pass in one character from "PEFWITDOG" to get a Lager object that either logs or doesn't, depending on whether the specified log level is enabled.
func (*Module) Note ¶ added in v1.1.2
Returns a Lager object. If Note log level has been disabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to report major milestones that are part of normal flow.
func (*Module) Obj ¶
Returns a Lager object. If Obj log level is not enabled, then the returned Lager will be one that does nothing (produces no output). Use this log level to log the details of internal data structures.
func (*Module) Panic ¶
Returns a Lager object that calls panic(). The JSON log line is first output to os.Stderr and then
panic("lager.Panic() logged (see above)")
is called.
type RawMap ¶
type RawMap []interface{}
A raw list of key/value pairs we can efficiently convert to JSON as a map.
func GcpHttp ¶ added in v1.1.2
GcpHtttp() returns a value for logging that GCP will recognize as details about an HTTP(S) request (and perhaps its response), if placed under the key "httpRequest".
`req` must not be `nil` but `resp` and `start` can be. `*start` will not be modified; `start` is of type `*time.Time` only to make it simple to omit latency calculations by passing in `nil`.
When using tracing, this allows GCP logging to display log lines for the same request (if each includes this block) together. So this can be a good thing to add to a context.Context used with your logging. For this to work, you must log a final message that includes all three arguments (as well as using GCP-compatible tracing).
The following items will be logged (in order in the original JSON, but GCP does not preserve order of JSON keys, understandably), except that some can be omitted depending on what you pass in.
"protocol" E.g. "HTTP/1.1" "requestMethod" E.g. "GET" "requestUrl" E.g. "https://cool.me/api/v1" "status" E.g. "403" "requestSize" Omitted if the request body size is not yet known. "responseSize" Omitted if `resp` is `nil` or body size not known. "latency" E.g. "0.1270s". Omitted if `start` is `nil`. "remoteIp" E.g. "127.0.0.1" "serverIp" Not currently ever included. "referer" Omitted if there is no Referer[sic] header. "userAgent" Omitted if there is no User-Agent header.
func Map ¶
func Map(pairs ...interface{}) RawMap
Returns a raw list of key/value pairs (lager.RawMap) that can be passed as an argument to another List() or Map() call to construct nested data that can be quickly serialized to JSON.
Dupliate keys all get output. If you need to squash duplicate keys, then call lager.Pairs() instead.
lager.Info(ctx).List("Using", lager.Map("name", name, "age", age))