Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental: zap backend for go-log #61

Merged
merged 12 commits into from
Sep 5, 2019
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
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ module github.com/ipfs/go-log

require (
github.com/gogo/protobuf v1.2.1
github.com/mattn/go-colorable v0.1.1
github.com/opentracing/opentracing-go v1.0.2
github.com/stretchr/testify v1.3.0 // indirect
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 // indirect
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.8.1 // indirect
github.com/stretchr/testify v1.4.0 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.10.0
)
30 changes: 16 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
30 changes: 30 additions & 0 deletions levels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package log

import "go.uber.org/zap/zapcore"

// LogLevel represents a log severity level. Use the package variables as an
// enum.
type LogLevel zapcore.Level

var (
LevelDebug = LogLevel(zapcore.DebugLevel)
LevelInfo = LogLevel(zapcore.InfoLevel)
LevelWarn = LogLevel(zapcore.WarnLevel)
LevelError = LogLevel(zapcore.ErrorLevel)
LevelDPanic = LogLevel(zapcore.DPanicLevel)
LevelPanic = LogLevel(zapcore.PanicLevel)
LevelFatal = LogLevel(zapcore.FatalLevel)
)

// LevelFromString parses a string-based level and returns the corresponding
// LogLevel.
//
// Supported strings are: DEBUG, INFO, WARN, ERROR, DPANIC, PANIC, FATAL, and
// their lower-case forms.
//
// The returned LogLevel must be discarded if error is not nil.
func LevelFromString(level string) (LogLevel, error) {
lvl := zapcore.InfoLevel // zero value
err := lvl.Set(level)
return LogLevel(lvl), err
}
58 changes: 28 additions & 30 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (
"time"

writer "github.com/ipfs/go-log/writer"
"github.com/whyrusleeping/go-logging"

opentrace "github.com/opentracing/opentracing-go"
otExt "github.com/opentracing/opentracing-go/ext"
"go.uber.org/zap"
)

var log = Logger("eventlog")
Expand Down Expand Up @@ -159,46 +159,48 @@ type EventLogger interface {
SerializeContext(ctx context.Context) ([]byte, error)
}

// Logger retrieves an event logger by name
func Logger(system string) EventLogger {
var _ EventLogger = Logger("test-logger")

// TODO if we would like to adjust log levels at run-time. Store this event
// logger in a map (just like the util.Logger impl)
// Logger retrieves an event logger by name
func Logger(system string) *ZapEventLogger {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the plan to eventually switch to zap directly? It seems odd to hard-code zap into this library and expose it like this if that isn't the case.

However, if that is the case, we should have a migration plan in place to get rid of the facade.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zap's interface is big but very useful for structured logging. I don't see any benefit of writing a full interface facade for it (it won't allow us to switch to something else easier).

The migration is mostly limited to stopping the use of deprecated functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But is there a plan to eventually drop this library and directly depend on Zap.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I too was in the camp that logging is so pervasive that we shouldn't introduce indirections. Also, changing the logging backend happens once in a blue moon -- so it's a questionable risk/reward gradient. However, there are some legit use cases where you'd want to replace the logging backend with something else, e.g. WASM runtimes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, as Zap doesn't provide centralised log level facilities.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, there are some legit use cases where you'd want to replace the logging backend with something else, e.g. WASM runtimes.

I guess we'd do that using build tags anyway. As long as the callers don't need to reference zap or zapcore explicitly, we should be able to mimic its public API?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can change how logging is done for WASM by changing formatters and outputs in Zap.

Problem with mimicking Zap's API is that they are at least 93 functions we would have to define.

In some cases (performance) one would use zap.Field and connected functions to achieve 0-overhead structured logging.

if len(system) == 0 {
setuplog := getLogger("setup-logger")
setuplog.Warning("Missing name parameter")
setuplog.Error("Missing name parameter")
system = "undefined"
}

logger := getLogger(system)

return &eventLogger{system: system, Logger: *logger}
return &ZapEventLogger{system: system, SugaredLogger: *logger}
}

// eventLogger implements the EventLogger and wraps a go-logging Logger
type eventLogger struct {
logging.Logger
// ZapEventLogger implements the EventLogger and wraps a go-logging Logger
type ZapEventLogger struct {
zap.SugaredLogger

system string
raulk marked this conversation as resolved.
Show resolved Hide resolved
// TODO add log-level
}

func (el *eventLogger) Warn(args ...interface{}) {
el.Warning(args...)
// Deprecated: use Warn
func (el *ZapEventLogger) Warning(args ...interface{}) {
el.Warn(args...)
}
func (el *eventLogger) Warnf(format string, args ...interface{}) {
el.Warningf(format, args...)

// Deprecated: use Warnf
func (el *ZapEventLogger) Warningf(format string, args ...interface{}) {
el.Warnf(format, args...)
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) Start(ctx context.Context, operationName string) context.Context {
func (el *ZapEventLogger) Start(ctx context.Context, operationName string) context.Context {
span, ctx := opentrace.StartSpanFromContext(ctx, operationName)
span.SetTag("system", el.system)
return ctx
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) StartFromParentState(ctx context.Context, operationName string, parent []byte) (context.Context, error) {
func (el *ZapEventLogger) StartFromParentState(ctx context.Context, operationName string, parent []byte) (context.Context, error) {
sc, err := deserializeContext(parent)
if err != nil {
return nil, err
Expand All @@ -211,7 +213,7 @@ func (el *eventLogger) StartFromParentState(ctx context.Context, operationName s
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) SerializeContext(ctx context.Context) ([]byte, error) {
func (el *ZapEventLogger) SerializeContext(ctx context.Context) ([]byte, error) {
gTracer := opentrace.GlobalTracer()
b := make([]byte, 0)
carrier := bytes.NewBuffer(b)
Expand All @@ -223,7 +225,7 @@ func (el *eventLogger) SerializeContext(ctx context.Context) ([]byte, error) {
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) LogKV(ctx context.Context, alternatingKeyValues ...interface{}) {
func (el *ZapEventLogger) LogKV(ctx context.Context, alternatingKeyValues ...interface{}) {
span := opentrace.SpanFromContext(ctx)
if span == nil {
_, file, line, _ := runtime.Caller(1)
Expand All @@ -234,7 +236,7 @@ func (el *eventLogger) LogKV(ctx context.Context, alternatingKeyValues ...interf
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) SetTag(ctx context.Context, k string, v interface{}) {
func (el *ZapEventLogger) SetTag(ctx context.Context, k string, v interface{}) {
span := opentrace.SpanFromContext(ctx)
if span == nil {
_, file, line, _ := runtime.Caller(1)
Expand All @@ -245,7 +247,7 @@ func (el *eventLogger) SetTag(ctx context.Context, k string, v interface{}) {
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) SetTags(ctx context.Context, tags map[string]interface{}) {
func (el *ZapEventLogger) SetTags(ctx context.Context, tags map[string]interface{}) {
span := opentrace.SpanFromContext(ctx)
if span == nil {
_, file, line, _ := runtime.Caller(1)
Expand All @@ -257,7 +259,7 @@ func (el *eventLogger) SetTags(ctx context.Context, tags map[string]interface{})
}
}

func (el *eventLogger) setErr(ctx context.Context, err error, skip int) {
func (el *ZapEventLogger) setErr(ctx context.Context, err error, skip int) {
span := opentrace.SpanFromContext(ctx)
if span == nil {
_, file, line, _ := runtime.Caller(skip)
Expand All @@ -273,12 +275,12 @@ func (el *eventLogger) setErr(ctx context.Context, err error, skip int) {
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) SetErr(ctx context.Context, err error) {
func (el *ZapEventLogger) SetErr(ctx context.Context, err error) {
el.setErr(ctx, err, 1)
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) Finish(ctx context.Context) {
func (el *ZapEventLogger) Finish(ctx context.Context) {
span := opentrace.SpanFromContext(ctx)
if span == nil {
_, file, line, _ := runtime.Caller(1)
Expand All @@ -289,7 +291,7 @@ func (el *eventLogger) Finish(ctx context.Context) {
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) FinishWithErr(ctx context.Context, err error) {
func (el *ZapEventLogger) FinishWithErr(ctx context.Context, err error) {
el.setErr(ctx, err, 2)
el.Finish(ctx)
}
Expand All @@ -306,7 +308,7 @@ func deserializeContext(bCtx []byte) (opentrace.SpanContext, error) {
}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) EventBegin(ctx context.Context, event string, metadata ...Loggable) *EventInProgress {
func (el *ZapEventLogger) EventBegin(ctx context.Context, event string, metadata ...Loggable) *EventInProgress {
ctx = el.Start(ctx, event)

for _, m := range metadata {
Expand All @@ -329,12 +331,8 @@ func (el *eventLogger) EventBegin(ctx context.Context, event string, metadata ..
return eip
}

type activeEventKeyType struct{}

var activeEventKey = activeEventKeyType{}

// Deprecated: Stop using go-log for event logging
func (el *eventLogger) Event(ctx context.Context, event string, metadata ...Loggable) {
func (el *ZapEventLogger) Event(ctx context.Context, event string, metadata ...Loggable) {

// short circuit if theres nothing to write to
if !writer.WriterGroup.Active() {
Expand Down
Loading