From 3ecf841a986a3aad909d86e716cfc1e9c5c05438 Mon Sep 17 00:00:00 2001 From: ybkuroki <45133652+ybkuroki@users.noreply.github.com> Date: Sun, 4 Oct 2020 16:49:16 +0900 Subject: [PATCH 1/6] Change Echo logger to Zap logger --- go.mod | 2 ++ go.sum | 29 +++++++++++++++++ logger/logger.go | 70 ++++++++++++++++++++-------------------- repository/repository.go | 6 ++-- service/account.go | 4 +-- service/book.go | 12 +++---- service/master.go | 4 +-- 7 files changed, 79 insertions(+), 48 deletions(-) diff --git a/go.mod b/go.mod index 553f7752..7c9a5e67 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,8 @@ require ( github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/stretchr/testify v1.6.1 github.com/valyala/fasttemplate v1.1.1 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.16.0 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect diff --git a/go.sum b/go.sum index 0a72cfe9..08941b03 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= @@ -58,8 +59,12 @@ github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +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/labstack/echo-contrib v0.9.0 h1:hKBA2SnxdxR7sghH0J04zq/pImnKRmgvmQ6MvY9hug4= github.com/labstack/echo-contrib v0.9.0/go.mod h1:TsFE5Vv0LRpZLoh4mMmaaAxzcTH+1CBFiUtVhwlegzU= github.com/labstack/echo/v4 v4.1.6/go.mod h1:kU/7PwzgNxZH4das4XNsSpBSOD09XIF5YEPzjpkGnGE= @@ -108,6 +113,7 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -129,21 +135,36 @@ github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.1.1 h1:o7HedfIt0u4jgkQnk0jkUOUI45c0CbFgcOOVUpo/txI= github.com/valyala/fasttemplate v1.1.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +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/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +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 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= @@ -172,7 +193,12 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -180,6 +206,8 @@ gopkg.in/boj/redistore.v1 v1.0.0-20160128113310-fc113767cd6b h1:U/Uqd1232+wrnHOv gopkg.in/boj/redistore.v1 v1.0.0-20160128113310-fc113767cd6b/go.mod h1:fgfIZMlsafAHpspcks2Bul+MWUNw/2dyQmjC2faKjtg= 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/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/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.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= @@ -192,3 +220,4 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/logger/logger.go b/logger/logger.go index 6156263e..3632be1d 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -3,24 +3,21 @@ package logger import ( "database/sql/driver" "fmt" - "io" - "os" "reflect" "regexp" - "strings" "time" "unicode" "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" "github.com/ybkuroki/go-webapp-sample/config" + "go.uber.org/zap" ) var logger *Logger // Logger is an alternative implementation of *gorm.Logger type Logger struct { - elogger echo.Logger + zap *zap.SugaredLogger } // GetLogger is return Logger @@ -28,53 +25,56 @@ func GetLogger() *Logger { return logger } -// GetEchoLogger is return echo's logger -func GetEchoLogger() echo.Logger { - return logger.elogger +// GetZapLogger returns zapSugaredLogger +func GetZapLogger() *zap.SugaredLogger { + return logger.zap } -// NewLogger create logger object for *gorm.DB from *echo.Logger -func newLogger(elog echo.Logger) *Logger { - return &Logger{elogger: elog} +// newLogger create logger object for *gorm.DB from *echo.Logger +func newLogger(zap *zap.SugaredLogger) *Logger { + return &Logger{zap: zap} } // InitLogger initialize logger. func InitLogger(e *echo.Echo, config *config.Config) { - // logging for each request. - e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ - Format: strings.Replace(config.Log.Format, "${level}", "INFO", 1) + "\n", - })) + zap, err := zap.NewDevelopment() + if err != nil { + fmt.Printf("Error") + } + defer zap.Sync() + sugar := zap.Sugar() + // set package varriable logger. + logger = newLogger(sugar) + + e.Use(RequestLoggerMiddleware) + // logging for the start and end of controller processes. // ref: https://echo.labstack.com/guide/customization - e.Use(MyLoggerMiddleware) - - // set logformat for echo logger. - e.Logger.SetHeader(config.Log.Format) - e.Logger.SetLevel(config.Log.Level) + e.Use(ActionLoggerMiddleware) +} - // if the log file exists, write both console and the log file. - if config.Log.FilePath != "" { - logfile, err := os.OpenFile(config.Log.FilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 066) - if err != nil { - panic("Cannot open the log file. Please check this file path. Path: " + config.Log.FilePath + ", Error: " + err.Error()) +// RequestLoggerMiddleware is middleware for logging the contents of requests. +func RequestLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + req := c.Request() + res := c.Response() + if err := next(c); err != nil { + c.Error(err) } - - e.Logger.SetOutput(io.MultiWriter(logfile, os.Stdout)) + GetZapLogger().Infof("Uri: %s, Method: %s, Status: %d", req.RequestURI, req.Method, res.Status) + return nil } - - // set package varriable logger. - logger = newLogger(e.Logger) } -// MyLoggerMiddleware is middleware for logging the start and end of controller processes. +// ActionLoggerMiddleware is middleware for logging the start and end of controller processes. // ref: https://echo.labstack.com/cookbook/middleware -func MyLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { +func ActionLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { - c.Logger().Debug(c.Path() + " Action Start") + GetZapLogger().Debug(c.Path() + " Action Start") if err := next(c); err != nil { c.Error(err) } - c.Logger().Debug(c.Path() + " Action End") + GetZapLogger().Debugf(c.Path() + " Action End") return nil } } @@ -94,7 +94,7 @@ func (l *Logger) Print(values ...interface{}) { func (l *Logger) Println(values []interface{}) { sql := createLog(values) if sql != "" { - l.elogger.Debug(sql) + l.zap.Debugf(sql) } } diff --git a/repository/repository.go b/repository/repository.go index a336554b..41f7152a 100644 --- a/repository/repository.go +++ b/repository/repository.go @@ -38,13 +38,13 @@ func getConnection(config *config.Config) string { // InitDB initialize a database connection. func InitDB() { - logger.GetEchoLogger().Info("Try database connection") + logger.GetZapLogger().Infof("Try database connection") conf := config.GetConfig() db, err := gorm.Open(conf.Database.Dialect, getConnection(conf)) if err != nil { - logger.GetEchoLogger().Error("Failure database connection") + logger.GetZapLogger().Errorf("Failure database connection") } - logger.GetEchoLogger().Info(fmt.Sprintf("Success database connection, %s:%s", conf.Database.Host, conf.Database.Port)) + logger.GetZapLogger().Infof("Success database connection, %s:%s", conf.Database.Host, conf.Database.Port) db.LogMode(true) db.SetLogger(logger.GetLogger()) rep = &Repository{} diff --git a/service/account.go b/service/account.go index 4a57145e..98caf284 100644 --- a/service/account.go +++ b/service/account.go @@ -13,12 +13,12 @@ func AuthenticateByUsernameAndPassword(username string, password string) (bool, account := model.Account{} result, err := account.FindByName(rep, username) if err != nil { - logger.GetEchoLogger().Error(err) + logger.GetZapLogger().Errorf(err.Error()) return false, nil } if err := bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(password)); err != nil { - logger.GetEchoLogger().Error(err) + logger.GetZapLogger().Errorf(err.Error()) return false, nil } diff --git a/service/book.go b/service/book.go index 81d05d15..ebece1f3 100644 --- a/service/book.go +++ b/service/book.go @@ -13,7 +13,7 @@ func FindAllBooks() *[]model.Book { book := model.Book{} result, err := book.FindAll(rep) if err != nil { - logger.GetEchoLogger().Error(err.Error) + logger.GetZapLogger().Errorf(err.Error()) return nil } return result @@ -25,7 +25,7 @@ func FindAllBooksByPage(page int, size int) *model.Page { book := model.Book{} result, err := book.FindAllByPage(rep, page, size) if err != nil { - logger.GetEchoLogger().Error(err.Error) + logger.GetZapLogger().Errorf(err.Error()) return nil } return result @@ -37,7 +37,7 @@ func FindBooksByTitle(title string, page int, size int) *model.Page { book := model.Book{} result, err := book.FindByTitle(rep, title, page, size) if err != nil { - logger.GetEchoLogger().Error(err.Error) + logger.GetZapLogger().Errorf(err.Error()) return nil } return result @@ -73,7 +73,7 @@ func RegisterBook(dto *dto.RegBookDto) (*model.Book, map[string]string) { }) if err != nil { - logger.GetEchoLogger().Error(err) + logger.GetZapLogger().Errorf(err.Error()) return nil, map[string]string{"error": "transaction error"} } @@ -123,7 +123,7 @@ func EditBook(dto *dto.ChgBookDto) (*model.Book, map[string]string) { }) if err != nil { - logger.GetEchoLogger().Error(err) + logger.GetZapLogger().Errorf(err.Error()) return nil, map[string]string{"error": "transaction error"} } @@ -158,7 +158,7 @@ func DeleteBook(dto *dto.ChgBookDto) (*model.Book, map[string]string) { }) if err != nil { - logger.GetEchoLogger().Error(err) + logger.GetZapLogger().Errorf(err.Error()) return nil, map[string]string{"error": "transaction error"} } diff --git a/service/master.go b/service/master.go index 960bfa30..aa5859b6 100644 --- a/service/master.go +++ b/service/master.go @@ -12,7 +12,7 @@ func FindAllCategories() *[]model.Category { category := model.Category{} result, err := category.FindAll(rep) if err != nil { - logger.GetEchoLogger().Error(err.Error) + logger.GetZapLogger().Errorf(err.Error()) return nil } return result @@ -24,7 +24,7 @@ func FindAllFormats() *[]model.Format { format := model.Format{} result, err := format.FindAll(rep) if err != nil { - logger.GetEchoLogger().Error(err.Error) + logger.GetZapLogger().Errorf(err.Error()) return nil } return result From 9ebdcc4a844a55c8933fb7118802d942b57f1f9f Mon Sep 17 00:00:00 2001 From: ybkuroki <45133652+ybkuroki@users.noreply.github.com> Date: Sun, 11 Oct 2020 17:20:24 +0900 Subject: [PATCH 2/6] #25 Fix logging for request error --- controller/error.go | 5 +- logger/logger.go | 35 +----------- main.go | 7 ++- middleware/middleware.go | 116 +++++++++++++++++++++++++++++++++++++++ session/session.go | 80 +++------------------------ test/unittest_util.go | 7 ++- 6 files changed, 135 insertions(+), 115 deletions(-) create mode 100644 middleware/middleware.go diff --git a/controller/error.go b/controller/error.go index a57411c3..12edb2b6 100644 --- a/controller/error.go +++ b/controller/error.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/labstack/echo/v4" + "github.com/ybkuroki/go-webapp-sample/logger" ) // APIError represents @@ -31,8 +32,8 @@ func JSONErrorHandler(err error, c echo.Context) { if !c.Response().Committed { if err := c.JSON(code, apierr); err != nil { - c.Logger().Error(err) + logger.GetZapLogger().Errorf(err.Error()) } } - c.Logger().Debug(err) + logger.GetZapLogger().Debugf(err.Error()) } diff --git a/logger/logger.go b/logger/logger.go index 3632be1d..d2c9fc35 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -8,7 +8,6 @@ import ( "time" "unicode" - "github.com/labstack/echo/v4" "github.com/ybkuroki/go-webapp-sample/config" "go.uber.org/zap" ) @@ -36,7 +35,7 @@ func newLogger(zap *zap.SugaredLogger) *Logger { } // InitLogger initialize logger. -func InitLogger(e *echo.Echo, config *config.Config) { +func InitLogger(config *config.Config) { zap, err := zap.NewDevelopment() if err != nil { fmt.Printf("Error") @@ -45,38 +44,6 @@ func InitLogger(e *echo.Echo, config *config.Config) { sugar := zap.Sugar() // set package varriable logger. logger = newLogger(sugar) - - e.Use(RequestLoggerMiddleware) - - // logging for the start and end of controller processes. - // ref: https://echo.labstack.com/guide/customization - e.Use(ActionLoggerMiddleware) -} - -// RequestLoggerMiddleware is middleware for logging the contents of requests. -func RequestLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - req := c.Request() - res := c.Response() - if err := next(c); err != nil { - c.Error(err) - } - GetZapLogger().Infof("Uri: %s, Method: %s, Status: %d", req.RequestURI, req.Method, res.Status) - return nil - } -} - -// ActionLoggerMiddleware is middleware for logging the start and end of controller processes. -// ref: https://echo.labstack.com/cookbook/middleware -func ActionLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - GetZapLogger().Debug(c.Path() + " Action Start") - if err := next(c); err != nil { - c.Error(err) - } - GetZapLogger().Debugf(c.Path() + " Action End") - return nil - } } // ============================================================== diff --git a/main.go b/main.go index 1022ce0a..b1b08e4a 100644 --- a/main.go +++ b/main.go @@ -4,17 +4,18 @@ import ( "github.com/labstack/echo/v4" "github.com/ybkuroki/go-webapp-sample/config" "github.com/ybkuroki/go-webapp-sample/logger" + "github.com/ybkuroki/go-webapp-sample/middleware" "github.com/ybkuroki/go-webapp-sample/migration" "github.com/ybkuroki/go-webapp-sample/repository" "github.com/ybkuroki/go-webapp-sample/router" - "github.com/ybkuroki/go-webapp-sample/session" ) func main() { e := echo.New() config.Load() - logger.InitLogger(e, config.GetConfig()) + logger.InitLogger(config.GetConfig()) + middleware.InitLoggerMiddleware(e) e.Logger.Info("Loaded this configuration : application." + *config.GetEnv() + ".yml") repository.InitDB() @@ -24,7 +25,7 @@ func main() { migration.InitMasterData(config.GetConfig()) router.Init(e, config.GetConfig()) - session.Init(e, config.GetConfig()) + middleware.InitSessionMiddleware(e, config.GetConfig()) if err := e.Start(":8080"); err != nil { e.Logger.Error(err) } diff --git a/middleware/middleware.go b/middleware/middleware.go new file mode 100644 index 00000000..97149c34 --- /dev/null +++ b/middleware/middleware.go @@ -0,0 +1,116 @@ +package middleware + +import ( + "fmt" + "net/http" + "regexp" + + "github.com/gorilla/sessions" + "github.com/labstack/echo-contrib/session" + "github.com/labstack/echo/v4" + "github.com/ybkuroki/go-webapp-sample/config" + "github.com/ybkuroki/go-webapp-sample/logger" + mySession "github.com/ybkuroki/go-webapp-sample/session" + "gopkg.in/boj/redistore.v1" +) + +// InitLoggerMiddleware initialize a middleware for logger. +func InitLoggerMiddleware(e *echo.Echo) { + e.Use(RequestLoggerMiddleware) + e.Use(ActionLoggerMiddleware) +} + +// InitSessionMiddleware initialize a middleware for session management. +func InitSessionMiddleware(e *echo.Echo, conf *config.Config) { + if conf.Extension.SecurityEnabled { + if conf.Redis.Enabled { + logger.GetZapLogger().Infof("Try redis connection") + address := fmt.Sprintf("%s:%s", conf.Redis.Host, conf.Redis.Port) + store, err := redistore.NewRediStore(conf.Redis.ConnectionPoolSize, "tcp", address, "", []byte("secret")) + if err != nil { + logger.GetZapLogger().Errorf("Failure redis connection") + } + e.Use(session.Middleware(store)) + logger.GetZapLogger().Infof(fmt.Sprintf("Success redis connection, %s", address)) + } else { + e.Use(session.Middleware(sessions.NewCookieStore([]byte("secret")))) + } + e.Use(AuthenticationMiddleware(conf)) + } +} + +// RequestLoggerMiddleware is middleware for logging the contents of requests. +func RequestLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + req := c.Request() + res := c.Response() + if err := next(c); err != nil { + c.Error(err) + } + if account := mySession.GetAccount(c); account != nil { + logger.GetZapLogger().Infof("Uri: %s, Method: %s, Status: %d, AccountName: %s", req.RequestURI, req.Method, res.Status, account.Name) + } else { + logger.GetZapLogger().Infof("Uri: %s, Method: %s, Status: %d, AccountName: %s", req.RequestURI, req.Method, res.Status, "None") + } + return nil + } +} + +// ActionLoggerMiddleware is middleware for logging the start and end of controller processes. +// ref: https://echo.labstack.com/cookbook/middleware +func ActionLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + logger.GetZapLogger().Debug(c.Path() + " Action Start") + if err := next(c); err != nil { + c.Error(err) + } + logger.GetZapLogger().Debugf(c.Path() + " Action End") + return nil + } +} + +// AuthenticationMiddleware is the middleware of session authentication for echo. +func AuthenticationMiddleware(conf *config.Config) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if !hasAuthorization(c, conf) { + return c.JSON(http.StatusUnauthorized, false) + } + if err := next(c); err != nil { + c.Error(err) + } + return nil + } + } +} + +// hasAuthorization judges whether the user has the right to access the path. +func hasAuthorization(c echo.Context, conf *config.Config) bool { + currentPath := c.Path() + if equalPath(currentPath, conf.Security.ExculdePath) { + return true + } + account := mySession.GetAccount(c) + if account == nil { + return false + } + if account.Authority.Name == "Admin" && equalPath(currentPath, conf.Security.AdminPath) { + _ = mySession.Save(c) + return true + } + if account.Authority.Name == "User" && equalPath(currentPath, conf.Security.UserPath) { + _ = mySession.Save(c) + return true + } + return false +} + +// equalPath judges whether a given path contains in the path list. +func equalPath(cpath string, paths []string) bool { + for i := range paths { + if regexp.MustCompile(paths[i]).Match([]byte(cpath)) { + return true + } + } + return false +} diff --git a/session/session.go b/session/session.go index 586f7b29..a3a99bd4 100644 --- a/session/session.go +++ b/session/session.go @@ -2,16 +2,12 @@ package session import ( "encoding/json" - "fmt" "net/http" - "regexp" "github.com/gorilla/sessions" "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" - "github.com/ybkuroki/go-webapp-sample/config" "github.com/ybkuroki/go-webapp-sample/model" - "gopkg.in/boj/redistore.v1" ) const ( @@ -21,71 +17,6 @@ const ( Account = "Account" ) -// Init initialize session authentication. -func Init(e *echo.Echo, conf *config.Config) { - if conf.Extension.SecurityEnabled { - if conf.Redis.Enabled { - e.Logger.Info("Try redis connection") - address := fmt.Sprintf("%s:%s", conf.Redis.Host, conf.Redis.Port) - store, err := redistore.NewRediStore(conf.Redis.ConnectionPoolSize, "tcp", address, "", []byte("secret")) - if err != nil { - e.Logger.Error("Failure redis connection") - } - e.Use(session.Middleware(store)) - e.Logger.Info(fmt.Sprintf("Success redis connection, %s", address)) - } else { - e.Use(session.Middleware(sessions.NewCookieStore([]byte("secret")))) - } - e.Use(AuthenticationMiddleware(conf)) - } -} - -// AuthenticationMiddleware is the middleware of session authentication for echo. -func AuthenticationMiddleware(conf *config.Config) echo.MiddlewareFunc { - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if !hasAuthorization(c, conf) { - return c.JSON(http.StatusUnauthorized, false) - } - if err := next(c); err != nil { - c.Error(err) - } - return nil - } - } -} - -// hasAuthorization judges whether the user has the right to access the path. -func hasAuthorization(c echo.Context, conf *config.Config) bool { - currentPath := c.Path() - if equalPath(currentPath, conf.Security.ExculdePath) { - return true - } - account := GetAccount(c) - if account == nil { - return false - } - if account.Authority.Name == "Admin" && equalPath(currentPath, conf.Security.AdminPath) { - _ = Save(c) - return true - } - if account.Authority.Name == "User" && equalPath(currentPath, conf.Security.UserPath) { - _ = Save(c) - return true - } - return false -} - -// equalPath judges whether a given path contains in the path list. -func equalPath(cpath string, paths []string) bool { - for i := range paths { - if regexp.MustCompile(paths[i]).Match([]byte(cpath)) { - return true - } - } - return false -} - // Get returns a session for the current request. func Get(c echo.Context) *sessions.Session { sess, _ := session.Get(sessionStr, c) @@ -134,10 +65,13 @@ func SetValue(c echo.Context, key string, value interface{}) error { // GetValue returns value of session. func GetValue(c echo.Context, key string) string { sess := Get(c) - v := sess.Values[key] - data, result := v.(string) - if result && data != "null" { - return data + if sess != nil { + if v, ok := sess.Values[key]; ok { + data, result := v.(string) + if result && data != "null" { + return data + } + } } return "" } diff --git a/test/unittest_util.go b/test/unittest_util.go index 8530d4d1..306703e9 100644 --- a/test/unittest_util.go +++ b/test/unittest_util.go @@ -6,9 +6,9 @@ import ( "github.com/labstack/echo/v4" "github.com/ybkuroki/go-webapp-sample/config" "github.com/ybkuroki/go-webapp-sample/logger" + "github.com/ybkuroki/go-webapp-sample/middleware" "github.com/ybkuroki/go-webapp-sample/migration" "github.com/ybkuroki/go-webapp-sample/repository" - "github.com/ybkuroki/go-webapp-sample/session" ) // Prepare func is to prepare for unit test. @@ -25,14 +25,15 @@ func Prepare() *echo.Echo { conf.Log.Level = 1 config.SetConfig(conf) - logger.InitLogger(e, config.GetConfig()) + logger.InitLogger(config.GetConfig()) + middleware.InitLoggerMiddleware(e) repository.InitDB() migration.CreateDatabase(config.GetConfig()) migration.InitMasterData(config.GetConfig()) - session.Init(e, config.GetConfig()) + middleware.InitSessionMiddleware(e, config.GetConfig()) return e } From ddaa78166b892ccc4a018f18bd616cf34fd3f40b Mon Sep 17 00:00:00 2001 From: ybkuroki <45133652+ybkuroki@users.noreply.github.com> Date: Sat, 24 Oct 2020 16:56:51 +0900 Subject: [PATCH 3/6] #25 Create logger configuration --- go.mod | 2 +- logger/logger.go | 15 +++++++++++++-- main.go | 2 +- middleware/middleware.go | 4 ++-- test/unittest_util.go | 2 +- zaplogger.develop.yml | 18 ++++++++++++++++++ zaplogger.docker.yml | 20 ++++++++++++++++++++ zaplogger.k8s.yml | 20 ++++++++++++++++++++ 8 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 zaplogger.develop.yml create mode 100644 zaplogger.docker.yml create mode 100644 zaplogger.k8s.yml diff --git a/go.mod b/go.mod index 7c9a5e67..7a9ad5c4 100644 --- a/go.mod +++ b/go.mod @@ -26,5 +26,5 @@ require ( gopkg.in/boj/redistore.v1 v1.0.0-20160128113310-fc113767cd6b gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.31.0 - gopkg.in/yaml.v2 v2.2.8 // indirect + gopkg.in/yaml.v2 v2.2.8 ) diff --git a/logger/logger.go b/logger/logger.go index d2c9fc35..c57515f9 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -3,6 +3,7 @@ package logger import ( "database/sql/driver" "fmt" + "io/ioutil" "reflect" "regexp" "time" @@ -10,6 +11,7 @@ import ( "github.com/ybkuroki/go-webapp-sample/config" "go.uber.org/zap" + "gopkg.in/yaml.v2" ) var logger *Logger @@ -35,8 +37,16 @@ func newLogger(zap *zap.SugaredLogger) *Logger { } // InitLogger initialize logger. -func InitLogger(config *config.Config) { - zap, err := zap.NewDevelopment() +func InitLogger() { + configYaml, err := ioutil.ReadFile("./zaplogger." + *config.GetEnv() + ".yml") + if err != nil { + fmt.Printf("Failed to read zap logger configuration: %s", err) + } + var myConfig zap.Config + if err := yaml.Unmarshal(configYaml, &myConfig); err != nil { + fmt.Printf("Failed to read zap logger configuration: %s", err) + } + zap, err := myConfig.Build() if err != nil { fmt.Printf("Error") } @@ -44,6 +54,7 @@ func InitLogger(config *config.Config) { sugar := zap.Sugar() // set package varriable logger. logger = newLogger(sugar) + logger.zap.Infof("Success to read zap logger configuration") } // ============================================================== diff --git a/main.go b/main.go index b1b08e4a..7c264f23 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ func main() { e := echo.New() config.Load() - logger.InitLogger(config.GetConfig()) + logger.InitLogger() middleware.InitLoggerMiddleware(e) e.Logger.Info("Loaded this configuration : application." + *config.GetEnv() + ".yml") diff --git a/middleware/middleware.go b/middleware/middleware.go index 97149c34..6ce202f1 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -48,9 +48,9 @@ func RequestLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { c.Error(err) } if account := mySession.GetAccount(c); account != nil { - logger.GetZapLogger().Infof("Uri: %s, Method: %s, Status: %d, AccountName: %s", req.RequestURI, req.Method, res.Status, account.Name) + logger.GetZapLogger().Infof("%s %s %s %d", account.Name, req.RequestURI, req.Method, res.Status) } else { - logger.GetZapLogger().Infof("Uri: %s, Method: %s, Status: %d, AccountName: %s", req.RequestURI, req.Method, res.Status, "None") + logger.GetZapLogger().Infof("%s %s %s %d", "None", req.RequestURI, req.Method, res.Status) } return nil } diff --git a/test/unittest_util.go b/test/unittest_util.go index 306703e9..207e1a25 100644 --- a/test/unittest_util.go +++ b/test/unittest_util.go @@ -25,7 +25,7 @@ func Prepare() *echo.Echo { conf.Log.Level = 1 config.SetConfig(conf) - logger.InitLogger(config.GetConfig()) + logger.InitLogger() middleware.InitLoggerMiddleware(e) repository.InitDB() diff --git a/zaplogger.develop.yml b/zaplogger.develop.yml new file mode 100644 index 00000000..2587c029 --- /dev/null +++ b/zaplogger.develop.yml @@ -0,0 +1,18 @@ +level: "debug" +encoding: "console" +development: true +encoderConfig: + messageKey: "Msg" + levelKey: "Level" + timeKey: "Time" + nameKey: "Name" + callerKey: "Caller" + stacktraceKey: "St" + levelEncoder: "capital" + timeEncoder: "iso8601" + durationEncoder: "string" + callerEncoder: "short" +outputPaths: + - "stdout" +errorOutputPaths: + - "stdout" diff --git a/zaplogger.docker.yml b/zaplogger.docker.yml new file mode 100644 index 00000000..30cb9eed --- /dev/null +++ b/zaplogger.docker.yml @@ -0,0 +1,20 @@ +level: "info" +encoding: "console" +development: true +encoderConfig: + messageKey: "Msg" + levelKey: "Level" + timeKey: "Time" + nameKey: "Name" + callerKey: "Caller" + stacktraceKey: "St" + levelEncoder: "capital" + timeEncoder: "iso8601" + durationEncoder: "string" + callerEncoder: "short" +outputPaths: + - "stdout" + - "./application.log" +errorOutputPaths: + - "stderr" + - "./error.log" diff --git a/zaplogger.k8s.yml b/zaplogger.k8s.yml new file mode 100644 index 00000000..30cb9eed --- /dev/null +++ b/zaplogger.k8s.yml @@ -0,0 +1,20 @@ +level: "info" +encoding: "console" +development: true +encoderConfig: + messageKey: "Msg" + levelKey: "Level" + timeKey: "Time" + nameKey: "Name" + callerKey: "Caller" + stacktraceKey: "St" + levelEncoder: "capital" + timeEncoder: "iso8601" + durationEncoder: "string" + callerEncoder: "short" +outputPaths: + - "stdout" + - "./application.log" +errorOutputPaths: + - "stderr" + - "./error.log" From c7c91bedecd240620b0b7ba5c317ab9b7585246b Mon Sep 17 00:00:00 2001 From: ybkuroki <45133652+ybkuroki@users.noreply.github.com> Date: Sun, 25 Oct 2020 16:39:45 +0900 Subject: [PATCH 4/6] #25 Create request log format --- application.develop.yml | 4 +--- application.docker.yml | 4 +--- application.k8s.yml | 4 +--- config/config.go | 5 +---- go.mod | 3 +-- go.sum | 10 ++++++++-- logger/logger.go | 2 +- main.go | 4 ++-- middleware/middleware.go | 32 ++++++++++++++++++++++++++------ test/unittest_util.go | 3 +-- 10 files changed, 43 insertions(+), 28 deletions(-) diff --git a/application.develop.yml b/application.develop.yml index 3e69f3e2..892be33b 100644 --- a/application.develop.yml +++ b/application.develop.yml @@ -13,9 +13,7 @@ extension: security_enabled: true log: - format: ${time_rfc3339} [${level}] ${remote_ip} ${method} ${uri} ${status} - level: 1 - file_path: + request_log_format: ${remote_ip} ${account_name} ${uri} ${method} ${status} security: exclude_path: diff --git a/application.docker.yml b/application.docker.yml index 20e3af61..45bb6a59 100644 --- a/application.docker.yml +++ b/application.docker.yml @@ -13,9 +13,7 @@ extension: security_enabled: true log: - format: ${time_rfc3339} [${level}] ${remote_ip} ${method} ${uri} ${status} - level: 2 - file_path: ./application.log + request_log_format: ${remote_ip} ${account_name} ${uri} ${method} ${status} security: exclude_path: diff --git a/application.k8s.yml b/application.k8s.yml index 9def68dc..145cb4bf 100644 --- a/application.k8s.yml +++ b/application.k8s.yml @@ -19,9 +19,7 @@ extension: security_enabled: true log: - format: ${time_rfc3339} [${level}] ${remote_ip} ${method} ${uri} ${status} - level: 2 - file_path: ./application.log + request_log_format: ${remote_ip} ${account_name} ${uri} ${method} ${status} security: exclude_path: diff --git a/config/config.go b/config/config.go index cc7cf43f..97df283b 100644 --- a/config/config.go +++ b/config/config.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/jinzhu/configor" - "github.com/labstack/gommon/log" ) // Config represents the composition of yml settings. @@ -31,9 +30,7 @@ type Config struct { SecurityEnabled bool `yaml:"security_enabled" default:"false"` } Log struct { - Format string `default:"${time_rfc3339} [${level}] ${remote_ip} ${method} ${uri} ${status}"` - Level log.Lvl `default:"2"` - FilePath string `yaml:"file_path"` + RequestLogFormat string `yaml:"request_log_format" default:"${remote_ip} ${account_name} ${uri} ${method} ${status}"` } Security struct { ExculdePath []string `yaml:"exclude_path"` diff --git a/go.mod b/go.mod index 7a9ad5c4..f1203ea0 100644 --- a/go.mod +++ b/go.mod @@ -10,13 +10,12 @@ require ( github.com/jinzhu/gorm v1.9.12 github.com/labstack/echo-contrib v0.9.0 github.com/labstack/echo/v4 v4.1.16 - github.com/labstack/gommon v0.3.0 github.com/leodido/go-urn v1.2.0 // indirect github.com/lib/pq v1.7.0 // indirect github.com/mattn/go-colorable v0.1.7 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/stretchr/testify v1.6.1 - github.com/valyala/fasttemplate v1.1.1 // indirect + github.com/valyala/fasttemplate v1.2.1 go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.16.0 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 diff --git a/go.sum b/go.sum index 08941b03..b293649a 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,10 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/labstack/echo-contrib v0.9.0 h1:hKBA2SnxdxR7sghH0J04zq/pImnKRmgvmQ6MvY9hug4= github.com/labstack/echo-contrib v0.9.0/go.mod h1:TsFE5Vv0LRpZLoh4mMmaaAxzcTH+1CBFiUtVhwlegzU= @@ -132,8 +134,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4= github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.1.1 h1:o7HedfIt0u4jgkQnk0jkUOUI45c0CbFgcOOVUpo/txI= -github.com/valyala/fasttemplate v1.1.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -156,6 +158,7 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAak golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -197,6 +200,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 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 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= @@ -206,6 +210,7 @@ gopkg.in/boj/redistore.v1 v1.0.0-20160128113310-fc113767cd6b h1:U/Uqd1232+wrnHOv gopkg.in/boj/redistore.v1 v1.0.0-20160128113310-fc113767cd6b/go.mod h1:fgfIZMlsafAHpspcks2Bul+MWUNw/2dyQmjC2faKjtg= 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/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 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/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= @@ -220,4 +225,5 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/logger/logger.go b/logger/logger.go index c57515f9..2bc579cf 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -54,7 +54,7 @@ func InitLogger() { sugar := zap.Sugar() // set package varriable logger. logger = newLogger(sugar) - logger.zap.Infof("Success to read zap logger configuration") + logger.zap.Infof("Success to read zap logger configuration: zaplogger." + *config.GetEnv() + ".yml") } // ============================================================== diff --git a/main.go b/main.go index 7c264f23..83c8dfa0 100644 --- a/main.go +++ b/main.go @@ -16,7 +16,7 @@ func main() { config.Load() logger.InitLogger() middleware.InitLoggerMiddleware(e) - e.Logger.Info("Loaded this configuration : application." + *config.GetEnv() + ".yml") + logger.GetZapLogger().Infof("Loaded this configuration : application." + *config.GetEnv() + ".yml") repository.InitDB() db := repository.GetDB() @@ -27,7 +27,7 @@ func main() { router.Init(e, config.GetConfig()) middleware.InitSessionMiddleware(e, config.GetConfig()) if err := e.Start(":8080"); err != nil { - e.Logger.Error(err) + logger.GetZapLogger().Errorf(err.Error()) } defer db.Close() diff --git a/middleware/middleware.go b/middleware/middleware.go index 6ce202f1..eeb2e9de 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -2,12 +2,15 @@ package middleware import ( "fmt" + "io" "net/http" "regexp" + "strconv" "github.com/gorilla/sessions" "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" + "github.com/valyala/fasttemplate" "github.com/ybkuroki/go-webapp-sample/config" "github.com/ybkuroki/go-webapp-sample/logger" mySession "github.com/ybkuroki/go-webapp-sample/session" @@ -47,11 +50,28 @@ func RequestLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { if err := next(c); err != nil { c.Error(err) } - if account := mySession.GetAccount(c); account != nil { - logger.GetZapLogger().Infof("%s %s %s %d", account.Name, req.RequestURI, req.Method, res.Status) - } else { - logger.GetZapLogger().Infof("%s %s %s %d", "None", req.RequestURI, req.Method, res.Status) - } + + template := fasttemplate.New(config.GetConfig().Log.RequestLogFormat, "${", "}") + logstr := template.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { + switch tag { + case "remote_ip": + return w.Write([]byte(c.RealIP())) + case "account_name": + if account := mySession.GetAccount(c); account != nil { + return w.Write([]byte(account.Name)) + } + return w.Write([]byte("None")) + case "uri": + return w.Write([]byte(req.RequestURI)) + case "method": + return w.Write([]byte(req.Method)) + case "status": + return w.Write([]byte(strconv.Itoa(res.Status))) + default: + return w.Write([]byte("")) + } + }) + logger.GetZapLogger().Debugf(logstr) return nil } } @@ -60,7 +80,7 @@ func RequestLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { // ref: https://echo.labstack.com/cookbook/middleware func ActionLoggerMiddleware(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { - logger.GetZapLogger().Debug(c.Path() + " Action Start") + logger.GetZapLogger().Debugf(c.Path() + " Action Start") if err := next(c); err != nil { c.Error(err) } diff --git a/test/unittest_util.go b/test/unittest_util.go index 207e1a25..01bb6de5 100644 --- a/test/unittest_util.go +++ b/test/unittest_util.go @@ -21,8 +21,7 @@ func Prepare() *echo.Echo { conf.Database.Migration = true conf.Extension.MasterGenerator = true conf.Extension.SecurityEnabled = false - conf.Log.Format = "${time_rfc3339} [${level}] ${remote_ip} ${method} ${uri} ${status}" - conf.Log.Level = 1 + conf.Log.RequestLogFormat = "${remote_ip} ${account_name} ${uri} ${method} ${status}" config.SetConfig(conf) logger.InitLogger() From 9fb8fc6f6d9b9c7003acc7f2b28654484a2fbeab Mon Sep 17 00:00:00 2001 From: ybkuroki <45133652+ybkuroki@users.noreply.github.com> Date: Sun, 25 Oct 2020 16:51:17 +0900 Subject: [PATCH 5/6] polish --- logger/logger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logger/logger.go b/logger/logger.go index 2bc579cf..a322ee46 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -50,11 +50,11 @@ func InitLogger() { if err != nil { fmt.Printf("Error") } - defer zap.Sync() sugar := zap.Sugar() // set package varriable logger. logger = newLogger(sugar) logger.zap.Infof("Success to read zap logger configuration: zaplogger." + *config.GetEnv() + ".yml") + _ = zap.Sync() } // ============================================================== From 7091a99ab9f51719f3b1f21e006426cf37b245a6 Mon Sep 17 00:00:00 2001 From: ybkuroki <45133652+ybkuroki@users.noreply.github.com> Date: Sat, 31 Oct 2020 16:45:41 +0900 Subject: [PATCH 6/6] polish --- logger/logger.go | 9 +++++++-- test/unittest_util.go | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/logger/logger.go b/logger/logger.go index a322ee46..93b1d18b 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -26,13 +26,18 @@ func GetLogger() *Logger { return logger } +// SetLogger sets logger +func SetLogger(log *Logger) { + logger = log +} + // GetZapLogger returns zapSugaredLogger func GetZapLogger() *zap.SugaredLogger { return logger.zap } // newLogger create logger object for *gorm.DB from *echo.Logger -func newLogger(zap *zap.SugaredLogger) *Logger { +func NewLogger(zap *zap.SugaredLogger) *Logger { return &Logger{zap: zap} } @@ -52,7 +57,7 @@ func InitLogger() { } sugar := zap.Sugar() // set package varriable logger. - logger = newLogger(sugar) + logger = NewLogger(sugar) logger.zap.Infof("Success to read zap logger configuration: zaplogger." + *config.GetEnv() + ".yml") _ = zap.Sync() } diff --git a/test/unittest_util.go b/test/unittest_util.go index 01bb6de5..1dab2f78 100644 --- a/test/unittest_util.go +++ b/test/unittest_util.go @@ -2,6 +2,7 @@ package test import ( "encoding/json" + "fmt" "github.com/labstack/echo/v4" "github.com/ybkuroki/go-webapp-sample/config" @@ -9,6 +10,8 @@ import ( "github.com/ybkuroki/go-webapp-sample/middleware" "github.com/ybkuroki/go-webapp-sample/migration" "github.com/ybkuroki/go-webapp-sample/repository" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) // Prepare func is to prepare for unit test. @@ -24,7 +27,7 @@ func Prepare() *echo.Echo { conf.Log.RequestLogFormat = "${remote_ip} ${account_name} ${uri} ${method} ${status}" config.SetConfig(conf) - logger.InitLogger() + initTestLogger() middleware.InitLoggerMiddleware(e) repository.InitDB() @@ -36,6 +39,40 @@ func Prepare() *echo.Echo { return e } +func initTestLogger() { + level := zap.NewAtomicLevel() + level.SetLevel(zapcore.DebugLevel) + + myConfig := zap.Config{ + Level: level, + Encoding: "console", + Development: true, + EncoderConfig: zapcore.EncoderConfig{ + TimeKey: "Time", + LevelKey: "Level", + NameKey: "Name", + CallerKey: "Caller", + MessageKey: "Msg", + StacktraceKey: "St", + EncodeLevel: zapcore.CapitalLevelEncoder, + EncodeTime: zapcore.ISO8601TimeEncoder, + EncodeDuration: zapcore.StringDurationEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + }, + OutputPaths: []string{"stdout"}, + ErrorOutputPaths: []string{"stderr"}, + } + zap, err := myConfig.Build() + if err != nil { + fmt.Printf("Error") + } + sugar := zap.Sugar() + log := logger.NewLogger(sugar) + logger.SetLogger(log) + logger.GetZapLogger().Infof("Success to construct zap logger.") + _ = zap.Sync() +} + // ConvertToString func is convert model to string. func ConvertToString(model interface{}) string { bytes, _ := json.Marshal(model)