diff --git a/flags.go b/flags.go new file mode 100644 index 0000000..dd30b8d --- /dev/null +++ b/flags.go @@ -0,0 +1,17 @@ +package main + +import "flag" + +var ( + flagJsonLogging = flag.Bool("jsonlog", false, "If set, server logs messages as json objects") + flagLogLevel = flag.String( + "loglevel", + "info", + "Sets the logging level. One of (case insensitive) trace, debug, info, warn, error, fatal", + ) + flagAddr = flag.String("address", ":8080", "Set the address and port the server listens on") +) + +func init() { + flag.Parse() +} diff --git a/go.mod b/go.mod index 12894b2..5ce8ed3 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,14 @@ module git.mstar.dev/mstar/go-ember-template go 1.23.3 +require ( + github.com/rs/zerolog v1.33.0 + gitlab.com/mstarongitlab/goutils v1.5.1 +) + require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/rs/zerolog v1.33.0 // indirect + github.com/rs/xid v1.5.0 // indirect golang.org/x/sys v0.12.0 // indirect ) diff --git a/go.sum b/go.sum index 98afda4..ef4d8f1 100644 --- a/go.sum +++ b/go.sum @@ -6,9 +6,12 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= 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= +gitlab.com/mstarongitlab/goutils v1.5.1 h1:UlQL90DctJ7QbfJ5NOPheMK3PdFt6sBIjXR3fJpd3Ms= +gitlab.com/mstarongitlab/goutils v1.5.1/go.mod h1:f71xLeTv05GHiRHKkgDRXfxOPRkjXNteXqLZyg02xhs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= diff --git a/main.go b/main.go new file mode 100644 index 0000000..8b3d18e --- /dev/null +++ b/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "context" + "embed" + "io" + "net/http" + "os" + "os/signal" + "strings" + "syscall" + "time" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "gitlab.com/mstarongitlab/goutils/embedFsWrapper" + "gitlab.com/mstarongitlab/goutils/middleware" +) + +//go:embed frontend/dist +var frontendFS embed.FS + +func main() { + setLogger() + setLogLevel() + + serverHandler := http.NewServeMux() + serverHandler.Handle( + "/", + http.FileServerFS(embedFsWrapper.NewFSWrapper(frontendFS, "frontend/dist/")), + ) + // serverHandler := server.NewServer(embedFsWrapper.NewFSWrapper(frontendFS, "frontend/dist/")) + server := http.Server{ + Handler: middleware.ChainMiddlewares(serverHandler, middleware.LoggingMiddleware), + Addr: *flagAddr, + } + + // Setup exit notifications + exitSignalChannel := make(chan os.Signal, 2) + signal.Notify(exitSignalChannel, os.Interrupt, syscall.SIGTERM) + + // Start the server in a separate goroutine so that main can handle shutdown + go func() { + log.Info().Str("addr", server.Addr).Msg("Starting server") + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatal().Err(err).Msg("Server crashed!") + } + }() + + // Wait for outside signal to close the server and stop the app + <-exitSignalChannel + + // Close the server with a maximum timeout of 30 seconds + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + log.Info().Msg("Shutting down server") + err := server.Shutdown(ctx) + if err != nil { + log.Fatal().Err(err).Msg("Failed to cleanly stop server") + } + +} + +func setLogger(extraLogWriters ...io.Writer) { + if !*flagJsonLogging { + console := zerolog.ConsoleWriter{Out: os.Stderr} + log.Logger = zerolog.New(zerolog.MultiLevelWriter(append([]io.Writer{console}, extraLogWriters...)...)). + With(). + Timestamp(). + Logger() + } else { + log.Logger = zerolog.New(zerolog.MultiLevelWriter( + append([]io.Writer{log.Logger}, extraLogWriters...)..., + )).With().Timestamp().Logger() + } +} + +func setLogLevel() { + switch strings.ToLower(*flagLogLevel) { + case "trace": + zerolog.SetGlobalLevel(zerolog.TraceLevel) + case "debug": + zerolog.SetGlobalLevel(zerolog.DebugLevel) + case "info": + zerolog.SetGlobalLevel(zerolog.InfoLevel) + case "warn": + zerolog.SetGlobalLevel(zerolog.WarnLevel) + case "error": + zerolog.SetGlobalLevel(zerolog.ErrorLevel) + case "fatal": + zerolog.SetGlobalLevel(zerolog.FatalLevel) + default: + zerolog.SetGlobalLevel(zerolog.InfoLevel) + } + log.Info().Str("new-level", *flagLogLevel).Msg("New log level set") +}