Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions examples/addsvc/cmd/addsvc/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package main

import (
"context"
Expand Down Expand Up @@ -51,8 +51,8 @@ func main() {
var logger log.Logger
{
logger = log.NewLogfmtLogger(os.Stdout)
logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)
logger = log.NewContext(logger).With("caller", log.DefaultCaller)
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
logger = log.With(logger, "caller", log.DefaultCaller)
}
logger.Log("msg", "hello")
defer logger.Log("msg", "goodbye")
Expand Down Expand Up @@ -86,7 +86,7 @@ func main() {
var tracer stdopentracing.Tracer
{
if *zipkinAddr != "" {
logger := log.NewContext(logger).With("tracer", "ZipkinHTTP")
logger := log.With(logger, "tracer", "ZipkinHTTP")
logger.Log("addr", *zipkinAddr)

// endpoint typically looks like: http://zipkinhost:9411/api/v1/spans
Expand All @@ -105,7 +105,7 @@ func main() {
os.Exit(1)
}
} else if *zipkinKafkaAddr != "" {
logger := log.NewContext(logger).With("tracer", "ZipkinKafka")
logger := log.With(logger, "tracer", "ZipkinKafka")
logger.Log("addr", *zipkinKafkaAddr)

collector, err := zipkin.NewKafkaCollector(
Expand All @@ -126,18 +126,18 @@ func main() {
os.Exit(1)
}
} else if *appdashAddr != "" {
logger := log.NewContext(logger).With("tracer", "Appdash")
logger := log.With(logger, "tracer", "Appdash")
logger.Log("addr", *appdashAddr)
tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr))
} else if *lightstepToken != "" {
logger := log.NewContext(logger).With("tracer", "LightStep")
logger := log.With(logger, "tracer", "LightStep")
logger.Log() // probably don't want to print out the token :)
tracer = lightstep.NewTracer(lightstep.Options{
AccessToken: *lightstepToken,
})
defer lightstep.FlushLightStepTracer(tracer)
} else {
logger := log.NewContext(logger).With("tracer", "none")
logger := log.With(logger, "tracer", "none")
logger.Log()
tracer = stdopentracing.GlobalTracer() // no-op
}
Expand All @@ -155,7 +155,7 @@ func main() {
var sumEndpoint endpoint.Endpoint
{
sumDuration := duration.With("method", "Sum")
sumLogger := log.NewContext(logger).With("method", "Sum")
sumLogger := log.With(logger, "method", "Sum")

sumEndpoint = addsvc.MakeSumEndpoint(service)
sumEndpoint = opentracing.TraceServer(tracer, "Sum")(sumEndpoint)
Expand All @@ -165,7 +165,7 @@ func main() {
var concatEndpoint endpoint.Endpoint
{
concatDuration := duration.With("method", "Concat")
concatLogger := log.NewContext(logger).With("method", "Concat")
concatLogger := log.With(logger, "method", "Concat")

concatEndpoint = addsvc.MakeConcatEndpoint(service)
concatEndpoint = opentracing.TraceServer(tracer, "Concat")(concatEndpoint)
Expand All @@ -190,7 +190,7 @@ func main() {

// Debug listener.
go func() {
logger := log.NewContext(logger).With("transport", "debug")
logger := log.With(logger, "transport", "debug")

m := http.NewServeMux()
m.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
Expand All @@ -206,15 +206,15 @@ func main() {

// HTTP transport.
go func() {
logger := log.NewContext(logger).With("transport", "HTTP")
logger := log.With(logger, "transport", "HTTP")
h := addsvc.MakeHTTPHandler(endpoints, tracer, logger)
logger.Log("addr", *httpAddr)
errc <- http.ListenAndServe(*httpAddr, h)
}()

// gRPC transport.
go func() {
logger := log.NewContext(logger).With("transport", "gRPC")
logger := log.With(logger, "transport", "gRPC")

ln, err := net.Listen("tcp", *grpcAddr)
if err != nil {
Expand All @@ -232,7 +232,7 @@ func main() {

// Thrift transport.
go func() {
logger := log.NewContext(logger).With("transport", "Thrift")
logger := log.With(logger, "transport", "Thrift")

var protocolFactory thrift.TProtocolFactory
switch *thriftProtocol {
Expand Down
4 changes: 2 additions & 2 deletions examples/apigateway/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ func main() {
var logger log.Logger
{
logger = log.NewLogfmtLogger(os.Stderr)
logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)
logger = log.NewContext(logger).With("caller", log.DefaultCaller)
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
logger = log.With(logger, "caller", log.DefaultCaller)
}

// Service discovery domain. In this example we use Consul.
Expand Down
8 changes: 4 additions & 4 deletions examples/profilesvc/cmd/profilesvc/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package main

import (
"flag"
Expand All @@ -21,8 +21,8 @@ func main() {
var logger log.Logger
{
logger = log.NewLogfmtLogger(os.Stderr)
logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)
logger = log.NewContext(logger).With("caller", log.DefaultCaller)
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
logger = log.With(logger, "caller", log.DefaultCaller)
}

var s profilesvc.Service
Expand All @@ -33,7 +33,7 @@ func main() {

var h http.Handler
{
h = profilesvc.MakeHTTPHandler(s, log.NewContext(logger).With("component", "HTTP"))
h = profilesvc.MakeHTTPHandler(s, log.With(logger, "component", "HTTP"))
}

errs := make(chan error)
Expand Down
10 changes: 5 additions & 5 deletions examples/shipping/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func main() {
var logger log.Logger
logger = log.NewLogfmtLogger(os.Stderr)
logger = &serializedLogger{Logger: logger}
logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)
logger = log.With(logger, "ts", log.DefaultTimestampUTC)

var (
cargos = inmem.NewCargoRepository()
Expand Down Expand Up @@ -78,7 +78,7 @@ func main() {

var bs booking.Service
bs = booking.NewService(cargos, locations, handlingEvents, rs)
bs = booking.NewLoggingService(log.NewContext(logger).With("component", "booking"), bs)
bs = booking.NewLoggingService(log.With(logger, "component", "booking"), bs)
bs = booking.NewInstrumentingService(
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "api",
Expand All @@ -97,7 +97,7 @@ func main() {

var ts tracking.Service
ts = tracking.NewService(cargos, handlingEvents)
ts = tracking.NewLoggingService(log.NewContext(logger).With("component", "tracking"), ts)
ts = tracking.NewLoggingService(log.With(logger, "component", "tracking"), ts)
ts = tracking.NewInstrumentingService(
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "api",
Expand All @@ -116,7 +116,7 @@ func main() {

var hs handling.Service
hs = handling.NewService(handlingEvents, handlingEventFactory, handlingEventHandler)
hs = handling.NewLoggingService(log.NewContext(logger).With("component", "handling"), hs)
hs = handling.NewLoggingService(log.With(logger, "component", "handling"), hs)
hs = handling.NewInstrumentingService(
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "api",
Expand All @@ -133,7 +133,7 @@ func main() {
hs,
)

httpLogger := log.NewContext(logger).With("component", "http")
httpLogger := log.With(logger, "component", "http")

mux := http.NewServeMux()

Expand Down
2 changes: 1 addition & 1 deletion examples/stringsvc3/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func main() {

var logger log.Logger
logger = log.NewLogfmtLogger(os.Stderr)
logger = log.NewContext(logger).With("listen", *listen).With("caller", log.DefaultCaller)
logger = log.With(logger, "listen", *listen, "caller", log.DefaultCaller)

fieldKeys := []string{"method", "error"}
requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Expand Down
71 changes: 35 additions & 36 deletions log/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
# package log

`package log` provides a minimal interface for structured logging in services.
It may be wrapped to encode conventions, enforce type-safety, provide leveled logging, and so on.
It can be used for both typical application log events, and log-structured data streams.
It may be wrapped to encode conventions, enforce type-safety, provide leveled
logging, and so on. It can be used for both typical application log events,
and log-structured data streams.

## Structured logging

Structured logging is, basically, conceding to the reality that logs are _data_,
and warrant some level of schematic rigor.
Using a stricter, key/value-oriented message format for our logs,
containing contextual and semantic information,
makes it much easier to get insight into the operational activity of the systems we build.
Consequently, `package log` is of the strong belief that
"[the benefits of structured logging outweigh the minimal effort involved](https://www.thoughtworks.com/radar/techniques/structured-logging)".
Structured logging is, basically, conceding to the reality that logs are
_data_, and warrant some level of schematic rigor. Using a stricter,
key/value-oriented message format for our logs, containing contextual and
semantic information, makes it much easier to get insight into the
operational activity of the systems we build. Consequently, `package log` is
of the strong belief that "[the benefits of structured logging outweigh the
minimal effort involved](https://www.thoughtworks.com/radar/techniques/structured-logging)".

Migrating from unstructured to structured logging is probably a lot easier than you'd expect.
Migrating from unstructured to structured logging is probably a lot easier
than you'd expect.

```go
// Unstructured
Expand All @@ -37,17 +39,17 @@ logger.Log("question", "what is the meaning of life?", "answer", 42)
// question="what is the meaning of life?" answer=42
```

### Log contexts
### Contextual Loggers

```go
func main() {
var logger log.Logger
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
logger = log.NewContext(logger).With("instance_id", 123)
logger = log.With(logger, "instance_id", 123)

logger.Log("msg", "starting")
NewWorker(log.NewContext(logger).With("component", "worker")).Run()
NewSlacker(log.NewContext(logger).With("component", "slacker")).Run()
NewWorker(log.With(logger, "component", "worker")).Run()
NewSlacker(log.With(logger, "component", "slacker")).Run()
}

// Output:
Expand Down Expand Up @@ -77,9 +79,8 @@ func main() {
// {"msg":"I sure like pie","ts":"2016/01/01 12:34:56"}
```

Or, if, for legacy reasons,
you need to pipe all of your logging through the stdlib log package,
you can redirect Go kit logger to the stdlib logger.
Or, if, for legacy reasons, you need to pipe all of your logging through the
stdlib log package, you can redirect Go kit logger to the stdlib logger.

```go
logger := kitlog.NewLogfmtLogger(kitlog.StdlibWriter{})
Expand All @@ -94,7 +95,7 @@ logger.Log("legacy", true, "msg", "at least it's something")
```go
var logger log.Logger
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)

logger.Log("msg", "hello")

Expand All @@ -104,7 +105,7 @@ logger.Log("msg", "hello")

## Supported output formats

- [Logfmt](https://brandur.org/logfmt)
- [Logfmt](https://brandur.org/logfmt) ([see also](https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write))
- JSON

## Enhancements
Expand All @@ -117,27 +118,25 @@ type Logger interface {
}
```

This interface, and its supporting code like [log.Context](https://godoc.org/github.com/go-kit/kit/log#Context),
is the product of much iteration and evaluation.
For more details on the evolution of the Logger interface,
see [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1),
a talk by [Chris Hines](https://github.com/ChrisHines).
This interface, and its supporting code like is the product of much iteration
and evaluation. For more details on the evolution of the Logger interface,
see [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1),
a talk by [Chris Hines](https://github.com/ChrisHines).
Also, please see
[#63](https://github.com/go-kit/kit/issues/63),
[#76](https://github.com/go-kit/kit/pull/76),
[#131](https://github.com/go-kit/kit/issues/131),
[#157](https://github.com/go-kit/kit/pull/157),
[#164](https://github.com/go-kit/kit/issues/164), and
[#252](https://github.com/go-kit/kit/pull/252)
to review historical conversations about package log and the Logger interface.
[#63](https://github.com/go-kit/kit/issues/63),
[#76](https://github.com/go-kit/kit/pull/76),
[#131](https://github.com/go-kit/kit/issues/131),
[#157](https://github.com/go-kit/kit/pull/157),
[#164](https://github.com/go-kit/kit/issues/164), and
[#252](https://github.com/go-kit/kit/pull/252)
to review historical conversations about package log and the Logger interface.

Value-add packages and suggestions,
like improvements to [the leveled logger](https://godoc.org/github.com/go-kit/kit/log/levels),
are of course welcome.
Good proposals should
like improvements to [the leveled logger](https://godoc.org/github.com/go-kit/kit/log/level),
are of course welcome. Good proposals should

- Be composable with [log.Context](https://godoc.org/github.com/go-kit/kit/log#Context),
- Not break the behavior of [log.Caller](https://godoc.org/github.com/go-kit/kit/log#Caller) in any wrapped context, and
- Be composable with [contextual loggers](https://godoc.org/github.com/go-kit/kit/log#With),
- Not break the behavior of [log.Caller](https://godoc.org/github.com/go-kit/kit/log#Caller) in any wrapped contextual loggers, and
- Be friendly to packages that accept only an unadorned log.Logger.

## Benchmarks & comparisons
Expand Down
4 changes: 2 additions & 2 deletions log/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
)

func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) {
lc := log.NewContext(logger).With("common_key", "common_value")
lc := log.With(logger, "common_key", "common_value")
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
Expand All @@ -17,5 +17,5 @@ func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) {

var (
baseMessage = func(logger log.Logger) { logger.Log("foo_key", "foo_value") }
withMessage = func(logger log.Logger) { log.NewContext(logger).With("a", "b").Log("c", "d") }
withMessage = func(logger log.Logger) { log.With(logger, "a", "b").Log("c", "d") }
)
Loading