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