A simple logger for go that mimics the API of python's logging module

dvirsky dvirsky Last update: Aug 02, 2022

PyLog

A simple logging module that mimics the behavior of Python's logging module.

All it does basically is wrap Go's logger with nice multi-level logging calls, andallows you to set the logging level of your app in runtime.

Logging is done just like calling fmt.Sprintf:

logging.Info("This object is %s and that is %s", obj, that)

Logging level can be set to whatever you want it to be, in runtime. Contrary to Python that specifies a minimal level, this logger is set with a bit mask of active levels.

//for INFO and ERROR use:logging.SetLevel(logging.INFO | logging.ERROR)// For everything but debug and info use:logging.SetLevel(logging.ALL &^ (logging.INFO | logging.DEBUG))

As with the standard log, you can specify any io.Writer type interface and send the log's output to it instead of the default stderr.

Installation:

go get github.com/dvirsky/go-pylog/logging

Usage Example:

package mainimport (	"github.com/dvirsky/go-pylog/logging")func main() {	logging.Info("All Your Base Are Belong to %s!", "us")	logging.Critical("And now with a stack trace")}

Lazily Evaluated functions as arguments

You can give the logger a function with the signature func() interface{}, and it will only execute it if the message is being printed, and simply format its output into the log.

For example:

// just pass a lambdalogging.Debug("The time now is %s", func() interface{} { return time.Now()})// or for more complex stuff:// let's say we have this heavy weight function we want to log, // but only if the relevant level is activfunc sumSeries(s []int) int {    ret := 0    for _, n := range s {        ret += n    }    return ret}// Wrapping it in this lazy lambda this will execute the function only if the level matches Infologging.Info("The sum of my series is %d", func() interface{} { return sumSeries(mySeries)})

Custom Handlers

By default we just write to Go's log, and you can set the output stream of it. But you can add a custom handler that will receive the raw unformatted messages, format them and do whatever it wants with them. The logger currently supports a single handler.

This was added for the use case of Scribe, that needs to receive messages as a pair of category and message. So an io.Writer was not applicable.

The inreface for a LogHandler is:

type LoggingHandler interface {    Emit(level, file string, line int, message string, args ...interface{}) error}

To set your own handler (or the provided scribe handler in the library), call logging.SetHandler(myHandler).

Custom Message formatting

It is possible to change the logger's display format. The default format is"%[1]s @ %[2]s:%[2]d: %[4]s" - resulting in messages looking like:INFO @ db.go:528: Registering plugin REPLICATION.

The indexes are there so you can change the order of the formatting elements if you want. [1] means the logging level, [2] is the file, [3] is the line and [4] is the unformatted message passed to the log.

To change the way they are formatted, call logging.SetFormatString().

Example Output:

2013/05/07 01:20:26 INFO @ db.go:528: Registering plugin REPLICATION2013/05/07 01:20:26 INFO @ db.go:562: Registered 6 plugins and 22 commands2013/05/07 01:20:26 INFO @ slave.go:277: Running replication watchdog loop!2013/05/07 01:20:26 INFO @ redis.go:49: Redis adapter listening on 0.0.0.0:20002013/05/07 01:20:26 WARN @ main.go:69: Starting adapter...2013/05/07 01:20:26 INFO @ db.go:966: Finished dump load. Loaded 2 objects from dump2013/05/07 01:22:26 INFO @ db.go:329: Checking persistence... 0 changes since 2m0.000297531s2013/05/07 01:22:26 DEBUG @ db.go:341: Sleeping for 2m0s
Tags:

PRAGMA foreign_keys = off; BEGIN TRANSACTION; COMMIT TRANSACTION; PRAGMA foreign_keys = on;

Subscribe to our newsletter