Skip to content

Commit

Permalink
commands: Show server error info in browser
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed Oct 5, 2018
1 parent fae48d7 commit 7aead85
Show file tree
Hide file tree
Showing 24 changed files with 369 additions and 122 deletions.
85 changes: 82 additions & 3 deletions commands/commandeer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,27 @@
package commands

import (
"errors"
"fmt"

"os"
"path/filepath"
"regexp"
"strings"
"sync"
"time"

"github.com/gohugoio/hugo/livereload"

"github.com/gohugoio/hugo/config"

"github.com/spf13/cobra"

"github.com/spf13/afero"

"github.com/gohugoio/hugo/hugolib"
"github.com/spf13/afero"

"github.com/bep/debounce"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
Expand Down Expand Up @@ -72,6 +77,78 @@ type commandeer struct {

configured bool
paused bool

errorHandler *errorHandler
}

type errorHandler struct {
logger *loggers.Logger
sync.RWMutex
err *buildError
}

type buildError struct {
logger *loggers.Logger
What string
Err error
}

func (b buildError) log() {
b.logger.ERROR.Println(b.Error())
}

func (b buildError) Error() string {
return fmt.Sprintf("%s: %s", b.What, b.Err)
}

func (c *commandeer) getError() *buildError {
h := c.errorHandler
h.RLock()
defer h.RUnlock()
return h.err
}

func (c *commandeer) getErrorWithContext() interface{} {
h := c.errorHandler
h.RLock()
defer h.RUnlock()
if h.err == nil && h.logger.ErrorCounter.Count() == 0 {
return nil
}
m := make(map[string]interface{})

var err error

if h.logger.ErrorCounter.Count() > 0 {
err = &buildError{What: "Errors(s) in log", Err: errors.New(h.logger.Errors.String())}
} else {
err = h.err
}

m["Error"] = err
m["Version"] = hugoVersionString()

return m
}

func (c *commandeer) handleError(what string, err error) error {
h := c.errorHandler
h.Lock()
defer h.Unlock()

if err == nil {
h.err = nil
return nil
}

h.err = &buildError{logger: h.logger, What: what, Err: err}
h.err.log()

// TODO(bep) server error config
// Need to refresh the browser to show the error page.
livereload.ForceRefresh()

return h.err
}

func (c *commandeer) Set(key string, value interface{}) {
Expand Down Expand Up @@ -244,11 +321,13 @@ func (c *commandeer) loadConfig(mustHaveConfigFile, running bool) error {
}
}

logger, err := c.createLogger(config)
logger, err := c.createLogger(config, running)
if err != nil {
return err
}

c.errorHandler = &errorHandler{logger: logger}

cfg.Logger = logger

createMemFs := config.GetBool("renderToMemory")
Expand Down
28 changes: 2 additions & 26 deletions commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
package commands

import (
"os"

"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/helpers"
"github.com/spf13/cobra"
jww "github.com/spf13/jwalterweatherman"

"github.com/spf13/nitro"
)
Expand Down Expand Up @@ -242,7 +240,7 @@ func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) {
_ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"})
}

func checkErr(logger *jww.Notepad, err error, s ...string) {
func checkErr(logger *loggers.Logger, err error, s ...string) {
if err == nil {
return
}
Expand All @@ -255,25 +253,3 @@ func checkErr(logger *jww.Notepad, err error, s ...string) {
}
logger.ERROR.Println(err)
}

func stopOnErr(logger *jww.Notepad, err error, s ...string) {
if err == nil {
return
}

defer os.Exit(-1)

if len(s) == 0 {
newMessage := err.Error()
// Printing an empty string results in a error with
// no message, no bueno.
if newMessage != "" {
logger.CRITICAL.Println(newMessage)
}
}
for _, message := range s {
if message != "" {
logger.CRITICAL.Println(message)
}
}
}
26 changes: 15 additions & 11 deletions commands/hugo.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ import (
"os/signal"
"sort"
"sync/atomic"

"github.com/gohugoio/hugo/common/loggers"

"syscall"

"github.com/gohugoio/hugo/hugolib/filesystems"
"github.com/pkg/errors"

"golang.org/x/sync/errgroup"

"log"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -85,7 +88,7 @@ func Execute(args []string) Response {
}

if err == nil {
errCount := int(jww.LogCountForLevelsGreaterThanorEqualTo(jww.LevelError))
errCount := int(loggers.GlobalErrorCounter.Count())
if errCount > 0 {
err = fmt.Errorf("logged %d errors", errCount)
} else if resp.Result != nil {
Expand Down Expand Up @@ -118,7 +121,7 @@ func initializeConfig(mustHaveConfigFile, running bool,

}

func (c *commandeer) createLogger(cfg config.Provider) (*jww.Notepad, error) {
func (c *commandeer) createLogger(cfg config.Provider, running bool) (*loggers.Logger, error) {
var (
logHandle = ioutil.Discard
logThreshold = jww.LevelWarn
Expand Down Expand Up @@ -161,7 +164,7 @@ func (c *commandeer) createLogger(cfg config.Provider) (*jww.Notepad, error) {
jww.SetStdoutThreshold(stdoutThreshold)
helpers.InitLoggers()

return jww.NewNotepad(stdoutThreshold, logThreshold, outHandle, logHandle, "", log.Ldate|log.Ltime), nil
return loggers.NewLogger(stdoutThreshold, logThreshold, outHandle, logHandle, running), nil
}

func initializeFlags(cmd *cobra.Command, cfg config.Provider) {
Expand Down Expand Up @@ -637,17 +640,17 @@ func (c *commandeer) fullRebuild() {
c.commandeerHugoState = &commandeerHugoState{}
err := c.loadConfig(true, true)
if err != nil {
jww.ERROR.Println("Failed to reload config:", err)
c.handleError("Failed to reload config", errors.WithStack(err))
// Set the processing on pause until the state is recovered.
c.paused = true
} else {
c.paused = false
}

if !c.paused {
if err := c.buildSites(); err != nil {
jww.ERROR.Println(err)
} else if !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") {
err := c.buildSites()
c.handleError("Build failed", errors.WithStack(err))
if err == nil && !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") {
livereload.ForceRefresh()
}
}
Expand Down Expand Up @@ -839,11 +842,12 @@ func (c *commandeer) newWatcher(dirList ...string) (*watcher.Batcher, error) {
c.Logger.FEEDBACK.Printf("Syncing all static files\n")
_, err := c.copyStatic()
if err != nil {
stopOnErr(c.Logger, err, "Error copying static files to publish dir")
c.handleError("Error copying static files to publish dir", errors.WithStack(err))
break
}
} else {
if err := staticSyncer.syncsStaticEvents(staticEvents); err != nil {
c.Logger.ERROR.Println(err)
c.handleError("Error syncing static files to publish dir", errors.WithStack(err))
continue
}
}
Expand Down Expand Up @@ -917,7 +921,7 @@ func (c *commandeer) newWatcher(dirList ...string) (*watcher.Batcher, error) {
}
case err := <-watcher.Errors:
if err != nil {
c.Logger.ERROR.Println(err)
c.handleError("Error while watching", errors.WithStack(err))
}
}
}
Expand Down
34 changes: 26 additions & 8 deletions commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"time"

"github.com/gohugoio/hugo/livereload"
"github.com/gohugoio/hugo/tpl"

"github.com/gohugoio/hugo/config"

Expand Down Expand Up @@ -271,10 +272,11 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
}

type fileServer struct {
baseURLs []string
roots []string
c *commandeer
s *serverCmd
baseURLs []string
roots []string
errorTemplate tpl.Template
c *commandeer
s *serverCmd
}

func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, error) {
Expand Down Expand Up @@ -316,6 +318,16 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro

decorate := func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

// First check the error state
err := f.c.getErrorWithContext()
if err != nil {
errTemplate := defaultBuildErrorTemplate
w.WriteHeader(errTemplate.statusCode) // TODO(bep) error server improve
f.errorTemplate.Execute(w, err)
return
}

if f.s.noHTTPCache {
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0")
w.Header().Set("Pragma", "no-cache")
Expand Down Expand Up @@ -365,11 +377,17 @@ func (c *commandeer) serve(s *serverCmd) error {
roots = []string{""}
}

templ, err := c.hugo.TextTmpl.Parse("__server_error", defaultBuildErrorTemplate.templ)
if err != nil {
return err
}

srv := &fileServer{
baseURLs: baseURLs,
roots: roots,
c: c,
s: s,
baseURLs: baseURLs,
roots: roots,
c: c,
s: s,
errorTemplate: templ,
}

doLiveReload := !c.Cfg.GetBool("disableLiveReload")
Expand Down
Loading

0 comments on commit 7aead85

Please sign in to comment.