1# package log
2
3[](https://pkg.go.dev/github.com/go-kit/log)
4[](https://goreportcard.com/report/go-kit/log)
5[](https://github.com/go-kit/log/actions/workflows/test.yml)
6[](https://coveralls.io/github/go-kit/log?branch=main)
7
8`package log` provides a minimal interface for structured logging in services.
9It may be wrapped to encode conventions, enforce type-safety, provide leveled
10logging, and so on. It can be used for both typical application log events,
11and log-structured data streams.
12
13## Structured logging
14
15Structured logging is, basically, conceding to the reality that logs are
16_data_, and warrant some level of schematic rigor. Using a stricter,
17key/value-oriented message format for our logs, containing contextual and
18semantic information, makes it much easier to get insight into the
19operational activity of the systems we build. Consequently, `package log` is
20of the strong belief that "[the benefits of structured logging outweigh the
21minimal effort involved](https://www.thoughtworks.com/radar/techniques/structured-logging)".
22
23Migrating from unstructured to structured logging is probably a lot easier
24than you'd expect.
25
26```go
27// Unstructured
28log.Printf("HTTP server listening on %s", addr)
29
30// Structured
31logger.Log("transport", "HTTP", "addr", addr, "msg", "listening")
32```
33
34## Usage
35
36### Typical application logging
37
38```go
39w := log.NewSyncWriter(os.Stderr)
40logger := log.NewLogfmtLogger(w)
41logger.Log("question", "what is the meaning of life?", "answer", 42)
42
43// Output:
44// question="what is the meaning of life?" answer=42
45```
46
47### Contextual Loggers
48
49```go
50func main() {
51 var logger log.Logger
52 logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
53 logger = log.With(logger, "instance_id", 123)
54
55 logger.Log("msg", "starting")
56 NewWorker(log.With(logger, "component", "worker")).Run()
57 NewSlacker(log.With(logger, "component", "slacker")).Run()
58}
59
60// Output:
61// instance_id=123 msg=starting
62// instance_id=123 component=worker msg=running
63// instance_id=123 component=slacker msg=running
64```
65
66### Interact with stdlib logger
67
68Redirect stdlib logger to Go kit logger.
69
70```go
71import (
72 "os"
73 stdlog "log"
74 kitlog "github.com/go-kit/log"
75)
76
77func main() {
78 logger := kitlog.NewJSONLogger(kitlog.NewSyncWriter(os.Stdout))
79 stdlog.SetOutput(kitlog.NewStdlibAdapter(logger))
80 stdlog.Print("I sure like pie")
81}
82
83// Output:
84// {"msg":"I sure like pie","ts":"2016/01/01 12:34:56"}
85```
86
87Or, if, for legacy reasons, you need to pipe all of your logging through the
88stdlib log package, you can redirect Go kit logger to the stdlib logger.
89
90```go
91logger := kitlog.NewLogfmtLogger(kitlog.StdlibWriter{})
92logger.Log("legacy", true, "msg", "at least it's something")
93
94// Output:
95// 2016/01/01 12:34:56 legacy=true msg="at least it's something"
96```
97
98### Timestamps and callers
99
100```go
101var logger log.Logger
102logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
103logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
104
105logger.Log("msg", "hello")
106
107// Output:
108// ts=2016-01-01T12:34:56Z caller=main.go:15 msg=hello
109```
110
111## Levels
112
113Log levels are supported via the [level package](https://godoc.org/github.com/go-kit/log/level).
114
115## Supported output formats
116
117- [Logfmt](https://brandur.org/logfmt) ([see also](https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write))
118- JSON
119
120## Enhancements
121
122`package log` is centered on the one-method Logger interface.
123
124```go
125type Logger interface {
126 Log(keyvals ...interface{}) error
127}
128```
129
130This interface, and its supporting code like is the product of much iteration
131and evaluation. For more details on the evolution of the Logger interface,
132see [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1),
133a talk by [Chris Hines](https://github.com/ChrisHines).
134Also, please see
135[#63](https://github.com/go-kit/kit/issues/63),
136[#76](https://github.com/go-kit/kit/pull/76),
137[#131](https://github.com/go-kit/kit/issues/131),
138[#157](https://github.com/go-kit/kit/pull/157),
139[#164](https://github.com/go-kit/kit/issues/164), and
140[#252](https://github.com/go-kit/kit/pull/252)
141to review historical conversations about package log and the Logger interface.
142
143Value-add packages and suggestions,
144like improvements to [the leveled logger](https://godoc.org/github.com/go-kit/log/level),
145are of course welcome. Good proposals should
146
147- Be composable with [contextual loggers](https://godoc.org/github.com/go-kit/log#With),
148- Not break the behavior of [log.Caller](https://godoc.org/github.com/go-kit/log#Caller) in any wrapped contextual loggers, and
149- Be friendly to packages that accept only an unadorned log.Logger.
150
151## Benchmarks & comparisons
152
153There are a few Go logging benchmarks and comparisons that include Go kit's package log.
154
155- [imkira/go-loggers-bench](https://github.com/imkira/go-loggers-bench) includes kit/log
156- [uber-common/zap](https://github.com/uber-common/zap), a zero-alloc logging library, includes a comparison with kit/log
View as plain text