diff --git a/generators.json b/generators.json index e4c610a..12b2f96 100644 --- a/generators.json +++ b/generators.json @@ -3,7 +3,7 @@ { "name": "Ambassador Labs Go Generator", "description": "Generates a new project for an API server writen in go", - "version": "0.0.1", + "version": "0.0.2", "languages": ["go"], "dir_name": "go" }] diff --git a/generators/go/base/internal/binary/handlers.go.template b/generators/go/base/internal/binary/handlers.go.template index 79bb1fa..7dd5104 100644 --- a/generators/go/base/internal/binary/handlers.go.template +++ b/generators/go/base/internal/binary/handlers.go.template @@ -1,24 +1,10 @@ package api import ( - "log" "net/http" "time" ) -// Handles returning a 404 to the client and logging a message for unsupported routes -func handle404(w http.ResponseWriter, r *http.Request) { - log.Printf("request to %s, path not found, method: %s\n", r.URL, r.Method) - http.NotFound(w, r) -} - -// Handles returning a simple about message -func handleAbout(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(" {{{ .ProjectName }}}: server generated by Ambassador Labs")) -} - - // responseWriter is a custom http.ResponseWriter that captures the status code. type responseWriter struct { http.ResponseWriter @@ -49,8 +35,19 @@ func (rw *responseWriter) Write(b []byte) (int, error) { return rw.ResponseWriter.Write(b) } +// Handles returning a 404 to the client and logging a message for unsupported routes +func (s *apiService) handle404(w http.ResponseWriter, r *http.Request) { + http.NotFound(w, r) +} + +// Handles returning a simple about message +func (s *apiService) handleAbout(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(" Sample Service: server generated by Ambassador Labs")) +} + // logMiddleware logs the request method, URL path, duration, and status code. -func logMiddleware(next http.Handler) http.Handler { +func (s *apiService) logMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() @@ -59,6 +56,6 @@ func logMiddleware(next http.Handler) http.Handler { next.ServeHTTP(wrappedWriter, r) // Log with the captured status code. - log.Printf("%s %s %d %s\n", r.Method, r.URL.Path, wrappedWriter.statusCode, time.Since(start)) + s.logger.Info().Msgf("%s %s %d %s", r.Method, r.URL.Path, wrappedWriter.statusCode, time.Since(start)) }) } diff --git a/generators/go/base/internal/binary/server.go.template b/generators/go/base/internal/binary/server.go.template index 953d314..61ecca1 100644 --- a/generators/go/base/internal/binary/server.go.template +++ b/generators/go/base/internal/binary/server.go.template @@ -2,25 +2,37 @@ package api import ( "context" - "log" "net/http" + "os" + "time" - "github.com/gorilla/mux" + "github.com/gorilla/mux" + "github.com/rs/zerolog" "golang.org/x/sync/errgroup" ctrl "sigs.k8s.io/controller-runtime" ) + type apiService struct { + logger zerolog.Logger addr string // TODO: optional k8s health checks } func NewAPIService() *apiService { + output := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + logger := zerolog.New(output).With().Timestamp().Logger() return &apiService{ - addr: ":8080", + addr: ":8080", + logger: logger, } } +func (s *apiService) WithLogger(logger zerolog.Logger) *apiService { + s.logger = logger + return s +} + func (s *apiService) WithAddr(addr string) *apiService { s.addr = addr return s @@ -28,7 +40,7 @@ func (s *apiService) WithAddr(addr string) *apiService { // Starts the main loop for the server which manages and spins up one or more sub servers that listen for requests func (s *apiService) Start() { - log.Println("{{{ .ProjectName }}} server is starting up") + s.logger.Info().Msg("{{{ .ProjectName }}} server is starting up") ctx := ctrl.SetupSignalHandler() g, gCtx := errgroup.WithContext(ctx) @@ -39,21 +51,21 @@ func (s *apiService) Start() { // Block here until shutdown signal err := g.Wait() if err != nil { - log.Printf("error occured starting {{{ .ProjectName }}} server: %s\n", err.Error()) + s.logger.Info().Msgf("error occured starting {{{ .ProjectName }}} server: %s", err.Error()) } - log.Println("{{{ .ProjectName }}} server shutting down...") + s.logger.Info().Msg("{{{ .ProjectName }}} server shutting down...") } // Starts the sub server for the api endpoints func (s *apiService) Serve(ctx context.Context) error { router := mux.NewRouter().StrictSlash(true) - router.HandleFunc("/", handle404) - router.HandleFunc("/about", handleAbout) + router.HandleFunc("/", s.handle404) + router.HandleFunc("/about", s.handleAbout) {{{ codeGenGorillaMux "router" }}} - loggedMux := logMiddleware(router) + loggedMux := s.logMiddleware(router) server := &http.Server{ Addr: s.addr, @@ -62,19 +74,19 @@ func (s *apiService) Serve(ctx context.Context) error { errChan := make(chan error) go func() { - log.Printf("starting {{{ .ProjectName }}} server, address: %s\n", s.addr) + s.logger.Info().Msgf("starting {{{ .ProjectName }}} server, address: %s", s.addr) errChan <- server.ListenAndServe() }() // wait for shut down or error to occur select { case <-ctx.Done(): - log.Println("{{{ .ProjectName }}} server graceful shutdown started") + s.logger.Info().Msg("{{{ .ProjectName }}} server graceful shutdown started") server.Shutdown(ctx) - log.Println("{{{ .ProjectName }}} server successfully shutdown") + s.logger.Info().Msg("{{{ .ProjectName }}} server successfully shutdown") return nil case err := <-errChan: - log.Printf("{{{ .ProjectName }}} server shutdown with error: %s\n", err.Error()) + s.logger.Info().Msgf("{{{ .ProjectName }}} server shutdown with error: %s", err.Error()) return err } } diff --git a/generators/go/generator-config.yaml b/generators/go/generator-config.yaml index 7342b3b..c02b373 100644 --- a/generators/go/generator-config.yaml +++ b/generators/go/generator-config.yaml @@ -1,7 +1,7 @@ metadata: name: "Ambassador Labs Go Generator" description: "Generates a new project for an API server writen in go" - version: "0.0.1" + version: "0.0.2" languages: ["go"] # Defines the base directory within the template folder.