Skip to content

Commit

Permalink
Replace the old log setup, with structured logging etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed Jun 17, 2023
1 parent aaf2e96 commit 728ad44
Show file tree
Hide file tree
Showing 79 changed files with 1,089 additions and 939 deletions.
5 changes: 2 additions & 3 deletions cache/filecache/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ package filecache_test
import (
"path/filepath"

jww "github.com/spf13/jwalterweatherman"

"testing"
"time"

"github.com/bep/logg"
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/htesting"
"github.com/gohugoio/hugo/hugolib"
Expand Down Expand Up @@ -80,7 +79,7 @@ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAA
`

b := hugolib.NewIntegrationTestBuilder(
hugolib.IntegrationTestConfig{T: t, TxtarString: files, Running: true, RunGC: true, NeedsOsFS: true, LogLevel: jww.LevelInfo},
hugolib.IntegrationTestConfig{T: t, TxtarString: files, Running: true, RunGC: true, NeedsOsFS: true, LogLevel: logg.LevelInfo},
).Build()

b.Assert(b.GCCount, qt.Equals, 0)
Expand Down
65 changes: 37 additions & 28 deletions commands/commandeer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ import (
"syscall"
"time"

jww "github.com/spf13/jwalterweatherman"

"go.uber.org/automaxprocs/maxprocs"

"github.com/bep/clock"
"github.com/bep/lazycache"
"github.com/bep/logg"
"github.com/bep/overlayfs"
"github.com/bep/simplecobra"

Expand Down Expand Up @@ -93,7 +92,8 @@ type rootCommand struct {
Println func(a ...interface{})
Out io.Writer

logger loggers.Logger
logger loggers.Logger
loggerDistinct loggers.Logger

// The main cache busting key for the caches below.
configVersionID atomic.Int32
Expand Down Expand Up @@ -405,52 +405,61 @@ func (r *rootCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
}
_, running := runner.Command.(*serverCommand)
var err error
r.logger, err = r.createLogger(running)
l1, l2, err := r.createBaseLoggers(running)
if err != nil {
return err
}
r.logger = l1
r.loggerDistinct = l2

loggers.PanicOnWarning.Store(r.panicOnWarning)
// TODO1 loggers.PanicOnWarning.Store(r.panicOnWarning)
r.commonConfigs = lazycache.New[int32, *commonConfig](lazycache.Options{MaxEntries: 5})
r.hugoSites = lazycache.New[int32, *hugolib.HugoSites](lazycache.Options{MaxEntries: 5})

return nil
}

func (r *rootCommand) createLogger(running bool) (loggers.Logger, error) {
var (
outHandle = r.Out
stdoutThreshold = jww.LevelWarn
)

if r.verbose {
helpers.Deprecated("--verbose", "use --logLevel info", false)
stdoutThreshold = jww.LevelInfo
}

if r.debug {
helpers.Deprecated("--debug", "use --logLevel debug", false)
stdoutThreshold = jww.LevelDebug
}
func (r *rootCommand) createBaseLoggers(running bool) (loggers.Logger, loggers.Logger, error) {
level := logg.LevelWarn

if r.logLevel != "" {
switch strings.ToLower(r.logLevel) {
case "debug":
stdoutThreshold = jww.LevelDebug
level = logg.LevelDebug
case "info":
stdoutThreshold = jww.LevelInfo
level = logg.LevelInfo
case "warn", "warning":
stdoutThreshold = jww.LevelWarn
level = logg.LevelWarn
case "error":
stdoutThreshold = jww.LevelError
level = logg.LevelError
default:
return nil, fmt.Errorf("invalid log level: %q, must be one of debug, warn, info or error", r.logLevel)
return nil, nil, fmt.Errorf("invalid log level: %q, must be one of debug, warn, info or error", r.logLevel)
}
} else {
if r.verbose {
helpers.Deprecated("--verbose", "use --logLevel info", false)
level = logg.LevelInfo
}

if r.debug {
helpers.Deprecated("--debug", "use --logLevel debug", false)
level = logg.LevelDebug
}
}

optsLogger := loggers.Options{
Level: level,
Stdout: r.Out,
Stderr: r.Out,
StoreErrors: running,
}

loggers.InitGlobalLogger(stdoutThreshold, jww.LevelWarn, outHandle, io.Discard)
helpers.InitLoggers()
return loggers.NewLogger(stdoutThreshold, jww.LevelWarn, outHandle, io.Discard, running), nil
optsLoggerDistinct := optsLogger
optsLoggerDistinct.Distinct = true

l1, l2 := loggers.New(optsLogger), loggers.New(optsLoggerDistinct)
return l1, l2, nil

}

func (r *rootCommand) Reset() {
Expand Down
2 changes: 1 addition & 1 deletion commands/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ documentation.
if err != nil {
return err
}
deployer, err := deploy.New(h.Configs.GetFirstLanguageConfig(), h.PathSpec.PublishFs)
deployer, err := deploy.New(h.Configs.GetFirstLanguageConfig(), h.Log, h.PathSpec.PublishFs)
if err != nil {
return err
}
Expand Down
13 changes: 8 additions & 5 deletions commands/hugobuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"sync"
"time"

"github.com/bep/logg"
"github.com/bep/simplecobra"
"github.com/fsnotify/fsnotify"
"github.com/gohugoio/hugo/common/herrors"
Expand Down Expand Up @@ -131,7 +132,7 @@ func (e *hugoBuilderErrState) wasErr() bool {
}

func (c *hugoBuilder) errCount() int {
return int(c.r.logger.LogCounters().ErrorCounter.Count())
return c.r.logger.LoggCount(logg.LevelError)
}

// getDirList provides NewWatcher() with a list of directories to watch for changes.
Expand Down Expand Up @@ -363,7 +364,7 @@ func (c *hugoBuilder) newWatcher(pollIntervalStr string, dirList ...string) (*wa
configFiles = conf.configs.LoadingInfo.ConfigFiles
})

c.r.logger.Println("Watching for config changes in", strings.Join(configFiles, ", "))
c.r.Println("Watching for config changes in", strings.Join(configFiles, ", "))
for _, configFile := range configFiles {
watcher.Add(configFile)
configSet[configFile] = true
Expand Down Expand Up @@ -461,6 +462,7 @@ func (c *hugoBuilder) copyStatic() (map[string]uint64, error) {
}

func (c *hugoBuilder) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint64, error) {
infol := c.r.logger.InfoCommand("copy static")
publishDir := helpers.FilePathSeparator

if sourceFs.PublishFolder != "" {
Expand All @@ -484,13 +486,13 @@ func (c *hugoBuilder) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint
syncer.SrcFs = fs

if syncer.Delete {
c.r.logger.Infoln("removing all files from destination that don't exist in static dirs")
infol.Logf("removing all files from destination that don't exist in static dirs")

syncer.DeleteFilter = func(f os.FileInfo) bool {
return f.IsDir() && strings.HasPrefix(f.Name(), ".")
}
}
c.r.logger.Infoln("syncing static files to", publishDir)
infol.Logf("syncing static files to %s", publishDir)

// because we are using a baseFs (to get the union right).
// set sync src to root
Expand Down Expand Up @@ -548,6 +550,7 @@ func (c *hugoBuilder) fullBuild(noBuildLock bool) error {
if !c.r.quiet {
fmt.Println("Start building sites … ")
fmt.Println(hugo.BuildVersionString())
fmt.Println()
if terminal.IsTerminal(os.Stdout) {
defer func() {
fmt.Print(showCursor + clearLine)
Expand Down Expand Up @@ -746,7 +749,7 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
return
}

c.r.logger.Infoln("Received System Events:", evs)
c.r.logger.Println("Received System Events:", evs)

staticEvents := []fsnotify.Event{}
dynamicEvents := []fsnotify.Event{}
Expand Down
11 changes: 5 additions & 6 deletions commands/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ import (
"errors"
"fmt"
"io"
"log"
"os"
"path/filepath"
"regexp"

jww "github.com/spf13/jwalterweatherman"

"strconv"
"strings"
"time"
Expand Down Expand Up @@ -299,7 +298,7 @@ func (c *importCommand) convertJekyllMetaData(m any, postName string, postDate t
}

func (c *importCommand) convertJekyllPost(path, relPath, targetDir string, draft bool) error {
jww.TRACE.Println("Converting", path)
log.Println("Converting", path)

filename := filepath.Base(path)
postDate, postName, err := c.parseJekyllFilename(filename)
Expand All @@ -308,7 +307,7 @@ func (c *importCommand) convertJekyllPost(path, relPath, targetDir string, draft
return nil
}

jww.TRACE.Println(filename, postDate, postName)
log.Println(filename, postDate, postName)

targetFile := filepath.Join(targetDir, relPath)
targetParentDir := filepath.Dir(targetFile)
Expand Down Expand Up @@ -367,7 +366,7 @@ func (c *importCommand) copyJekyllFilesAndFolders(jekyllRoot, dest string, jekyl
if _, ok := jekyllPostDirs[entry.Name()]; !ok {
err = hugio.CopyDir(fs, sfp, dfp, nil)
if err != nil {
jww.ERROR.Println(err)
c.r.logger.Errorln(err)
}
}
}
Expand All @@ -388,7 +387,7 @@ func (c *importCommand) copyJekyllFilesAndFolders(jekyllRoot, dest string, jekyl
if !isExcept && entry.Name()[0] != '.' && entry.Name()[0] != '_' {
err = hugio.CopyFile(fs, sfp, dfp)
if err != nil {
jww.ERROR.Println(err)
c.r.logger.Errorln(err)
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,8 @@ func (c *serverCommand) getErrorWithContext() any {

m := make(map[string]any)

//xwm["Error"] = errors.New(cleanErrorLog(removeErrorPrefixFromLog(c.r.logger.Errors())))
m["Error"] = errors.New(cleanErrorLog(removeErrorPrefixFromLog(c.r.logger.Errors())))
m["Error"] = c.r.logger.Errors()

m["Version"] = hugo.BuildVersionString()
ferrors := herrors.UnwrapFileErrorsWithErrorContext(c.errState.buildErr())
m["Files"] = ferrors
Expand Down Expand Up @@ -861,6 +861,10 @@ func (c *serverCommand) serve() error {
return err
}

// We need the server to share the same logger as the Hugo build (for error counts etc.)
c.r.logger = h.Log
c.r.loggerDistinct = h.LogDistinct

if isMultiHost {
for _, l := range conf.configs.ConfigLangs() {
baseURLs = append(baseURLs, l.BaseURL().String())
Expand Down Expand Up @@ -1066,8 +1070,7 @@ func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
}
})

// prevent spamming the log on changes
logger := helpers.NewDistinctErrorLogger()
logger := s.c.r.loggerDistinct

for _, ev := range staticEvents {
// Due to our approach of layering both directories and the content's rendered output
Expand Down
107 changes: 107 additions & 0 deletions common/loggers/defaulthandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2023 The Hugo Authors. All rights reserved.
// Some functions in this file (see comments) is based on the Go source code,
// copyright The Go Authors and governed by a BSD-style license.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// package loggers contains some basic logging setup.
package loggers

import (
"fmt"
"io"
"sync"

"github.com/bep/logg"

"github.com/fatih/color"
)

var bold = color.New(color.Bold)

// Colors mapping.
var Colors = [...]*color.Color{
logg.LevelDebug: color.New(color.FgWhite),
logg.LevelInfo: color.New(color.FgBlue),
logg.LevelWarn: color.New(color.FgYellow),
logg.LevelError: color.New(color.FgRed),
}

// Strings mapping.
var Strings = [...]string{
logg.LevelDebug: "[debug]",
logg.LevelInfo: "[info] ",
logg.LevelWarn: "[warn]]",
logg.LevelError: "[error]",
}

// newDefaultHandler handler.
func newDefaultHandler(outWriter, errWriter io.Writer) logg.Handler {
return &defaultHandler{
outWriter: outWriter,
errWriter: errWriter,
Padding: 0,
}
}

// Default Handler implementation.
// Based on https://github.com/apex/log/blob/master/handlers/cli/cli.go
type defaultHandler struct {
mu sync.Mutex
outWriter io.Writer // Defaults to os.Stdout.
errWriter io.Writer // Defaults to os.Stderr.

Padding int
}

// HandleLog implements logg.Handler.
func (h *defaultHandler) HandleLog(e *logg.Entry) error {
color := Colors[e.Level]
level := Strings[e.Level]

h.mu.Lock()
defer h.mu.Unlock()

var w io.Writer
if e.Level > logg.LevelInfo {
w = h.errWriter
} else {
w = h.outWriter
}

const cmdName = "cmd"

var prefix string
for _, field := range e.Fields {
if field.Name == cmdName {
prefix = fmt.Sprint(field.Value)
break
}
}

if prefix != "" {
prefix = prefix + ": "
}

color.Fprintf(w, "%s %s%s", bold.Sprintf("%*s", h.Padding+1, level), color.Sprint(prefix), e.Message)

for _, field := range e.Fields {
if field.Name == cmdName {
continue
}
fmt.Fprintf(w, " %s %v", color.Sprint(field.Name), field.Value)
}

fmt.Fprintln(w)

return nil
}
Loading

0 comments on commit 728ad44

Please sign in to comment.