diff --git a/README.md b/README.md index 369489f..8d5e99c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![obligatory xkcd](http://imgs.xkcd.com/comics/standards.png) -# log15 +# log15 [![godoc reference](https://godoc.org/gopkg.in/inconshreveable/log15.v2?status.png)](https://godoc.org/gopkg.in/inconshreveable/log15.v2) Package log15 provides an opinionated, simple toolkit for best-practice logging that is both human and machine readable. It is modeled after the standard library's io and net/http packages. @@ -14,49 +14,45 @@ Package log15 provides an opinionated, simple toolkit for best-practice logging - Built-in support for logging to files, streams, syslog, and the network - Support for forking records to multiple handlers, buffering records for output, failing over from failed handler writes, + more -## Documentation - -The package documentation is extensive and complete. Browse on godoc: - -#### [log15 API Documentation](https://godoc.org/gopkg.in/inconshreveable/log15.v2) - ## Versioning The API of the master branch of log15 should always be considered unstable. Using a stable version of the log15 package is supported by gopkg.in. Include your dependency like so: import log "gopkg.in/inconshreveable/log15.v2" -You can also vendor log15 with a tool like Godep. - ## Examples - // all loggers can have key/value context - srvlog := log.New("module", "app/server") +```go +// all loggers can have key/value context +srvlog := log.New("module", "app/server") - // all log messages can have key/value context - srvlog.Warn("abnormal conn rate", "rate", curRate, "low", lowRate, "high", highRate) +// all log messages can have key/value context +srvlog.Warn("abnormal conn rate", "rate", curRate, "low", lowRate, "high", highRate) - // child loggers with inherited context - connlog := srvlog.New("raddr", c.RemoteAddr()) - connlog.Info("connection open") +// child loggers with inherited context +connlog := srvlog.New("raddr", c.RemoteAddr()) +connlog.Info("connection open") - // lazy evaluation - connlog.Debug("ping remote", "latency", log.Lazy(pingRemote)) +// lazy evaluation +connlog.Debug("ping remote", "latency", log.Lazy(pingRemote)) - // flexible configuration - srvlog.SetHandler(log.MultiHandler( - log.StreamHandler(os.Stderr, log.LogfmtFormat()), - log.LvlFilterHandler( - log.LvlError, - log.Must.FileHandler("errors.json", log.JsonHandler()))) +// flexible configuration +srvlog.SetHandler(log.MultiHandler( + log.StreamHandler(os.Stderr, log.LogfmtFormat()), + log.LvlFilterHandler( + log.LvlError, + log.Must.FileHandler("errors.json", log.JsonHandler()))) +``` ## FAQ ### The varargs style is brittle and error prone! Can I have type saftey please? Yes. Use log.Ctx: - srvlog := log.New(log.Ctx{"module": "app/server"}) - srvlog.Warn("abnormal conn rate", log.Ctx{"rate": curRate, "low": lowRate, "high": highRate}) +```go +srvlog := log.New(log.Ctx{"module": "app/server"}) +srvlog.Warn("abnormal conn rate", log.Ctx{"rate": curRate, "low": lowRate, "high": highRate}) +``` ## License Apache diff --git a/log15_test.go b/log15_test.go index 156d83c..516f7a4 100644 --- a/log15_test.go +++ b/log15_test.go @@ -189,6 +189,25 @@ func TestLogContext(t *testing.T) { } } +func TestMapCtx(t *testing.T) { + t.Parallel() + + l, _, r := testLogger() + l.Crit("test", Ctx{"foo": "bar"}) + + if len(r.Ctx) != 2 { + t.Fatalf("Wrong context length, got %d, expected %d", len(r.Ctx), 2) + } + + if r.Ctx[0] != "foo" { + t.Fatalf("Wrong context key, got %s expected %s", r.Ctx[0], "foo") + } + + if r.Ctx[1] != "bar" { + t.Fatalf("Wrong context value, got %s expected %s", r.Ctx[1], "bar") + } +} + func TestLvlFilterHandler(t *testing.T) { t.Parallel() diff --git a/logger.go b/logger.go index 00d9942..dcd7cf8 100644 --- a/logger.go +++ b/logger.go @@ -121,7 +121,7 @@ func newContext(prefix []interface{}, suffix []interface{}) []interface{} { normalizedSuffix := normalize(suffix) newCtx := make([]interface{}, len(prefix)+len(normalizedSuffix)) n := copy(newCtx, prefix) - copy(newCtx[n:], suffix) + copy(newCtx[n:], normalizedSuffix) return newCtx }