diff --git a/go.mod b/go.mod index bce77c0..7fd583a 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/go-playground/validator/v10 v10.22.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/jackc/pgx v3.6.2+incompatible + github.com/rs/zerolog v1.33.0 github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.25.0 gopkg.in/yaml.v3 v3.0.1 @@ -32,6 +33,7 @@ require ( github.com/kr/pretty v0.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index 43e9afb..aafa458 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,7 @@ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -30,6 +31,7 @@ github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4 github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= @@ -59,6 +61,10 @@ 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.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -74,6 +80,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -99,8 +108,10 @@ golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/logger/event.go b/logger/event.go new file mode 100644 index 0000000..0422b8b --- /dev/null +++ b/logger/event.go @@ -0,0 +1,28 @@ +package logger + +import "github.com/rs/zerolog" + +type Event interface { + Err(err error) Event + Msg(msg string) + Msgf(format string, v ...interface{}) +} + +type event struct { + zerologEvent *zerolog.Event +} + +func (e event) Err(err error) Event { + e.zerologEvent = e.zerologEvent.Err(err) + return e +} + +// Never call it twice: event gets disposed after first call +func (e event) Msg(msg string) { + e.zerologEvent.Msg(msg) +} + +// Never call it twice: event gets disposed after first call +func (e event) Msgf(format string, v ...interface{}) { + e.zerologEvent.Msgf(format, v...) +} diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..633f6e8 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,30 @@ +package logger + +import "github.com/rs/zerolog" + +type Logger interface { + Log() Event + Warning() Event + Error() Event + Fatal() Event +} + +type logger struct { + zeroLogger *zerolog.Logger +} + +func (l logger) Log() Event { + return event{l.zeroLogger.Log()} +} + +func (l *logger) Warning() Event { + return event{l.zeroLogger.Warn()} +} + +func (l *logger) Error() Event { + return event{l.zeroLogger.Error()} +} + +func (l *logger) Fatal() Event { + return event{l.zeroLogger.Fatal()} +} diff --git a/logger/new.go b/logger/new.go new file mode 100644 index 0000000..8cda8d7 --- /dev/null +++ b/logger/new.go @@ -0,0 +1,47 @@ +package logger + +import ( + "io" + "os" + + "github.com/rs/zerolog" +) + +// type OutputStream int + +// const ( +// OutputStreamNone OutputStream = iota +// OutputStreamStderr +// OutputStreamStdout +// ) + +type NewLoggerOpts struct { + Debug bool + OutputFile string + // OutputStream OutputStream +} + +func New(opts NewLoggerOpts) (Logger, error) { + writers := []io.Writer{} + writers = append(writers, os.Stderr) + + if opts.OutputFile != "" { + file, err := os.OpenFile(opts.OutputFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0777) + if err != nil { + return nil, err + } + writers = append(writers, file) + } + + level := zerolog.TraceLevel + if opts.Debug { + level = zerolog.DebugLevel + } + + writer := io.MultiWriter(writers...) + + l := zerolog.New(writer).Level(level) + return &logger{ + zeroLogger: &l, + }, nil +} diff --git a/main.go b/main.go index f87ff5f..02765b0 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "backend/args_parser" "backend/config" + "backend/logger" "backend/src/handlers" "backend/src/middleware" "backend/src/models" @@ -22,27 +23,37 @@ import ( ) func main() { + debugMode := true + args, err := args_parser.Parse(os.Args) if err != nil { panic(err) } + logger, err := logger.New(logger.NewLoggerOpts{ + Debug: debugMode, + OutputFile: "./log.txt", + }) + if err != nil { + panic(err) + } + conf, err := config.NewFromFile(args.GetConfigPath()) if err != nil { - panic(err) + logger.Fatal().Err(err).Msg("failed parsing config file") } var key *rsa.PrivateKey { keyRawBytes, err := os.ReadFile(conf.GetJwtSigningKey()) if err != nil { - panic(err) + logger.Fatal().Err(err).Msg("failed reading signing key file") } keyPem, _ := pem.Decode(keyRawBytes) key, err = x509.ParsePKCS1PrivateKey(keyPem.Bytes) if err != nil { - panic(err) + logger.Fatal().Err(err).Msg("failed parsing signing key") } } @@ -51,12 +62,12 @@ func main() { pgConnStr := conf.GetPostgresUrl() connConf, err := pgx.ParseConnectionString(pgConnStr) if err != nil { - panic(err) + logger.Fatal().Err(err).Msg("failed parsing postgres connection string") } sqlDb := stdlib.OpenDB(connConf) if err := sqlDb.Ping(); err != nil { - panic(err) + logger.Fatal().Err(err).Msg("failed pinging postgres db") } } @@ -74,6 +85,10 @@ func main() { }, ) + if !debugMode { + gin.SetMode(gin.ReleaseMode) + } + r := gin.New() r.Use(gin.Logger()) r.Use(gin.Recovery())