diff --git a/log/logr/v2/RELEASE.md b/log/logr/v2/RELEASE.md new file mode 100644 index 0000000..d697677 --- /dev/null +++ b/log/logr/v2/RELEASE.md @@ -0,0 +1,5 @@ +Since this is a multi module repository to ensure clients can import\ +github.com/packethost/pkg/log/logr/v2 or higher releases of this module\ +the repository must be tagged as `log/logr/v2.0.0` + +https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository diff --git a/log/logr/v2/go.mod b/log/logr/v2/go.mod new file mode 100644 index 0000000..333d72d --- /dev/null +++ b/log/logr/v2/go.mod @@ -0,0 +1,15 @@ +module github.com/packethost/pkg/log/logr/v2 + +go 1.16 + +require ( + github.com/go-logr/logr v1.2.2 + github.com/go-logr/zapr v1.2.2 + github.com/jacobweinstock/rollzap v0.1.3 + // parent module imported based on + // https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository + github.com/packethost/pkg/log/logr v0.0.0-20210106215246-8e2e62dc8f0c + github.com/pkg/errors v0.9.1 + github.com/rollbar/rollbar-go v1.2.0 + go.uber.org/zap v1.19.0 +) diff --git a/log/logr/v2/go.sum b/log/logr/v2/go.sum new file mode 100644 index 0000000..e73e0f3 --- /dev/null +++ b/log/logr/v2/go.sum @@ -0,0 +1,72 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.2 h1:5YNlIL6oZLydaV4dOFjL8YpgXF/tPeTbnpatnu3cq6o= +github.com/go-logr/zapr v1.2.2/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/jacobweinstock/rollzap v0.1.3 h1:9nkpwYew+JiDoMWwVIEUpFyos6hdfY3gDmaj6d+Hq9M= +github.com/jacobweinstock/rollzap v0.1.3/go.mod h1:hlnp7hysC0vG3HB+EXl5k8UwCjTroVtvVNqoKUCotak= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rollbar/rollbar-go v1.2.0 h1:CUanFtVu0sa3QZ/fBlgevdGQGLWaE3D4HxoVSQohDfo= +github.com/rollbar/rollbar-go v1.2.0/go.mod h1:czC86b8U4xdUH7W2C6gomi2jutLm8qK0OtrF5WMvpcc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 h1:Yq9t9jnGoR+dBuitxdo9l6Q7xh/zOyNnYUtDKaQ3x0E= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/log/logr/v2/packetlogger.go b/log/logr/v2/packetlogger.go new file mode 100644 index 0000000..db8338a --- /dev/null +++ b/log/logr/v2/packetlogger.go @@ -0,0 +1,202 @@ +package logr + +import ( + "os" + + "github.com/go-logr/logr" + "github.com/go-logr/zapr" + "github.com/pkg/errors" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// WithLogLevel sets the log level +func WithLogLevel(level string) LoggerOption { + return func(args *PacketLogr) { args.logLevel = level } +} + +// WithOutputPaths adds output paths +func WithOutputPaths(paths []string) LoggerOption { + return func(args *PacketLogr) { args.outputPaths = paths } +} + +// WithServiceName adds a service name a logged field +func WithServiceName(name string) LoggerOption { + return func(args *PacketLogr) { args.serviceName = name } +} + +// WithKeysAndValues adds extra key/value fields +func WithKeysAndValues(kvs []interface{}) LoggerOption { + return func(args *PacketLogr) { args.keysAndValues = append(args.keysAndValues, kvs...) } +} + +// WithEnableErrLogsToStderr sends .Error logs to stderr +func WithEnableErrLogsToStderr(enable bool) LoggerOption { + return func(args *PacketLogr) { args.enableErrLogsToStderr = enable } +} + +// WithEnableRollbar sends error logs to Rollbar service +func WithEnableRollbar(enable bool) LoggerOption { + return func(args *PacketLogr) { args.enableRollbar = enable } +} + +// WithRollbarConfig customizes the Rollbar details +func WithRollbarConfig(config rollbarConfig) LoggerOption { + return func(args *PacketLogr) { args.rollbarConfig = config } +} + +// PacketLogr is a wrapper around zap.SugaredLogger +type PacketLogr struct { + logr.Logger + logLevel string + outputPaths []string + serviceName string + keysAndValues []interface{} + enableErrLogsToStderr bool + enableRollbar bool + rollbarConfig rollbarConfig +} + +// LoggerOption for setting optional values +type LoggerOption func(*PacketLogr) + +// NewPacketLogr is the opionated packet logger setup +func NewPacketLogr(opts ...LoggerOption) (*PacketLogr, *zap.Logger, error) { + // defaults + const ( + defaultLogLevel = "info" + defaultServiceName = "not/set" + ) + var ( + defaultOutputPaths = []string{"stdout"} + defaultKeysAndValues = []interface{}{} + zapConfig = zap.NewProductionConfig() + zLevel = zap.InfoLevel + defaultZapOpts = []zap.Option{} + rollbarOptions zap.Option + defaultRollbarConfig = rollbarConfig{ + token: "123", + env: "production", + version: "1", + } + ) + + pl := &PacketLogr{ + Logger: logr.Logger{}, + logLevel: defaultLogLevel, + outputPaths: defaultOutputPaths, + serviceName: defaultServiceName, + keysAndValues: defaultKeysAndValues, + enableRollbar: false, + rollbarConfig: defaultRollbarConfig, + } + + for _, opt := range opts { + opt(pl) + } + + switch pl.logLevel { + case "debug": + zLevel = zap.DebugLevel + } + zapConfig.Level = zap.NewAtomicLevelAt(zLevel) + zapConfig.OutputPaths = sliceDedupe(pl.outputPaths) + + if pl.enableErrLogsToStderr { + defaultZapOpts = append(defaultZapOpts, errLogsToStderr(zapConfig)) + } + + zapLogger, err := zapConfig.Build(defaultZapOpts...) + if err != nil { + return pl, zapLogger, errors.Wrap(err, "failed to build logger config") + } + if pl.enableRollbar { + rollbarOptions = pl.rollbarConfig.setupRollbar(pl.serviceName, zapLogger) + zapLogger = zapLogger.WithOptions(rollbarOptions) + } + keysAndValues := append(pl.keysAndValues, "service", pl.serviceName) + zapLogger = zapLogger.With(handleFields(zapLogger, keysAndValues)...) + pl.Logger = zapr.NewLogger(zapLogger) + return pl, zapLogger, err +} + +func sliceDedupe(elements []string) []string { + encountered := map[string]bool{} + result := []string{} + + for v := range elements { + if encountered[elements[v]] { + } else { + encountered[elements[v]] = true + result = append(result, elements[v]) + } + } + return result +} + +func errLogsToStderr(c zap.Config) zap.Option { + errorLogs := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { + return lvl >= zapcore.ErrorLevel + }) + nonErrorLogs := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { + return !errorLogs(lvl) + }) + console := zapcore.Lock(os.Stdout) + consoleErrors := zapcore.Lock(os.Stderr) + encoder := zapcore.NewJSONEncoder(c.EncoderConfig) + + core := zapcore.NewTee( + zapcore.NewCore(encoder, console, nonErrorLogs), + zapcore.NewCore(encoder, consoleErrors, errorLogs), + ) + splitLogger := zap.WrapCore(func(c zapcore.Core) zapcore.Core { + return core + + }) + return splitLogger +} + +// handleFields converts a bunch of arbitrary key-value pairs into Zap fields. It takes +// additional pre-converted Zap fields, for use with automatically attached fields, like +// `error`. copy/paste from https://github.com/go-logr/zapr/blob/146009e52d528183a25bf1a1e3cf56d1ff3919b5/zapr.go#L79 +func handleFields(l *zap.Logger, args []interface{}, additional ...zap.Field) []zap.Field { + // a slightly modified version of zap.SugaredLogger.sweetenFields + if len(args) == 0 { + // fast-return if we have no suggared fields. + return additional + } + + // unlike Zap, we can be pretty sure users aren't passing structured + // fields (since logr has no concept of that), so guess that we need a + // little less space. + fields := make([]zap.Field, 0, len(args)/2+len(additional)) + for i := 0; i < len(args); { + // check just in case for strongly-typed Zap fields, which is illegal (since + // it breaks implementation agnosticism), so we can give a better error message. + if _, ok := args[i].(zap.Field); ok { + l.DPanic("strongly-typed Zap Field passed to logr", zap.Any("zap field", args[i])) + break + } + + // make sure this isn't a mismatched key + if i == len(args)-1 { + l.DPanic("odd number of arguments passed as key-value pairs for logging", zap.Any("ignored key", args[i])) + break + } + + // process a key-value pair, + // ensuring that the key is a string + key, val := args[i], args[i+1] + keyStr, isString := key.(string) + if !isString { + // if the key isn't a string, DPanic and stop logging + l.DPanic("non-string key argument passed to logging, ignoring all later arguments", zap.Any("invalid key", key)) + break + } + + fields = append(fields, zap.Any(keyStr, val)) + i += 2 + } + + return append(fields, additional...) +} diff --git a/log/logr/v2/packetlogger_test.go b/log/logr/v2/packetlogger_test.go new file mode 100644 index 0000000..ce1adff --- /dev/null +++ b/log/logr/v2/packetlogger_test.go @@ -0,0 +1,112 @@ +package logr + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + "strings" + "sync" + "testing" +) + +func TestPacketLogr(t *testing.T) { + expectedLogMsg := "new logger test message" + capturedOutput := captureOutput(func() { + l, _, err := NewPacketLogr() + if err != nil { + t.Fatal(err) + } + l.V(0).Info(expectedLogMsg) + }) + if !strings.Contains(capturedOutput, expectedLogMsg) { + t.Fatalf("expected to contain: %v, got: %v", expectedLogMsg, capturedOutput) + } +} + +func TestPacketLogrRollbarEnabled(t *testing.T) { + expectedLogMsg := "test error message" + + capturedOutput := captureOutput(func() { + l, _, err := NewPacketLogr( + WithLogLevel("debug"), + WithEnableRollbar(true), + WithServiceName("github.com/packethost/pkg"), + WithRollbarConfig(rollbarConfig{ + token: "badtoken", + env: "production", + version: "v2", + }), + ) + if err != nil { + t.Fatal(err) + } + l.V(0).Error(errors.New("packetlogger test error"), expectedLogMsg) + + }) + if !strings.Contains(capturedOutput, expectedLogMsg) { + t.Fatalf("expected to contain: %v, got: %v", expectedLogMsg, capturedOutput) + } + fmt.Println(capturedOutput) + +} + +func TestPacketLogrWithOptions(t *testing.T) { + expectedLogMsg := "new logger test message" + expectedKeyValue := "\"hello\":\"world\"" + serviceName := "myservice" + expectedServiceKV := fmt.Sprintf("\"service\":\"%v\"", serviceName) + capturedOutput := captureOutput(func() { + l, _, err := NewPacketLogr( + WithLogLevel("debug"), + WithOutputPaths([]string{"stdout"}), + WithServiceName(serviceName), + WithKeysAndValues([]interface{}{"hello", "world"}), + WithKeysAndValues([]interface{}{"world", "hello"}), + WithEnableErrLogsToStderr(true), + ) + if err != nil { + t.Fatal(err) + } + l.V(0).Info(expectedLogMsg) + }) + if !strings.Contains(capturedOutput, expectedLogMsg) { + t.Fatalf("expected to contain: %v, got: %v", expectedLogMsg, capturedOutput) + } + if !strings.Contains(capturedOutput, expectedKeyValue) { + t.Fatalf("expected to contain: %v, got: %v", expectedKeyValue, capturedOutput) + } + if !strings.Contains(capturedOutput, expectedServiceKV) { + t.Fatalf("expected to contain: %v, got: %v", expectedServiceKV, capturedOutput) + } + fmt.Println(capturedOutput) +} + +func captureOutput(f func()) string { + reader, writer, err := os.Pipe() + if err != nil { + panic(err) + } + stdout := os.Stdout + stderr := os.Stderr + defer func() { + os.Stdout = stdout + os.Stderr = stderr + }() + os.Stdout = writer + os.Stderr = writer + out := make(chan string) + wg := new(sync.WaitGroup) + wg.Add(1) + go func() { + var buf bytes.Buffer + wg.Done() + _, _ = io.Copy(&buf, reader) + out <- buf.String() + }() + wg.Wait() + f() + writer.Close() + return <-out +} diff --git a/log/logr/v2/rollbar.go b/log/logr/v2/rollbar.go new file mode 100644 index 0000000..fcc9f01 --- /dev/null +++ b/log/logr/v2/rollbar.go @@ -0,0 +1,38 @@ +package logr + +import ( + "github.com/jacobweinstock/rollzap" + "github.com/rollbar/rollbar-go" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// rollbarConfig if enabled +type rollbarConfig struct { + token string + env string + version string +} + +// rollbarLogger for implementing the rollbar client logger +type rollbarLogger struct { + *zap.Logger +} + +func (c rollbarConfig) setupRollbar(service string, logger *zap.Logger) zap.Option { + rollbar.SetToken(c.token) + rollbar.SetEnvironment(c.env) + rollbar.SetCodeVersion(c.version) + rollbar.SetServerRoot(service) + rollbar.SetLogger(rollbarLogger{logger}) + + rollbarCore := rollzap.NewRollbarCore(zapcore.ErrorLevel) + return zap.WrapCore(func(core zapcore.Core) zapcore.Core { + return zapcore.NewTee(core, rollbarCore) + }) +} + +// Printf for internal rollbar errors +func (r rollbarLogger) Printf(format string, args ...interface{}) { + r.Sugar().Infof(format, args...) +}