diff --git a/cmd/proxy/actions/basicauth_test.go b/cmd/proxy/actions/basicauth_test.go index d7ec083d4..54e72e026 100644 --- a/cmd/proxy/actions/basicauth_test.go +++ b/cmd/proxy/actions/basicauth_test.go @@ -70,7 +70,7 @@ func TestBasicAuth(t *testing.T) { w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodGet, tc.path, nil) r.SetBasicAuth(tc.user, tc.pass) - lggr := log.New("none", logrus.DebugLevel) + lggr := log.New("none", logrus.DebugLevel, "") buf := &bytes.Buffer{} lggr.Out = buf ctx := log.SetEntryInContext(context.Background(), lggr) diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index e0a75fc91..d139d715e 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -42,7 +42,7 @@ func main() { stdlog.Fatalf("Could not parse log level %q: %v", conf.LogLevel, err) } - logger := athenslog.New(conf.CloudRuntime, logLvl) + logger := athenslog.New(conf.CloudRuntime, logLvl, conf.LogFormat) // Turn standard logger output into logrus Errors. logrusErrorWriter := logger.WriterLevel(logrus.ErrorLevel) diff --git a/config.dev.toml b/config.dev.toml index fbf5e29a8..187eeb37d 100755 --- a/config.dev.toml +++ b/config.dev.toml @@ -78,6 +78,11 @@ ProtocolWorkers = 30 # Env override: ATHENS_LOG_LEVEL LogLevel = "debug" +# LogFormat determines the format that logs are output in. Defaults to json. +# It is only used when CloudRuntime is set to none. Values can be "plain" or "json". +# Env override: ATHENS_LOG_FORMAT +LogFormat = "json" + # CloudRuntime is the Cloud Provider on which the Proxy/Registry is running. # Currently available options are "GCP", or "none". Defaults to "none" # Env override: ATHENS_CLOUD_RUNTIME diff --git a/go.mod b/go.mod index b4f1a848c..0661fe90b 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/aws/aws-sdk-go v1.44.220 github.com/bsm/redislock v0.7.2 github.com/fatih/color v1.13.0 + github.com/go-playground/validator/v10 v10.19.0 github.com/go-redis/redis/v8 v8.11.4 github.com/go-sql-driver/mysql v1.6.0 github.com/gobuffalo/envy v1.7.0 @@ -40,7 +41,6 @@ require ( golang.org/x/oauth2 v0.11.0 golang.org/x/sync v0.3.0 google.golang.org/api v0.126.0 - gopkg.in/go-playground/validator.v9 v9.20.2 ) require ( @@ -64,8 +64,9 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.0 // indirect - github.com/go-playground/locales v0.12.1 // indirect - github.com/go-playground/universal-translator v0.16.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect @@ -88,6 +89,7 @@ require ( github.com/klauspost/compress v1.9.5 // indirect github.com/klauspost/cpuid v1.2.3 // indirect github.com/kylelemons/godebug v1.1.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/markbates/hmax v1.0.0 // indirect github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d // indirect @@ -132,9 +134,9 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect @@ -145,7 +147,6 @@ require ( google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/DataDog/dd-trace-go.v1 v1.10.0 // indirect - gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/ini.v1 v1.42.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index a663003e8..f30db6e05 100644 --- a/go.sum +++ b/go.sum @@ -160,6 +160,8 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -170,10 +172,13 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= +github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -375,6 +380,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/markbates/hmax v1.0.0 h1:yo2N0gBoCnUMKhV/VRLHomT6Y9wUm+oQQENuWJqCdlM= @@ -599,8 +606,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -684,8 +691,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -772,8 +779,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -980,10 +987,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.20.2 h1:6AVDyt8bk0FDiSYSeWivUfzqEjHyVSCMRkpTr6ZCIgk= -gopkg.in/go-playground/validator.v9 v9.20.2/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= diff --git a/pkg/config/config.go b/pkg/config/config.go index f0308f4f6..177a0b523 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -10,10 +10,10 @@ import ( "strings" "github.com/BurntSushi/toml" + "github.com/go-playground/validator/v10" "github.com/gomods/athens/pkg/download/mode" "github.com/gomods/athens/pkg/errors" "github.com/kelseyhightower/envconfig" - "gopkg.in/go-playground/validator.v9" ) const defaultConfigFile = "athens.toml" @@ -28,7 +28,8 @@ type Config struct { GoGetDir string `envconfig:"ATHENS_GOGET_DIR"` ProtocolWorkers int `validate:"required" envconfig:"ATHENS_PROTOCOL_WORKERS"` LogLevel string `validate:"required" envconfig:"ATHENS_LOG_LEVEL"` - CloudRuntime string `validate:"required" envconfig:"ATHENS_CLOUD_RUNTIME"` + LogFormat string `validate:"oneof='' 'json' 'plain'" envconfig:"ATHENS_LOG_FORMAT"` + CloudRuntime string `validate:"required_without=LogFormat" envconfig:"ATHENS_CLOUD_RUNTIME"` EnablePprof bool `envconfig:"ATHENS_ENABLE_PPROF"` PprofPort string `envconfig:"ATHENS_PPROF_PORT"` FilterFile string `envconfig:"ATHENS_FILTER_FILE"` @@ -150,6 +151,7 @@ func defaultConfig() *Config { GoGetWorkers: 10, ProtocolWorkers: 30, LogLevel: "debug", + LogFormat: "json", CloudRuntime: "none", EnablePprof: false, PprofPort: ":3001", diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 9cd31e0cf..fe3a7425f 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -258,6 +258,7 @@ func TestParseExampleConfig(t *testing.T) { expConf := &Config{ GoEnv: "development", LogLevel: "debug", + LogFormat: "json", GoBinary: "go", GoGetWorkers: 10, ProtocolWorkers: 30, diff --git a/pkg/log/format.go b/pkg/log/format.go index 30d64a462..bbddce44e 100644 --- a/pkg/log/format.go +++ b/pkg/log/format.go @@ -64,6 +64,10 @@ func sortFields(data logrus.Fields) []string { return keys } -func getDefaultFormatter() logrus.Formatter { +func parseFormat(format string) logrus.Formatter { + if format == "plain" { + return &logrus.TextFormatter{} + } + return &logrus.JSONFormatter{} } diff --git a/pkg/log/log.go b/pkg/log/log.go index 1139e2a56..d70d4bfcc 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -14,7 +14,7 @@ type Logger struct { // environment and the cloud platform it is // running on. TODO: take cloud arg and env // to construct the correct JSON formatter. -func New(cloudProvider string, level logrus.Level) *Logger { +func New(cloudProvider string, level logrus.Level, format string) *Logger { l := logrus.New() switch cloudProvider { case "GCP": @@ -22,7 +22,7 @@ func New(cloudProvider string, level logrus.Level) *Logger { case "none": l.Formatter = getDevFormatter() default: - l.Formatter = getDefaultFormatter() + l.Formatter = parseFormat(format) } l.Level = level return &Logger{Logger: l} diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index 64a864d95..2fe579982 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -14,6 +14,7 @@ import ( type input struct { name string cloudProvider string + format string level logrus.Level fields logrus.Fields logFunc func(e Entry) time.Time @@ -82,10 +83,10 @@ var testCases = []input{ output: `{"message":"warn message","severity":"warning","timestamp":"%v"}` + "\n", }, { - name: "default", - cloudProvider: "default", - level: logrus.DebugLevel, - fields: logrus.Fields{"xyz": "abc", "abc": "xyz"}, + name: "default json", + format: "json", + level: logrus.DebugLevel, + fields: logrus.Fields{"xyz": "abc", "abc": "xyz"}, logFunc: func(e Entry) time.Time { t := time.Now() e.Warnf("warn message") @@ -98,7 +99,7 @@ var testCases = []input{ func TestCloudLogger(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - lggr := New(tc.cloudProvider, tc.level) + lggr := New(tc.cloudProvider, tc.level, "") var buf bytes.Buffer lggr.Out = &buf e := lggr.WithFields(tc.fields) diff --git a/pkg/middleware/log_entry_test.go b/pkg/middleware/log_entry_test.go index 0f6a76dd2..2135748fd 100644 --- a/pkg/middleware/log_entry_test.go +++ b/pkg/middleware/log_entry_test.go @@ -24,7 +24,7 @@ func TestLogContext(t *testing.T) { r.HandleFunc("/test", h) var buf bytes.Buffer - lggr := log.New("", logrus.DebugLevel) + lggr := log.New("", logrus.DebugLevel, "") lggr.Formatter = &logrus.JSONFormatter{DisableTimestamp: true} lggr.Out = &buf