Skip to content
Open
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
5 changes: 5 additions & 0 deletions log/logr/v2/RELEASE.md
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions log/logr/v2/go.mod
Original file line number Diff line number Diff line change
@@ -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
)
72 changes: 72 additions & 0 deletions log/logr/v2/go.sum
Original file line number Diff line number Diff line change
@@ -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=
202 changes: 202 additions & 0 deletions log/logr/v2/packetlogger.go
Original file line number Diff line number Diff line change
@@ -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...)
}
Loading