Allow getJSON errors to be ignored

This change is mostly motivated to get a more stable CI build (we're building the Hugo site there, with Instagram and Twitter shortcodes sometimes failing).

Fixes #7866
This commit is contained in:
Bjørn Erik Pedersen 2020-10-21 11:17:48 +02:00
parent 8cbe2bbfad
commit fdfa4a5fe6
52 changed files with 318 additions and 221 deletions

View file

@ -72,6 +72,6 @@ script:
HUGO_TIMEOUT=30000 mage -v check; HUGO_TIMEOUT=30000 mage -v check;
fi fi
- mage -v hugo - mage -v hugo
- ./hugo -s docs/ - HUGO_IGNOREERRORS=error-remote-getjson ./hugo -s docs/
- ./hugo --renderToMemory -s docs/ - HUGO_IGNOREERRORS=error-remote-getjson ./hugo --renderToMemory -s docs/
- df -h - df -h

View file

@ -60,7 +60,7 @@ type commandeerHugoState struct {
type commandeer struct { type commandeer struct {
*commandeerHugoState *commandeerHugoState
logger *loggers.Logger logger loggers.Logger
serverConfig *config.Server serverConfig *config.Server
// Currently only set when in "fast render mode". But it seems to // Currently only set when in "fast render mode". But it seems to
@ -112,7 +112,7 @@ func (c *commandeerHugoState) hugo() *hugolib.HugoSites {
} }
func (c *commandeer) errCount() int { func (c *commandeer) errCount() int {
return int(c.logger.ErrorCounter.Count()) return int(c.logger.LogCounters().ErrorCounter.Count())
} }
func (c *commandeer) getErrorWithContext() interface{} { func (c *commandeer) getErrorWithContext() interface{} {
@ -415,7 +415,7 @@ func (c *commandeer) loadConfig(mustHaveConfigFile, running bool) error {
} }
config.Set("cacheDir", cacheDir) config.Set("cacheDir", cacheDir)
cfg.Logger.INFO.Println("Using config file:", config.ConfigFileUsed()) cfg.Logger.Infoln("Using config file:", config.ConfigFileUsed())
return nil return nil

View file

@ -322,16 +322,12 @@ func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) {
_ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"}) _ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"})
} }
func checkErr(logger *loggers.Logger, err error, s ...string) { func checkErr(logger loggers.Logger, err error, s ...string) {
if err == nil { if err == nil {
return return
} }
if len(s) == 0 {
logger.CRITICAL.Println(err)
return
}
for _, message := range s { for _, message := range s {
logger.ERROR.Println(message) logger.Errorln(message)
} }
logger.ERROR.Println(err) logger.Errorln(err)
} }

View file

@ -123,7 +123,7 @@ func (cc *convertCmd) convertContents(format metadecoders.Format) error {
site := h.Sites[0] site := h.Sites[0]
site.Log.FEEDBACK.Println("processing", len(site.AllPages()), "content files") site.Log.Println("processing", len(site.AllPages()), "content files")
for _, p := range site.AllPages() { for _, p := range site.AllPages() {
if err := cc.convertAndSavePage(p, site, format); err != nil { if err := cc.convertAndSavePage(p, site, format); err != nil {
return err return err
@ -147,19 +147,19 @@ func (cc *convertCmd) convertAndSavePage(p page.Page, site *hugolib.Site, target
errMsg := fmt.Errorf("Error processing file %q", p.Path()) errMsg := fmt.Errorf("Error processing file %q", p.Path())
site.Log.INFO.Println("Attempting to convert", p.File().Filename()) site.Log.Infoln("Attempting to convert", p.File().Filename())
f := p.File() f := p.File()
file, err := f.FileInfo().Meta().Open() file, err := f.FileInfo().Meta().Open()
if err != nil { if err != nil {
site.Log.ERROR.Println(errMsg) site.Log.Errorln(errMsg)
file.Close() file.Close()
return nil return nil
} }
pf, err := pageparser.ParseFrontMatterAndContent(file) pf, err := pageparser.ParseFrontMatterAndContent(file)
if err != nil { if err != nil {
site.Log.ERROR.Println(errMsg) site.Log.Errorln(errMsg)
file.Close() file.Close()
return err return err
} }
@ -179,7 +179,7 @@ func (cc *convertCmd) convertAndSavePage(p page.Page, site *hugolib.Site, target
var newContent bytes.Buffer var newContent bytes.Buffer
err = parser.InterfaceToFrontMatter(pf.FrontMatter, targetFormat, &newContent) err = parser.InterfaceToFrontMatter(pf.FrontMatter, targetFormat, &newContent)
if err != nil { if err != nil {
site.Log.ERROR.Println(errMsg) site.Log.Errorln(errMsg)
return err return err
} }

View file

@ -130,7 +130,7 @@ func initializeConfig(mustHaveConfigFile, running bool,
} }
func (c *commandeer) createLogger(cfg config.Provider, running bool) (*loggers.Logger, error) { func (c *commandeer) createLogger(cfg config.Provider, running bool) (loggers.Logger, error) {
var ( var (
logHandle = ioutil.Discard logHandle = ioutil.Discard
logThreshold = jww.LevelWarn logThreshold = jww.LevelWarn
@ -374,12 +374,12 @@ func (c *commandeer) initMemProfile() {
f, err := os.Create(c.h.memprofile) f, err := os.Create(c.h.memprofile)
if err != nil { if err != nil {
c.logger.ERROR.Println("could not create memory profile: ", err) c.logger.Errorf("could not create memory profile: ", err)
} }
defer f.Close() defer f.Close()
runtime.GC() // get up-to-date statistics runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f); err != nil { if err := pprof.WriteHeapProfile(f); err != nil {
c.logger.ERROR.Println("could not write memory profile: ", err) c.logger.Errorf("could not write memory profile: ", err)
} }
} }
@ -518,7 +518,7 @@ func (c *commandeer) build() error {
if createCounter, ok := c.destinationFs.(hugofs.DuplicatesReporter); ok { if createCounter, ok := c.destinationFs.(hugofs.DuplicatesReporter); ok {
dupes := createCounter.ReportDuplicates() dupes := createCounter.ReportDuplicates()
if dupes != "" { if dupes != "" {
c.logger.WARN.Println("Duplicate target paths:", dupes) c.logger.Warnln("Duplicate target paths:", dupes)
} }
} }
} }
@ -532,8 +532,8 @@ func (c *commandeer) build() error {
baseWatchDir := c.Cfg.GetString("workingDir") baseWatchDir := c.Cfg.GetString("workingDir")
rootWatchDirs := getRootWatchDirsStr(baseWatchDir, watchDirs) rootWatchDirs := getRootWatchDirsStr(baseWatchDir, watchDirs)
c.logger.FEEDBACK.Printf("Watching for changes in %s%s{%s}\n", baseWatchDir, helpers.FilePathSeparator, rootWatchDirs) c.logger.Printf("Watching for changes in %s%s{%s}\n", baseWatchDir, helpers.FilePathSeparator, rootWatchDirs)
c.logger.FEEDBACK.Println("Press Ctrl+C to stop") c.logger.Println("Press Ctrl+C to stop")
watcher, err := c.newWatcher(watchDirs...) watcher, err := c.newWatcher(watchDirs...)
checkErr(c.Logger, err) checkErr(c.Logger, err)
defer watcher.Close() defer watcher.Close()
@ -590,7 +590,7 @@ func (c *commandeer) doWithPublishDirs(f func(sourceFs *filesystems.SourceFilesy
staticFilesystems := c.hugo().BaseFs.SourceFilesystems.Static staticFilesystems := c.hugo().BaseFs.SourceFilesystems.Static
if len(staticFilesystems) == 0 { if len(staticFilesystems) == 0 {
c.logger.INFO.Println("No static directories found to sync") c.logger.Infoln("No static directories found to sync")
return langCount, nil return langCount, nil
} }
@ -662,13 +662,13 @@ func (c *commandeer) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint6
syncer.Delete = c.Cfg.GetBool("cleanDestinationDir") syncer.Delete = c.Cfg.GetBool("cleanDestinationDir")
if syncer.Delete { if syncer.Delete {
c.logger.INFO.Println("removing all files from destination that don't exist in static dirs") c.logger.Infoln("removing all files from destination that don't exist in static dirs")
syncer.DeleteFilter = func(f os.FileInfo) bool { syncer.DeleteFilter = func(f os.FileInfo) bool {
return f.IsDir() && strings.HasPrefix(f.Name(), ".") return f.IsDir() && strings.HasPrefix(f.Name(), ".")
} }
} }
c.logger.INFO.Println("syncing static files to", publishDir) c.logger.Infoln("syncing static files to", publishDir)
// because we are using a baseFs (to get the union right). // because we are using a baseFs (to get the union right).
// set sync src to root // set sync src to root
@ -689,7 +689,7 @@ func (c *commandeer) firstPathSpec() *helpers.PathSpec {
func (c *commandeer) timeTrack(start time.Time, name string) { func (c *commandeer) timeTrack(start time.Time, name string) {
elapsed := time.Since(start) elapsed := time.Since(start)
c.logger.FEEDBACK.Printf("%s in %v ms", name, int(1000*elapsed.Seconds())) c.logger.Printf("%s in %v ms", name, int(1000*elapsed.Seconds()))
} }
// getDirList provides NewWatcher() with a list of directories to watch for changes. // getDirList provides NewWatcher() with a list of directories to watch for changes.
@ -698,7 +698,7 @@ func (c *commandeer) getDirList() ([]string, error) {
walkFn := func(path string, fi hugofs.FileMetaInfo, err error) error { walkFn := func(path string, fi hugofs.FileMetaInfo, err error) error {
if err != nil { if err != nil {
c.logger.ERROR.Println("walker: ", err) c.logger.Errorln("walker: ", err)
return nil return nil
} }
@ -724,7 +724,7 @@ func (c *commandeer) getDirList() ([]string, error) {
w := hugofs.NewWalkway(hugofs.WalkwayConfig{Logger: c.logger, Info: fi, WalkFn: walkFn}) w := hugofs.NewWalkway(hugofs.WalkwayConfig{Logger: c.logger, Info: fi, WalkFn: walkFn})
if err := w.Walk(); err != nil { if err := w.Walk(); err != nil {
c.logger.ERROR.Println("walker: ", err) c.logger.Errorln("walker: ", err)
} }
} }
@ -740,8 +740,8 @@ func (c *commandeer) buildSites() (err error) {
func (c *commandeer) handleBuildErr(err error, msg string) { func (c *commandeer) handleBuildErr(err error, msg string) {
c.buildErr = err c.buildErr = err
c.logger.ERROR.Print(msg + ":\n\n") c.logger.Errorln(msg + ":\n")
c.logger.ERROR.Println(helpers.FirstUpper(err.Error())) c.logger.Errorln(helpers.FirstUpper(err.Error()))
if !c.h.quiet && c.h.verbose { if !c.h.quiet && c.h.verbose {
herrors.PrintStackTraceFromErr(err) herrors.PrintStackTraceFromErr(err)
} }
@ -822,13 +822,13 @@ func (c *commandeer) fullRebuild(changeType string) {
if !c.paused { if !c.paused {
_, err := c.copyStatic() _, err := c.copyStatic()
if err != nil { if err != nil {
c.logger.ERROR.Println(err) c.logger.Errorln(err)
return return
} }
err = c.buildSites() err = c.buildSites()
if err != nil { if err != nil {
c.logger.ERROR.Println(err) c.logger.Errorln(err)
} else if !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") { } else if !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") {
livereload.ForceRefresh() livereload.ForceRefresh()
} }
@ -862,7 +862,7 @@ func (c *commandeer) newWatcher(dirList ...string) (*watcher.Batcher, error) {
// Identifies changes to config (config.toml) files. // Identifies changes to config (config.toml) files.
configSet := make(map[string]bool) configSet := make(map[string]bool)
c.logger.FEEDBACK.Println("Watching for config changes in", strings.Join(c.configFiles, ", ")) c.logger.Println("Watching for config changes in", strings.Join(c.configFiles, ", "))
for _, configFile := range c.configFiles { for _, configFile := range c.configFiles {
watcher.Add(configFile) watcher.Add(configFile)
configSet[configFile] = true configSet[configFile] = true
@ -879,7 +879,7 @@ func (c *commandeer) newWatcher(dirList ...string) (*watcher.Batcher, error) {
} }
case err := <-watcher.Errors: case err := <-watcher.Errors:
if err != nil { if err != nil {
c.logger.ERROR.Println("Error while watching:", err) c.logger.Errorln("Error while watching:", err)
} }
} }
} }
@ -895,9 +895,9 @@ func (c *commandeer) printChangeDetected(typ string) {
} }
msg += " detected, rebuilding site." msg += " detected, rebuilding site."
c.logger.FEEDBACK.Println(msg) c.logger.Println(msg)
const layout = "2006-01-02 15:04:05.000 -0700" const layout = "2006-01-02 15:04:05.000 -0700"
c.logger.FEEDBACK.Println(time.Now().Format(layout)) c.logger.Println(time.Now().Format(layout))
} }
const ( const (
@ -979,7 +979,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
return return
} }
c.logger.INFO.Println("Received System Events:", evs) c.logger.Infoln("Received System Events:", evs)
staticEvents := []fsnotify.Event{} staticEvents := []fsnotify.Event{}
dynamicEvents := []fsnotify.Event{} dynamicEvents := []fsnotify.Event{}
@ -1059,7 +1059,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
walkAdder := func(path string, f hugofs.FileMetaInfo, err error) error { walkAdder := func(path string, f hugofs.FileMetaInfo, err error) error {
if f.IsDir() { if f.IsDir() {
c.logger.FEEDBACK.Println("adding created directory to watchlist", path) c.logger.Println("adding created directory to watchlist", path)
if err := watcher.Add(path); err != nil { if err := watcher.Add(path); err != nil {
return err return err
} }
@ -1091,15 +1091,15 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
c.printChangeDetected("Static files") c.printChangeDetected("Static files")
if c.Cfg.GetBool("forceSyncStatic") { if c.Cfg.GetBool("forceSyncStatic") {
c.logger.FEEDBACK.Printf("Syncing all static files\n") c.logger.Printf("Syncing all static files\n")
_, err := c.copyStatic() _, err := c.copyStatic()
if err != nil { if err != nil {
c.logger.ERROR.Println("Error copying static files to publish dir:", err) c.logger.Errorln("Error copying static files to publish dir:", err)
return return
} }
} else { } else {
if err := staticSyncer.syncsStaticEvents(staticEvents); err != nil { if err := staticSyncer.syncsStaticEvents(staticEvents); err != nil {
c.logger.ERROR.Println("Error syncing static files to publish dir:", err) c.logger.Errorln("Error syncing static files to publish dir:", err)
return return
} }
} }

View file

@ -185,7 +185,7 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
// port set explicitly by user -- he/she probably meant it! // port set explicitly by user -- he/she probably meant it!
err = newSystemErrorF("Server startup failed: %s", err) err = newSystemErrorF("Server startup failed: %s", err)
} }
c.logger.FEEDBACK.Println("port", sc.serverPort, "already in use, attempting to use an available port") c.logger.Println("port", sc.serverPort, "already in use, attempting to use an available port")
sp, err := helpers.FindAvailablePort() sp, err := helpers.FindAvailablePort()
if err != nil { if err != nil {
err = newSystemError("Unable to find alternative port to use:", err) err = newSystemError("Unable to find alternative port to use:", err)
@ -350,7 +350,7 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
w.WriteHeader(500) w.WriteHeader(500)
r, err := f.errorTemplate(err) r, err := f.errorTemplate(err)
if err != nil { if err != nil {
f.c.logger.ERROR.Println(err) f.c.logger.Errorln(err)
} }
port = 1313 port = 1313
@ -508,7 +508,7 @@ func (c *commandeer) serve(s *serverCmd) error {
go func() { go func() {
err = http.ListenAndServe(endpoint, mu) err = http.ListenAndServe(endpoint, mu)
if err != nil { if err != nil {
c.logger.ERROR.Printf("Error: %s\n", err.Error()) c.logger.Errorf("Error: %s\n", err.Error())
os.Exit(1) os.Exit(1)
} }
}() }()

View file

@ -107,10 +107,10 @@ func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
logger.Println("Syncing", relPath, "to", publishDir) logger.Println("Syncing", relPath, "to", publishDir)
if err := syncer.Sync(filepath.Join(publishDir, relPath), relPath); err != nil { if err := syncer.Sync(filepath.Join(publishDir, relPath), relPath); err != nil {
c.logger.ERROR.Println(err) c.logger.Errorln(err)
} }
} else { } else {
c.logger.ERROR.Println(err) c.logger.Errorln(err)
} }
continue continue
@ -119,7 +119,7 @@ func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
// For all other event operations Hugo will sync static. // For all other event operations Hugo will sync static.
logger.Println("Syncing", relPath, "to", publishDir) logger.Println("Syncing", relPath, "to", publishDir)
if err := syncer.Sync(filepath.Join(publishDir, relPath), relPath); err != nil { if err := syncer.Sync(filepath.Join(publishDir, relPath), relPath); err != nil {
c.logger.ERROR.Println(err) c.logger.Errorln(err)
} }
} }

View file

@ -18,4 +18,8 @@ package constants
const ( const (
ErrIDAmbigousDisableKindTaxonomy = "error-disable-taxonomy" ErrIDAmbigousDisableKindTaxonomy = "error-disable-taxonomy"
ErrIDAmbigousOutputKindTaxonomy = "error-output-taxonomy" ErrIDAmbigousOutputKindTaxonomy = "error-output-taxonomy"
// IDs for remote errors in tpl/data.
ErrRemoteGetJSON = "error-remote-getjson"
ErrRemoteGetCSV = "error-remote-getcsv"
) )

View file

@ -19,25 +19,31 @@ import (
) )
// IgnorableLogger is a logger that ignores certain log statements. // IgnorableLogger is a logger that ignores certain log statements.
type IgnorableLogger struct { type IgnorableLogger interface {
logger *Logger Logger
Errorsf(statementID, format string, v ...interface{})
}
type ignorableLogger struct {
Logger
statements map[string]bool statements map[string]bool
} }
// NewIgnorableLogger wraps the given logger and ignores the log statement IDs given. // NewIgnorableLogger wraps the given logger and ignores the log statement IDs given.
func NewIgnorableLogger(logger *Logger, statements ...string) IgnorableLogger { func NewIgnorableLogger(logger Logger, statements ...string) IgnorableLogger {
statementsSet := make(map[string]bool) statementsSet := make(map[string]bool)
for _, s := range statements { for _, s := range statements {
statementsSet[strings.ToLower(s)] = true statementsSet[strings.ToLower(s)] = true
} }
return IgnorableLogger{ return ignorableLogger{
logger: logger, Logger: logger,
statements: statementsSet, statements: statementsSet,
} }
} }
func (l IgnorableLogger) Errorf(statementID, format string, v ...interface{}) { // Errorsf logs statementID as an ERROR if not configured as ignoreable.
func (l ignorableLogger) Errorsf(statementID, format string, v ...interface{}) {
if l.statements[statementID] { if l.statements[statementID] {
// Ignore. // Ignore.
return return
@ -48,5 +54,5 @@ ignoreErrors = [%q]`, statementID)
format += ignoreMsg format += ignoreMsg
l.logger.ERROR.Printf(format, v...) l.Errorf(format, v...)
} }

View file

@ -1,4 +1,4 @@
// Copyright 2018 The Hugo Authors. All rights reserved. // Copyright 2020 The Hugo Authors. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "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 not use this file except in compliance with the License.
@ -56,39 +56,122 @@ func (w prefixWriter) Write(p []byte) (n int, err error) {
return len(p), nil return len(p), nil
} }
// Logger wraps a *loggers.Logger and some other related logging state. type Logger interface {
type Logger struct { Printf(format string, v ...interface{})
Println(v ...interface{})
PrintTimerIfDelayed(start time.Time, name string)
Debug() *log.Logger
Info() *log.Logger
Infof(format string, v ...interface{})
Infoln(v ...interface{})
Warn() *log.Logger
Warnf(format string, v ...interface{})
Warnln(v ...interface{})
Error() *log.Logger
Errorf(format string, v ...interface{})
Errorln(v ...interface{})
Errors() string
Out() io.Writer
Reset()
// Used in tests.
LogCounters() *LogCounters
}
type LogCounters struct {
ErrorCounter *jww.Counter
WarnCounter *jww.Counter
}
type logger struct {
*jww.Notepad *jww.Notepad
// The writer that represents stdout. // The writer that represents stdout.
// Will be ioutil.Discard when in quiet mode. // Will be ioutil.Discard when in quiet mode.
Out io.Writer out io.Writer
ErrorCounter *jww.Counter logCounters *LogCounters
WarnCounter *jww.Counter
// This is only set in server mode. // This is only set in server mode.
errors *bytes.Buffer errors *bytes.Buffer
} }
func (l *logger) Printf(format string, v ...interface{}) {
l.FEEDBACK.Printf(format, v...)
}
func (l *logger) Println(v ...interface{}) {
l.FEEDBACK.Println(v...)
}
func (l *logger) Debug() *log.Logger {
return l.DEBUG
}
func (l *logger) Infof(format string, v ...interface{}) {
l.INFO.Printf(format, v...)
}
func (l *logger) Infoln(v ...interface{}) {
l.INFO.Println(v...)
}
func (l *logger) Info() *log.Logger {
return l.INFO
}
func (l *logger) Warnf(format string, v ...interface{}) {
l.WARN.Printf(format, v...)
}
func (l *logger) Warnln(v ...interface{}) {
l.WARN.Println(v...)
}
func (l *logger) Warn() *log.Logger {
return l.WARN
}
func (l *logger) Errorf(format string, v ...interface{}) {
l.ERROR.Printf(format, v...)
}
func (l *logger) Errorln(v ...interface{}) {
l.ERROR.Println(v...)
}
func (l *logger) Error() *log.Logger {
return l.ERROR
}
func (l *logger) LogCounters() *LogCounters {
return l.logCounters
}
func (l *logger) Out() io.Writer {
return l.out
}
// PrintTimerIfDelayed prints a time statement to the FEEDBACK logger // PrintTimerIfDelayed prints a time statement to the FEEDBACK logger
// if considerable time is spent. // if considerable time is spent.
func (l *Logger) PrintTimerIfDelayed(start time.Time, name string) { func (l *logger) PrintTimerIfDelayed(start time.Time, name string) {
elapsed := time.Since(start) elapsed := time.Since(start)
milli := int(1000 * elapsed.Seconds()) milli := int(1000 * elapsed.Seconds())
if milli < 500 { if milli < 500 {
return return
} }
l.FEEDBACK.Printf("%s in %v ms", name, milli) l.Printf("%s in %v ms", name, milli)
} }
func (l *Logger) PrintTimer(start time.Time, name string) { func (l *logger) PrintTimer(start time.Time, name string) {
elapsed := time.Since(start) elapsed := time.Since(start)
milli := int(1000 * elapsed.Seconds()) milli := int(1000 * elapsed.Seconds())
l.FEEDBACK.Printf("%s in %v ms", name, milli) l.Printf("%s in %v ms", name, milli)
} }
func (l *Logger) Errors() string { func (l *logger) Errors() string {
if l.errors == nil { if l.errors == nil {
return "" return ""
} }
@ -96,45 +179,45 @@ func (l *Logger) Errors() string {
} }
// Reset resets the logger's internal state. // Reset resets the logger's internal state.
func (l *Logger) Reset() { func (l *logger) Reset() {
l.ErrorCounter.Reset() l.logCounters.ErrorCounter.Reset()
if l.errors != nil { if l.errors != nil {
l.errors.Reset() l.errors.Reset()
} }
} }
// NewLogger creates a new Logger for the given thresholds // NewLogger creates a new Logger for the given thresholds
func NewLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) *Logger { func NewLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) Logger {
return newLogger(stdoutThreshold, logThreshold, outHandle, logHandle, saveErrors) return newLogger(stdoutThreshold, logThreshold, outHandle, logHandle, saveErrors)
} }
// NewDebugLogger is a convenience function to create a debug logger. // NewDebugLogger is a convenience function to create a debug logger.
func NewDebugLogger() *Logger { func NewDebugLogger() Logger {
return NewBasicLogger(jww.LevelDebug) return NewBasicLogger(jww.LevelDebug)
} }
// NewWarningLogger is a convenience function to create a warning logger. // NewWarningLogger is a convenience function to create a warning logger.
func NewWarningLogger() *Logger { func NewWarningLogger() Logger {
return NewBasicLogger(jww.LevelWarn) return NewBasicLogger(jww.LevelWarn)
} }
// NewInfoLogger is a convenience function to create a info logger. // NewInfoLogger is a convenience function to create a info logger.
func NewInfoLogger() *Logger { func NewInfoLogger() Logger {
return NewBasicLogger(jww.LevelInfo) return NewBasicLogger(jww.LevelInfo)
} }
// NewErrorLogger is a convenience function to create an error logger. // NewErrorLogger is a convenience function to create an error logger.
func NewErrorLogger() *Logger { func NewErrorLogger() Logger {
return NewBasicLogger(jww.LevelError) return NewBasicLogger(jww.LevelError)
} }
// NewBasicLogger creates a new basic logger writing to Stdout. // NewBasicLogger creates a new basic logger writing to Stdout.
func NewBasicLogger(t jww.Threshold) *Logger { func NewBasicLogger(t jww.Threshold) Logger {
return newLogger(t, jww.LevelError, os.Stdout, ioutil.Discard, false) return newLogger(t, jww.LevelError, os.Stdout, ioutil.Discard, false)
} }
// NewBasicLoggerForWriter creates a new basic logger writing to w. // NewBasicLoggerForWriter creates a new basic logger writing to w.
func NewBasicLoggerForWriter(t jww.Threshold, w io.Writer) *Logger { func NewBasicLoggerForWriter(t jww.Threshold, w io.Writer) Logger {
return newLogger(t, jww.LevelError, w, ioutil.Discard, false) return newLogger(t, jww.LevelError, w, ioutil.Discard, false)
} }
@ -219,7 +302,7 @@ var fatalLogListener = func(t jww.Threshold) io.Writer {
return new(fatalLogWriter) return new(fatalLogWriter)
} }
func newLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) *Logger { func newLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) *logger {
errorCounter := &jww.Counter{} errorCounter := &jww.Counter{}
warnCounter := &jww.Counter{} warnCounter := &jww.Counter{}
outHandle, logHandle = getLogWriters(outHandle, logHandle) outHandle, logHandle = getLogWriters(outHandle, logHandle)
@ -239,11 +322,13 @@ func newLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle
listeners = append(listeners, errorCapture) listeners = append(listeners, errorCapture)
} }
return &Logger{ return &logger{
Notepad: jww.NewNotepad(stdoutThreshold, logThreshold, outHandle, logHandle, "", log.Ldate|log.Ltime, listeners...), Notepad: jww.NewNotepad(stdoutThreshold, logThreshold, outHandle, logHandle, "", log.Ldate|log.Ltime, listeners...),
Out: outHandle, out: outHandle,
ErrorCounter: errorCounter, logCounters: &LogCounters{
WarnCounter: warnCounter, ErrorCounter: errorCounter,
errors: errorBuff, WarnCounter: warnCounter,
},
errors: errorBuff,
} }
} }

View file

@ -26,11 +26,11 @@ func TestLogger(t *testing.T) {
c := qt.New(t) c := qt.New(t)
l := NewWarningLogger() l := NewWarningLogger()
l.ERROR.Println("One error") l.Errorln("One error")
l.ERROR.Println("Two error") l.Errorln("Two error")
l.WARN.Println("A warning") l.Warnln("A warning")
c.Assert(l.ErrorCounter.Count(), qt.Equals, uint64(2)) c.Assert(l.LogCounters().ErrorCounter.Count(), qt.Equals, uint64(2))
} }

14
deps/deps.go vendored
View file

@ -21,6 +21,7 @@ import (
"github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/tpl"
"github.com/spf13/cast"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
) )
@ -30,7 +31,7 @@ import (
type Deps struct { type Deps struct {
// The logger to use. // The logger to use.
Log *loggers.Logger `json:"-"` Log loggers.Logger `json:"-"`
// Used to log errors that may repeat itself many times. // Used to log errors that may repeat itself many times.
DistinctErrorLog *helpers.DistinctLogger DistinctErrorLog *helpers.DistinctLogger
@ -260,12 +261,15 @@ func New(cfg DepsCfg) (*Deps, error) {
timeoutms = 3000 timeoutms = 3000
} }
distinctErrorLogger := helpers.NewDistinctLogger(logger.ERROR) ignoreErrors := cast.ToStringSlice(cfg.Cfg.Get("ignoreErrors"))
distinctWarnLogger := helpers.NewDistinctLogger(logger.WARN) ignorableLogger := loggers.NewIgnorableLogger(logger, ignoreErrors...)
distinctErrorLogger := helpers.NewDistinctLogger(logger.Error())
distinctWarnLogger := helpers.NewDistinctLogger(logger.Warn())
d := &Deps{ d := &Deps{
Fs: fs, Fs: fs,
Log: logger, Log: ignorableLogger,
DistinctErrorLog: distinctErrorLogger, DistinctErrorLog: distinctErrorLogger,
DistinctWarningLog: distinctWarnLogger, DistinctWarningLog: distinctWarnLogger,
templateProvider: cfg.TemplateProvider, templateProvider: cfg.TemplateProvider,
@ -350,7 +354,7 @@ func (d Deps) ForLanguage(cfg DepsCfg, onCreated func(d *Deps) error) (*Deps, er
type DepsCfg struct { type DepsCfg struct {
// The Logger to use. // The Logger to use.
Logger *loggers.Logger Logger loggers.Logger
// The file systems to use // The file systems to use
Fs *hugofs.Fs Fs *hugofs.Fs

View file

@ -65,7 +65,7 @@ type ContentSpec struct {
// NewContentSpec returns a ContentSpec initialized // NewContentSpec returns a ContentSpec initialized
// with the appropriate fields from the given config.Provider. // with the appropriate fields from the given config.Provider.
func NewContentSpec(cfg config.Provider, logger *loggers.Logger, contentFs afero.Fs) (*ContentSpec, error) { func NewContentSpec(cfg config.Provider, logger loggers.Logger, contentFs afero.Fs) (*ContentSpec, error) {
spec := &ContentSpec{ spec := &ContentSpec{
summaryLength: cfg.GetInt("summaryLength"), summaryLength: cfg.GetInt("summaryLength"),

View file

@ -38,13 +38,13 @@ type PathSpec struct {
} }
// NewPathSpec creats a new PathSpec from the given filesystems and language. // NewPathSpec creats a new PathSpec from the given filesystems and language.
func NewPathSpec(fs *hugofs.Fs, cfg config.Provider, logger *loggers.Logger) (*PathSpec, error) { func NewPathSpec(fs *hugofs.Fs, cfg config.Provider, logger loggers.Logger) (*PathSpec, error) {
return NewPathSpecWithBaseBaseFsProvided(fs, cfg, logger, nil) return NewPathSpecWithBaseBaseFsProvided(fs, cfg, logger, nil)
} }
// NewPathSpecWithBaseBaseFsProvided creats a new PathSpec from the given filesystems and language. // NewPathSpecWithBaseBaseFsProvided creats a new PathSpec from the given filesystems and language.
// If an existing BaseFs is provided, parts of that is reused. // If an existing BaseFs is provided, parts of that is reused.
func NewPathSpecWithBaseBaseFsProvided(fs *hugofs.Fs, cfg config.Provider, logger *loggers.Logger, baseBaseFs *filesystems.BaseFs) (*PathSpec, error) { func NewPathSpecWithBaseBaseFsProvided(fs *hugofs.Fs, cfg config.Provider, logger loggers.Logger, baseBaseFs *filesystems.BaseFs) (*PathSpec, error) {
p, err := paths.New(fs, cfg) p, err := paths.New(fs, cfg)
if err != nil { if err != nil {

View file

@ -28,14 +28,14 @@ var (
) )
// NewNoSymlinkFs creates a new filesystem that prevents symlinks. // NewNoSymlinkFs creates a new filesystem that prevents symlinks.
func NewNoSymlinkFs(fs afero.Fs, logger *loggers.Logger, allowFiles bool) afero.Fs { func NewNoSymlinkFs(fs afero.Fs, logger loggers.Logger, allowFiles bool) afero.Fs {
return &noSymlinkFs{Fs: fs, logger: logger, allowFiles: allowFiles} return &noSymlinkFs{Fs: fs, logger: logger, allowFiles: allowFiles}
} }
// noSymlinkFs is a filesystem that prevents symlinking. // noSymlinkFs is a filesystem that prevents symlinking.
type noSymlinkFs struct { type noSymlinkFs struct {
allowFiles bool // block dirs only allowFiles bool // block dirs only
logger *loggers.Logger logger loggers.Logger
afero.Fs afero.Fs
} }

View file

@ -68,7 +68,7 @@ func TestNoSymlinkFs(t *testing.T) {
for _, bfs := range []afero.Fs{NewBaseFileDecorator(Os), Os} { for _, bfs := range []afero.Fs{NewBaseFileDecorator(Os), Os} {
for _, allowFiles := range []bool{false, true} { for _, allowFiles := range []bool{false, true} {
logger.WarnCounter.Reset() logger.LogCounters().WarnCounter.Reset()
fs := NewNoSymlinkFs(bfs, logger, allowFiles) fs := NewNoSymlinkFs(bfs, logger, allowFiles)
ls := fs.(afero.Lstater) ls := fs.(afero.Lstater)
symlinkedDir := filepath.Join(workDir, "symlinkdedir") symlinkedDir := filepath.Join(workDir, "symlinkdedir")
@ -139,7 +139,7 @@ func TestNoSymlinkFs(t *testing.T) {
_, err = f.Readdir(-1) _, err = f.Readdir(-1)
c.Assert(err, qt.IsNil) c.Assert(err, qt.IsNil)
f.Close() f.Close()
c.Assert(logger.WarnCounter.Count(), qt.Equals, uint64(1)) c.Assert(logger.LogCounters().WarnCounter.Count(), qt.Equals, uint64(1))
} }
} }

View file

@ -37,7 +37,7 @@ type Walkway struct {
root string root string
basePath string basePath string
logger *loggers.Logger logger loggers.Logger
// May be pre-set // May be pre-set
fi FileMetaInfo fi FileMetaInfo
@ -59,7 +59,7 @@ type WalkwayConfig struct {
Root string Root string
BasePath string BasePath string
Logger *loggers.Logger Logger loggers.Logger
// One or both of these may be pre-set. // One or both of these may be pre-set.
Info FileMetaInfo Info FileMetaInfo
@ -158,15 +158,15 @@ func (w *Walkway) checkErr(filename string, err error) bool {
// The file may be removed in process. // The file may be removed in process.
// This may be a ERROR situation, but it is not possible // This may be a ERROR situation, but it is not possible
// to determine as a general case. // to determine as a general case.
w.logger.WARN.Printf("File %q not found, skipping.", filename) w.logger.Warnf("File %q not found, skipping.", filename)
return true return true
} }
return false return false
} }
func logUnsupportedSymlink(filename string, logger *loggers.Logger) { func logUnsupportedSymlink(filename string, logger loggers.Logger) {
logger.WARN.Printf("Unsupported symlink found in %q, skipping.", filename) logger.Warnf("Unsupported symlink found in %q, skipping.", filename)
} }
// walk recursively descends path, calling walkFn. // walk recursively descends path, calling walkFn.

View file

@ -33,11 +33,11 @@ import (
type aliasHandler struct { type aliasHandler struct {
t tpl.TemplateHandler t tpl.TemplateHandler
log *loggers.Logger log loggers.Logger
allowRoot bool allowRoot bool
} }
func newAliasHandler(t tpl.TemplateHandler, l *loggers.Logger, allowRoot bool) aliasHandler { func newAliasHandler(t tpl.TemplateHandler, l loggers.Logger, allowRoot bool) aliasHandler {
return aliasHandler{t, l, allowRoot} return aliasHandler{t, l, allowRoot}
} }
@ -80,7 +80,7 @@ func (s *Site) writeDestAlias(path, permalink string, outputFormat output.Format
func (s *Site) publishDestAlias(allowRoot bool, path, permalink string, outputFormat output.Format, p page.Page) (err error) { func (s *Site) publishDestAlias(allowRoot bool, path, permalink string, outputFormat output.Format, p page.Page) (err error) {
handler := newAliasHandler(s.Tmpl(), s.Log, allowRoot) handler := newAliasHandler(s.Tmpl(), s.Log, allowRoot)
s.Log.DEBUG.Println("creating alias:", path, "redirecting to", permalink) s.Log.Debug().Println("creating alias:", path, "redirecting to", permalink)
targetPath, err := handler.targetPathAlias(path) targetPath, err := handler.targetPathAlias(path)
if err != nil { if err != nil {
@ -153,12 +153,12 @@ func (a aliasHandler) targetPathAlias(src string) (string, error) {
if len(msgs) > 0 { if len(msgs) > 0 {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
for _, m := range msgs { for _, m := range msgs {
a.log.ERROR.Println(m) a.log.Errorln(m)
} }
return "", fmt.Errorf("cannot create \"%s\": Windows filename restriction", originalAlias) return "", fmt.Errorf("cannot create \"%s\": Windows filename restriction", originalAlias)
} }
for _, m := range msgs { for _, m := range msgs {
a.log.INFO.Println(m) a.log.Infoln(m)
} }
} }

View file

@ -74,7 +74,7 @@ func loadSiteConfig(cfg config.Provider) (scfg SiteConfig, err error) {
// ConfigSourceDescriptor describes where to find the config (e.g. config.toml etc.). // ConfigSourceDescriptor describes where to find the config (e.g. config.toml etc.).
type ConfigSourceDescriptor struct { type ConfigSourceDescriptor struct {
Fs afero.Fs Fs afero.Fs
Logger *loggers.Logger Logger loggers.Logger
// Path to the config file to use, e.g. /my/project/config.toml // Path to the config file to use, e.g. /my/project/config.toml
Filename string Filename string

View file

@ -581,7 +581,7 @@ func (m *pageMap) attachPageToViews(s string, b *contentNode) {
w := getParamToLower(b.p, viewName.plural+"_weight") w := getParamToLower(b.p, viewName.plural+"_weight")
weight, err := cast.ToIntE(w) weight, err := cast.ToIntE(w)
if err != nil { if err != nil {
m.s.Log.ERROR.Printf("Unable to convert taxonomy weight %#v to int for %q", w, b.p.Path()) m.s.Log.Errorf("Unable to convert taxonomy weight %#v to int for %q", w, b.p.Path())
// weight will equal zero, so let the flow continue // weight will equal zero, so let the flow continue
} }

View file

@ -359,7 +359,7 @@ func WithBaseFs(b *BaseFs) func(*BaseFs) error {
} }
// NewBase builds the filesystems used by Hugo given the paths and options provided.NewBase // NewBase builds the filesystems used by Hugo given the paths and options provided.NewBase
func NewBase(p *paths.Paths, logger *loggers.Logger, options ...func(*BaseFs) error) (*BaseFs, error) { func NewBase(p *paths.Paths, logger loggers.Logger, options ...func(*BaseFs) error) (*BaseFs, error) {
fs := p.Fs fs := p.Fs
if logger == nil { if logger == nil {
logger = loggers.NewWarningLogger() logger = loggers.NewWarningLogger()
@ -396,14 +396,14 @@ func NewBase(p *paths.Paths, logger *loggers.Logger, options ...func(*BaseFs) er
} }
type sourceFilesystemsBuilder struct { type sourceFilesystemsBuilder struct {
logger *loggers.Logger logger loggers.Logger
p *paths.Paths p *paths.Paths
sourceFs afero.Fs sourceFs afero.Fs
result *SourceFilesystems result *SourceFilesystems
theBigFs *filesystemsCollector theBigFs *filesystemsCollector
} }
func newSourceFilesystemsBuilder(p *paths.Paths, logger *loggers.Logger, b *BaseFs) *sourceFilesystemsBuilder { func newSourceFilesystemsBuilder(p *paths.Paths, logger loggers.Logger, b *BaseFs) *sourceFilesystemsBuilder {
sourceFs := hugofs.NewBaseFileDecorator(p.Fs.Source) sourceFs := hugofs.NewBaseFileDecorator(p.Fs.Source)
return &sourceFilesystemsBuilder{p: p, logger: logger, sourceFs: sourceFs, theBigFs: b.theBigFs, result: &SourceFilesystems{}} return &sourceFilesystemsBuilder{p: p, logger: logger, sourceFs: sourceFs, theBigFs: b.theBigFs, result: &SourceFilesystems{}}
} }

View file

@ -649,7 +649,7 @@ min_version = 0.55.0
c := qt.New(t) c := qt.New(t)
c.Assert(logger.WarnCounter.Count(), qt.Equals, uint64(3)) c.Assert(logger.LogCounters().WarnCounter.Count(), qt.Equals, uint64(3))
} }

View file

@ -223,7 +223,7 @@ func (h *HugoSites) pickOneAndLogTheRest(errors []error) error {
break break
} }
h.Log.ERROR.Println(err) h.Log.Errorln(err)
} }
return errors[i] return errors[i]
@ -246,7 +246,7 @@ func (h *HugoSites) NumLogErrors() int {
if h == nil { if h == nil {
return 0 return 0
} }
return int(h.Log.ErrorCounter.Count()) return int(h.Log.LogCounters().ErrorCounter.Count())
} }
func (h *HugoSites) PrintProcessingStats(w io.Writer) { func (h *HugoSites) PrintProcessingStats(w io.Writer) {
@ -386,7 +386,7 @@ func (h *HugoSites) loadGitInfo() error {
if h.Cfg.GetBool("enableGitInfo") { if h.Cfg.GetBool("enableGitInfo") {
gi, err := newGitInfo(h.Cfg) gi, err := newGitInfo(h.Cfg)
if err != nil { if err != nil {
h.Log.ERROR.Println("Failed to read Git log:", err) h.Log.Errorln("Failed to read Git log:", err)
} else { } else {
h.gitInfo = gi h.gitInfo = gi
} }
@ -570,7 +570,7 @@ func (h *HugoSites) resetLogs() {
h.Log.Reset() h.Log.Reset()
loggers.GlobalErrorCounter.Reset() loggers.GlobalErrorCounter.Reset()
for _, s := range h.Sites { for _, s := range h.Sites {
s.Deps.DistinctErrorLog = helpers.NewDistinctLogger(h.Log.ERROR) s.Deps.DistinctErrorLog = helpers.NewDistinctLogger(h.Log.Error())
} }
} }
@ -879,14 +879,14 @@ func (h *HugoSites) handleDataFile(r source.File) error {
// 1. A theme uses the same key; the main data folder wins // 1. A theme uses the same key; the main data folder wins
// 2. A sub folder uses the same key: the sub folder wins // 2. A sub folder uses the same key: the sub folder wins
// TODO(bep) figure out a way to detect 2) above and make that a WARN // TODO(bep) figure out a way to detect 2) above and make that a WARN
h.Log.INFO.Printf("Data for key '%s' in path '%s' is overridden by higher precedence data already in the data tree", key, r.Path()) h.Log.Infof("Data for key '%s' in path '%s' is overridden by higher precedence data already in the data tree", key, r.Path())
} else { } else {
higherPrecedentMap[key] = value higherPrecedentMap[key] = value
} }
} }
default: default:
// can't merge: higherPrecedentData is not a map // can't merge: higherPrecedentData is not a map
h.Log.WARN.Printf("The %T data from '%s' overridden by "+ h.Log.Warnf("The %T data from '%s' overridden by "+
"higher precedence %T data already in the data tree", data, r.Path(), higherPrecedentData) "higher precedence %T data already in the data tree", data, r.Path(), higherPrecedentData)
} }
@ -895,12 +895,12 @@ func (h *HugoSites) handleDataFile(r source.File) error {
current[r.BaseFileName()] = data current[r.BaseFileName()] = data
} else { } else {
// we don't merge array data // we don't merge array data
h.Log.WARN.Printf("The %T data from '%s' overridden by "+ h.Log.Warnf("The %T data from '%s' overridden by "+
"higher precedence %T data already in the data tree", data, r.Path(), higherPrecedentData) "higher precedence %T data already in the data tree", data, r.Path(), higherPrecedentData)
} }
default: default:
h.Log.ERROR.Printf("unexpected data type %T in file %s", data, r.LogicalName()) h.Log.Errorf("unexpected data type %T in file %s", data, r.LogicalName())
} }
return nil return nil

View file

@ -162,9 +162,8 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
var b bytes.Buffer var b bytes.Buffer
h.Metrics.WriteMetrics(&b) h.Metrics.WriteMetrics(&b)
h.Log.FEEDBACK.Printf("\nTemplate Metrics:\n\n") h.Log.Printf("\nTemplate Metrics:\n\n")
h.Log.FEEDBACK.Print(b.String()) h.Log.Println(b.String())
h.Log.FEEDBACK.Println()
} }
select { select {
@ -183,7 +182,7 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
return err return err
} }
errorCount := h.Log.ErrorCounter.Count() errorCount := h.Log.LogCounters().ErrorCounter.Count()
if errorCount > 0 { if errorCount > 0 {
return fmt.Errorf("logged %d error(s)", errorCount) return fmt.Errorf("logged %d error(s)", errorCount)
} }

View file

@ -536,7 +536,7 @@ func (p *pageState) renderResources() (err error) {
// mode when the same resource is member of different page bundles. // mode when the same resource is member of different page bundles.
toBeDeleted = append(toBeDeleted, i) toBeDeleted = append(toBeDeleted, i)
} else { } else {
p.s.Log.ERROR.Printf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err) p.s.Log.Errorf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err)
} }
} else { } else {
p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files) p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files)
@ -718,7 +718,7 @@ func (p *pageState) getContentConverter() converter.Converter {
}) })
if err != nil { if err != nil {
p.s.Log.ERROR.Println("Failed to create content converter:", err) p.s.Log.Errorln("Failed to create content converter:", err)
} }
return p.m.contentConverter return p.m.contentConverter
} }

View file

@ -66,7 +66,7 @@ func (p *pageMenus) init() {
var err error var err error
p.pm, err = navigation.PageMenusFromPage(p.p) p.pm, err = navigation.PageMenusFromPage(p.p)
if err != nil { if err != nil {
p.p.s.Log.ERROR.Println(p.p.wrapError(err)) p.p.s.Log.Errorln(p.p.wrapError(err))
} }
}) })

View file

@ -431,7 +431,7 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
// more easily tested without the Page, but the coupling is strong. // more easily tested without the Page, but the coupling is strong.
err := pm.s.frontmatterHandler.HandleDates(descriptor) err := pm.s.frontmatterHandler.HandleDates(descriptor)
if err != nil { if err != nil {
p.s.Log.ERROR.Printf("Failed to handle dates for page %q: %s", p.pathOrTitle(), err) p.s.Log.Errorf("Failed to handle dates for page %q: %s", p.pathOrTitle(), err)
} }
pm.buildConfig, err = pagemeta.DecodeBuildConfig(frontmatter["_build"]) pm.buildConfig, err = pagemeta.DecodeBuildConfig(frontmatter["_build"])
@ -486,7 +486,7 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
// We added support for page relative URLs in Hugo 0.55 and // We added support for page relative URLs in Hugo 0.55 and
// this may get its language path added twice. // this may get its language path added twice.
// TODO(bep) eventually remove this. // TODO(bep) eventually remove this.
p.s.Log.WARN.Printf(`Front matter in %q with the url %q with no leading / has what looks like the language prefix added. In Hugo 0.55 we added support for page relative URLs in front matter, no language prefix needed. Check the URL and consider to either add a leading / or remove the language prefix.`, p.pathOrTitle(), url) p.s.Log.Warnf(`Front matter in %q with the url %q with no leading / has what looks like the language prefix added. In Hugo 0.55 we added support for page relative URLs in front matter, no language prefix needed. Check the URL and consider to either add a leading / or remove the language prefix.`, p.pathOrTitle(), url)
} }
} }
@ -515,7 +515,7 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
outFormats, err := p.s.outputFormatsConfig.GetByNames(o...) outFormats, err := p.s.outputFormatsConfig.GetByNames(o...)
if err != nil { if err != nil {
p.s.Log.ERROR.Printf("Failed to resolve output formats: %s", err) p.s.Log.Errorf("Failed to resolve output formats: %s", err)
} else { } else {
pm.configuredOutputFormats = outFormats pm.configuredOutputFormats = outFormats
pm.params[loki] = outFormats pm.params[loki] = outFormats
@ -634,7 +634,7 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
if draft != nil && published != nil { if draft != nil && published != nil {
pm.draft = *draft pm.draft = *draft
p.m.s.Log.WARN.Printf("page %q has both draft and published settings in its frontmatter. Using draft.", p.File().Filename()) p.m.s.Log.Warnf("page %q has both draft and published settings in its frontmatter. Using draft.", p.File().Filename())
} else if draft != nil { } else if draft != nil {
pm.draft = *draft pm.draft = *draft
} else if published != nil { } else if published != nil {

View file

@ -91,7 +91,7 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
// See https://github.com/gohugoio/hugo/issues/6210 // See https://github.com/gohugoio/hugo/issues/6210
if r := recover(); r != nil { if r := recover(); r != nil {
err = fmt.Errorf("%s", r) err = fmt.Errorf("%s", r)
p.s.Log.ERROR.Printf("[BUG] Got panic:\n%s\n%s", r, string(debug.Stack())) p.s.Log.Errorf("[BUG] Got panic:\n%s\n%s", r, string(debug.Stack()))
} }
}() }()
@ -177,7 +177,7 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
} else { } else {
summary, content, err := splitUserDefinedSummaryAndContent(cp.p.m.markup, cp.workContent) summary, content, err := splitUserDefinedSummaryAndContent(cp.p.m.markup, cp.workContent)
if err != nil { if err != nil {
cp.p.s.Log.ERROR.Printf("Failed to set user defined summary for page %q: %s", cp.p.pathOrTitle(), err) cp.p.s.Log.Errorf("Failed to set user defined summary for page %q: %s", cp.p.pathOrTitle(), err)
} else { } else {
cp.workContent = content cp.workContent = content
cp.summary = helpers.BytesToHTML(summary) cp.summary = helpers.BytesToHTML(summary)

View file

@ -41,7 +41,7 @@ const (
func newPagesCollector( func newPagesCollector(
sp *source.SourceSpec, sp *source.SourceSpec,
contentMap *pageMaps, contentMap *pageMaps,
logger *loggers.Logger, logger loggers.Logger,
contentTracker *contentChangeMap, contentTracker *contentChangeMap,
proc pagesCollectorProcessorProvider, filenames ...string) *pagesCollector { proc pagesCollectorProcessorProvider, filenames ...string) *pagesCollector {
@ -83,7 +83,7 @@ type pageBundles map[string]*fileinfoBundle
type pagesCollector struct { type pagesCollector struct {
sp *source.SourceSpec sp *source.SourceSpec
fs afero.Fs fs afero.Fs
logger *loggers.Logger logger loggers.Logger
contentMap *pageMaps contentMap *pageMaps
@ -441,7 +441,7 @@ func (c *pagesCollector) collectDir(dirname string, partial bool, inFilter func(
// The branch variant will win because of sort order, but log // The branch variant will win because of sort order, but log
// a warning about it. // a warning about it.
if thisBtype > bundleNot && btype > bundleNot && thisBtype != btype { if thisBtype > bundleNot && btype > bundleNot && thisBtype != btype {
c.logger.WARN.Printf("Content directory %q have both index.* and _index.* files, pick one.", dir.Meta().Filename()) c.logger.Warnf("Content directory %q have both index.* and _index.* files, pick one.", dir.Meta().Filename())
// Reclassify it so it will be handled as a content file inside the // Reclassify it so it will be handled as a content file inside the
// section, which is in line with the <= 0.55 behaviour. // section, which is in line with the <= 0.55 behaviour.
meta["classifier"] = files.ContentClassContent meta["classifier"] = files.ContentClassContent

View file

@ -324,7 +324,7 @@ func renderShortcode(
var found, more bool var found, more bool
tmpl, found, more = s.Tmpl().LookupVariant(sc.name, tplVariants) tmpl, found, more = s.Tmpl().LookupVariant(sc.name, tplVariants)
if !found { if !found {
s.Log.ERROR.Printf("Unable to locate template for shortcode %q in page %q", sc.name, p.File().Path()) s.Log.Errorf("Unable to locate template for shortcode %q in page %q", sc.name, p.File().Path())
return "", false, nil return "", false, nil
} }
hasVariants = hasVariants || more hasVariants = hasVariants || more
@ -349,7 +349,7 @@ func renderShortcode(
hasVariants = hasVariants || more hasVariants = hasVariants || more
inner += s inner += s
default: default:
s.Log.ERROR.Printf("Illegal state on shortcode rendering of %q in page %q. Illegal type in inner data: %s ", s.Log.Errorf("Illegal state on shortcode rendering of %q in page %q. Illegal type in inner data: %s ",
sc.name, p.File().Path(), reflect.TypeOf(innerData)) sc.name, p.File().Path(), reflect.TypeOf(innerData))
return "", false, nil return "", false, nil
} }

View file

@ -425,7 +425,7 @@ func newSite(cfg deps.DepsCfg) (*Site, error) {
delete(disabledKinds, "taxonomyTerm") delete(disabledKinds, "taxonomyTerm")
} else if disabledKinds[page.KindTaxonomy] && !disabledKinds[page.KindTerm] { } else if disabledKinds[page.KindTaxonomy] && !disabledKinds[page.KindTerm] {
// This is a potentially ambigous situation. It may be correct. // This is a potentially ambigous situation. It may be correct.
ignorableLogger.Errorf(constants.ErrIDAmbigousDisableKindTaxonomy, `You have the value 'taxonomy' in the disabledKinds list. In Hugo 0.73.0 we fixed these to be what most people expect (taxonomy and term). ignorableLogger.Errorsf(constants.ErrIDAmbigousDisableKindTaxonomy, `You have the value 'taxonomy' in the disabledKinds list. In Hugo 0.73.0 we fixed these to be what most people expect (taxonomy and term).
But this also means that your site configuration may not do what you expect. If it is correct, you can suppress this message by following the instructions below.`) But this also means that your site configuration may not do what you expect. If it is correct, you can suppress this message by following the instructions below.`)
} }
@ -485,7 +485,7 @@ But this also means that your site configuration may not do what you expect. If
delete(siteOutputs, "taxonomyTerm") delete(siteOutputs, "taxonomyTerm")
} else if hasTaxonomy && !hasTerm { } else if hasTaxonomy && !hasTerm {
// This is a potentially ambigous situation. It may be correct. // This is a potentially ambigous situation. It may be correct.
ignorableLogger.Errorf(constants.ErrIDAmbigousOutputKindTaxonomy, `You have configured output formats for 'taxonomy' in your site configuration. In Hugo 0.73.0 we fixed these to be what most people expect (taxonomy and term). ignorableLogger.Errorsf(constants.ErrIDAmbigousOutputKindTaxonomy, `You have configured output formats for 'taxonomy' in your site configuration. In Hugo 0.73.0 we fixed these to be what most people expect (taxonomy and term).
But this also means that your site configuration may not do what you expect. If it is correct, you can suppress this message by following the instructions below.`) But this also means that your site configuration may not do what you expect. If it is correct, you can suppress this message by following the instructions below.`)
} }
if !hasTaxonomy && hasTaxonomyTerm { if !hasTaxonomy && hasTaxonomyTerm {
@ -806,12 +806,12 @@ type siteRefLinker struct {
} }
func newSiteRefLinker(cfg config.Provider, s *Site) (siteRefLinker, error) { func newSiteRefLinker(cfg config.Provider, s *Site) (siteRefLinker, error) {
logger := s.Log.ERROR logger := s.Log.Error()
notFoundURL := cfg.GetString("refLinksNotFoundURL") notFoundURL := cfg.GetString("refLinksNotFoundURL")
errLevel := cfg.GetString("refLinksErrorLevel") errLevel := cfg.GetString("refLinksErrorLevel")
if strings.EqualFold(errLevel, "warning") { if strings.EqualFold(errLevel, "warning") {
logger = s.Log.WARN logger = s.Log.Warn()
} }
return siteRefLinker{s: s, errorLogger: logger, notFoundURL: notFoundURL}, nil return siteRefLinker{s: s, errorLogger: logger, notFoundURL: notFoundURL}, nil
} }
@ -1006,7 +1006,7 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
changeIdentities := make(identity.Identities) changeIdentities := make(identity.Identities)
s.Log.DEBUG.Printf("Rebuild for events %q", events) s.Log.Debug().Printf("Rebuild for events %q", events)
h := s.h h := s.h
@ -1377,17 +1377,17 @@ func (s *Site) getMenusFromConfig() navigation.Menus {
for name, menu := range menus { for name, menu := range menus {
m, err := cast.ToSliceE(menu) m, err := cast.ToSliceE(menu)
if err != nil { if err != nil {
s.Log.ERROR.Printf("unable to process menus in site config\n") s.Log.Errorf("unable to process menus in site config\n")
s.Log.ERROR.Println(err) s.Log.Errorln(err)
} else { } else {
for _, entry := range m { for _, entry := range m {
s.Log.DEBUG.Printf("found menu: %q, in site config\n", name) s.Log.Debug().Printf("found menu: %q, in site config\n", name)
menuEntry := navigation.MenuEntry{Menu: name} menuEntry := navigation.MenuEntry{Menu: name}
ime, err := maps.ToStringMapE(entry) ime, err := maps.ToStringMapE(entry)
if err != nil { if err != nil {
s.Log.ERROR.Printf("unable to process menus in site config\n") s.Log.Errorf("unable to process menus in site config\n")
s.Log.ERROR.Println(err) s.Log.Errorln(err)
} }
menuEntry.MarshallMap(ime) menuEntry.MarshallMap(ime)
@ -1471,7 +1471,7 @@ func (s *Site) assembleMenus() {
for name, me := range p.pageMenus.menus() { for name, me := range p.pageMenus.menus() {
if _, ok := flat[twoD{name, me.KeyName()}]; ok { if _, ok := flat[twoD{name, me.KeyName()}]; ok {
err := p.wrapError(errors.Errorf("duplicate menu entry with identifier %q in menu %q", me.KeyName(), name)) err := p.wrapError(errors.Errorf("duplicate menu entry with identifier %q in menu %q", me.KeyName(), name))
s.Log.WARN.Println(err) s.Log.Warnln(err)
continue continue
} }
flat[twoD{name, me.KeyName()}] = me flat[twoD{name, me.KeyName()}] = me
@ -1643,7 +1643,7 @@ func (s *Site) lookupLayouts(layouts ...string) tpl.Template {
} }
func (s *Site) renderAndWriteXML(statCounter *uint64, name string, targetPath string, d interface{}, templ tpl.Template) error { func (s *Site) renderAndWriteXML(statCounter *uint64, name string, targetPath string, d interface{}, templ tpl.Template) error {
s.Log.DEBUG.Printf("Render XML for %q to %q", name, targetPath) s.Log.Debug().Printf("Render XML for %q to %q", name, targetPath)
renderBuffer := bp.GetBuffer() renderBuffer := bp.GetBuffer()
defer bp.PutBuffer(renderBuffer) defer bp.PutBuffer(renderBuffer)
@ -1665,7 +1665,7 @@ func (s *Site) renderAndWriteXML(statCounter *uint64, name string, targetPath st
} }
func (s *Site) renderAndWritePage(statCounter *uint64, name string, targetPath string, p *pageState, templ tpl.Template) error { func (s *Site) renderAndWritePage(statCounter *uint64, name string, targetPath string, p *pageState, templ tpl.Template) error {
s.Log.DEBUG.Printf("Render %s to %q", name, targetPath) s.Log.Debug().Printf("Render %s to %q", name, targetPath)
renderBuffer := bp.GetBuffer() renderBuffer := bp.GetBuffer()
defer bp.PutBuffer(renderBuffer) defer bp.PutBuffer(renderBuffer)

View file

@ -149,9 +149,9 @@ func pageRenderer(
} }
func (s *Site) logMissingLayout(name, layout, kind, outputFormat string) { func (s *Site) logMissingLayout(name, layout, kind, outputFormat string) {
log := s.Log.WARN log := s.Log.Warn()
if name != "" && infoOnMissingLayout[name] { if name != "" && infoOnMissingLayout[name] {
log = s.Log.INFO log = s.Log.Info()
} }
errMsg := "You should create a template file which matches Hugo Layouts Lookup Rules for this combination." errMsg := "You should create a template file which matches Hugo Layouts Lookup Rules for this combination."
@ -396,13 +396,13 @@ func (s *Site) renderMainLanguageRedirect() error {
mainLang := s.h.multilingual.DefaultLang mainLang := s.h.multilingual.DefaultLang
if s.Info.defaultContentLanguageInSubdir { if s.Info.defaultContentLanguageInSubdir {
mainLangURL := s.PathSpec.AbsURL(mainLang.Lang+"/", false) mainLangURL := s.PathSpec.AbsURL(mainLang.Lang+"/", false)
s.Log.DEBUG.Printf("Write redirect to main language %s: %s", mainLang, mainLangURL) s.Log.Debug().Printf("Write redirect to main language %s: %s", mainLang, mainLangURL)
if err := s.publishDestAlias(true, "/", mainLangURL, html, nil); err != nil { if err := s.publishDestAlias(true, "/", mainLangURL, html, nil); err != nil {
return err return err
} }
} else { } else {
mainLangURL := s.PathSpec.AbsURL("", false) mainLangURL := s.PathSpec.AbsURL("", false)
s.Log.DEBUG.Printf("Write redirect to main language %s: %s", mainLang, mainLangURL) s.Log.Debug().Printf("Write redirect to main language %s: %s", mainLang, mainLangURL)
if err := s.publishDestAlias(true, mainLang.Lang, mainLangURL, html, nil); err != nil { if err := s.publishDestAlias(true, mainLang.Lang, mainLangURL, html, nil); err != nil {
return err return err
} }

View file

@ -67,7 +67,7 @@ type sitesBuilder struct {
*qt.C *qt.C
logger *loggers.Logger logger loggers.Logger
rnd *rand.Rand rnd *rand.Rand
dumper litter.Options dumper litter.Options
@ -154,7 +154,7 @@ func (s *sitesBuilder) WithNothingAdded() *sitesBuilder {
return s return s
} }
func (s *sitesBuilder) WithLogger(logger *loggers.Logger) *sitesBuilder { func (s *sitesBuilder) WithLogger(logger loggers.Logger) *sitesBuilder {
s.logger = logger s.logger = logger
return s return s
} }

View file

@ -35,11 +35,11 @@ var (
type Translator struct { type Translator struct {
translateFuncs map[string]translateFunc translateFuncs map[string]translateFunc
cfg config.Provider cfg config.Provider
logger *loggers.Logger logger loggers.Logger
} }
// NewTranslator creates a new Translator for the given language bundle and configuration. // NewTranslator creates a new Translator for the given language bundle and configuration.
func NewTranslator(b *i18n.Bundle, cfg config.Provider, logger *loggers.Logger) Translator { func NewTranslator(b *i18n.Bundle, cfg config.Provider, logger loggers.Logger) Translator {
t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]translateFunc)} t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]translateFunc)}
t.initFuncs(b) t.initFuncs(b)
return t return t
@ -51,12 +51,12 @@ func (t Translator) Func(lang string) translateFunc {
if f, ok := t.translateFuncs[lang]; ok { if f, ok := t.translateFuncs[lang]; ok {
return f return f
} }
t.logger.INFO.Printf("Translation func for language %v not found, use default.", lang) t.logger.Infof("Translation func for language %v not found, use default.", lang)
if f, ok := t.translateFuncs[t.cfg.GetString("defaultContentLanguage")]; ok { if f, ok := t.translateFuncs[t.cfg.GetString("defaultContentLanguage")]; ok {
return f return f
} }
t.logger.INFO.Println("i18n not initialized; if you need string translations, check that you have a bundle in /i18n that matches the site language or the default language.") t.logger.Infoln("i18n not initialized; if you need string translations, check that you have a bundle in /i18n that matches the site language or the default language.")
return func(translationID string, args interface{}) string { return func(translationID string, args interface{}) string {
return "" return ""
} }
@ -98,7 +98,7 @@ func (t Translator) initFuncs(bndl *i18n.Bundle) {
} }
if _, ok := err.(*i18n.MessageNotFoundErr); !ok { if _, ok := err.(*i18n.MessageNotFoundErr); !ok {
t.logger.WARN.Printf("Failed to get translated string for language %q and ID %q: %s", currentLangStr, translationID, err) t.logger.Warnf("Failed to get translated string for language %q and ID %q: %s", currentLangStr, translationID, err)
} }
if t.cfg.GetBool("logI18nWarnings") { if t.cfg.GetBool("logI18nWarnings") {

View file

@ -82,7 +82,7 @@ func (a *asciidocConverter) Supports(_ identity.Identity) bool {
func (a *asciidocConverter) getAsciidocContent(src []byte, ctx converter.DocumentContext) []byte { func (a *asciidocConverter) getAsciidocContent(src []byte, ctx converter.DocumentContext) []byte {
path := getAsciidoctorExecPath() path := getAsciidoctorExecPath()
if path == "" { if path == "" {
a.cfg.Logger.ERROR.Println("asciidoctor not found in $PATH: Please install.\n", a.cfg.Logger.Errorln("asciidoctor not found in $PATH: Please install.\n",
" Leaving AsciiDoc content unrendered.") " Leaving AsciiDoc content unrendered.")
return src return src
} }
@ -90,7 +90,7 @@ func (a *asciidocConverter) getAsciidocContent(src []byte, ctx converter.Documen
args := a.parseArgs(ctx) args := a.parseArgs(ctx)
args = append(args, "-") args = append(args, "-")
a.cfg.Logger.INFO.Println("Rendering", ctx.DocumentName, "with", path, "using asciidoctor args", args, "...") a.cfg.Logger.Infoln("Rendering", ctx.DocumentName, "with", path, "using asciidoctor args", args, "...")
return internal.ExternallyRenderContent(a.cfg, ctx, src, path, args) return internal.ExternallyRenderContent(a.cfg, ctx, src, path, args)
} }
@ -103,7 +103,7 @@ func (a *asciidocConverter) parseArgs(ctx converter.DocumentContext) []string {
for _, extension := range cfg.Extensions { for _, extension := range cfg.Extensions {
if !asciidocext_config.AllowedExtensions[extension] { if !asciidocext_config.AllowedExtensions[extension] {
a.cfg.Logger.ERROR.Println("Unsupported asciidoctor extension was passed in. Extension `" + extension + "` ignored.") a.cfg.Logger.Errorln("Unsupported asciidoctor extension was passed in. Extension `" + extension + "` ignored.")
continue continue
} }
@ -112,7 +112,7 @@ func (a *asciidocConverter) parseArgs(ctx converter.DocumentContext) []string {
for attributeKey, attributeValue := range cfg.Attributes { for attributeKey, attributeValue := range cfg.Attributes {
if asciidocext_config.DisallowedAttributes[attributeKey] { if asciidocext_config.DisallowedAttributes[attributeKey] {
a.cfg.Logger.ERROR.Println("Unsupported asciidoctor attribute was passed in. Attribute `" + attributeKey + "` ignored.") a.cfg.Logger.Errorln("Unsupported asciidoctor attribute was passed in. Attribute `" + attributeKey + "` ignored.")
continue continue
} }
@ -125,7 +125,7 @@ func (a *asciidocConverter) parseArgs(ctx converter.DocumentContext) []string {
destinationDir := a.cfg.Cfg.GetString("destination") destinationDir := a.cfg.Cfg.GetString("destination")
if destinationDir == "" { if destinationDir == "" {
a.cfg.Logger.ERROR.Println("markup.asciidocext.workingFolderCurrent requires hugo command option --destination to be set") a.cfg.Logger.Errorln("markup.asciidocext.workingFolderCurrent requires hugo command option --destination to be set")
} }
if !filepath.IsAbs(destinationDir) && sourceDir != "" { if !filepath.IsAbs(destinationDir) && sourceDir != "" {
destinationDir = filepath.Join(sourceDir, destinationDir) destinationDir = filepath.Join(sourceDir, destinationDir)
@ -144,14 +144,14 @@ func (a *asciidocConverter) parseArgs(ctx converter.DocumentContext) []string {
if ok { if ok {
postDir = filepath.Base(page.RelPermalink()) postDir = filepath.Base(page.RelPermalink())
} else { } else {
a.cfg.Logger.ERROR.Println("unable to cast interface to pageSubset") a.cfg.Logger.Errorln("unable to cast interface to pageSubset")
} }
outDir, err = filepath.Abs(filepath.Join(destinationDir, filepath.Dir(ctx.DocumentName), postDir)) outDir, err = filepath.Abs(filepath.Join(destinationDir, filepath.Dir(ctx.DocumentName), postDir))
} }
if err != nil { if err != nil {
a.cfg.Logger.ERROR.Println("asciidoctor outDir: ", err) a.cfg.Logger.Errorln("asciidoctor outDir: ", err)
} }
args = append(args, "--base-dir", contentDir, "-a", "outdir="+outDir) args = append(args, "--base-dir", contentDir, "-a", "outdir="+outDir)
@ -160,7 +160,7 @@ func (a *asciidocConverter) parseArgs(ctx converter.DocumentContext) []string {
if cfg.NoHeaderOrFooter { if cfg.NoHeaderOrFooter {
args = append(args, "--no-header-footer") args = append(args, "--no-header-footer")
} else { } else {
a.cfg.Logger.WARN.Println("asciidoctor parameter NoHeaderOrFooter is expected for correct html rendering") a.cfg.Logger.Warnln("asciidoctor parameter NoHeaderOrFooter is expected for correct html rendering")
} }
if cfg.SectionNumbers { if cfg.SectionNumbers {
@ -187,7 +187,7 @@ func (a *asciidocConverter) appendArg(args []string, option, value, defaultValue
if allowedValues[value] { if allowedValues[value] {
args = append(args, option, value) args = append(args, option, value)
} else { } else {
a.cfg.Logger.ERROR.Println("Unsupported asciidoctor value `" + value + "` for option " + option + " was passed in and will be ignored.") a.cfg.Logger.Errorln("Unsupported asciidoctor value `" + value + "` for option " + option + " was passed in and will be ignored.")
} }
} }
return args return args

View file

@ -31,7 +31,7 @@ type ProviderConfig struct {
Cfg config.Provider // Site config Cfg config.Provider // Site config
ContentFs afero.Fs ContentFs afero.Fs
Logger *loggers.Logger Logger loggers.Logger
Highlight func(code, lang, optsStr string) (string, error) Highlight func(code, lang, optsStr string) (string, error)
} }

View file

@ -25,11 +25,11 @@ func ExternallyRenderContent(
for _, item := range strings.Split(cmderr.String(), "\n") { for _, item := range strings.Split(cmderr.String(), "\n") {
item := strings.TrimSpace(item) item := strings.TrimSpace(item)
if item != "" { if item != "" {
logger.ERROR.Printf("%s: %s", ctx.DocumentName, item) logger.Errorf("%s: %s", ctx.DocumentName, item)
} }
} }
if err != nil { if err != nil {
logger.ERROR.Printf("%s rendering %s: %v", path, ctx.DocumentName, err) logger.Errorf("%s rendering %s: %v", path, ctx.DocumentName, err)
} }
return normalizeExternalHelperLineFeeds(out.Bytes()) return normalizeExternalHelperLineFeeds(out.Bytes())

View file

@ -47,7 +47,7 @@ type orgConverter struct {
func (c *orgConverter) Convert(ctx converter.RenderContext) (converter.Result, error) { func (c *orgConverter) Convert(ctx converter.RenderContext) (converter.Result, error) {
logger := c.cfg.Logger logger := c.cfg.Logger
config := org.New() config := org.New()
config.Log = logger.WARN config.Log = logger.Warn()
config.ReadFile = func(filename string) ([]byte, error) { config.ReadFile = func(filename string) ([]byte, error) {
return afero.ReadFile(c.cfg.ContentFs, filename) return afero.ReadFile(c.cfg.ContentFs, filename)
} }
@ -55,7 +55,7 @@ func (c *orgConverter) Convert(ctx converter.RenderContext) (converter.Result, e
writer.HighlightCodeBlock = func(source, lang string, inline bool) string { writer.HighlightCodeBlock = func(source, lang string, inline bool) string {
highlightedSource, err := c.cfg.Highlight(source, lang, "") highlightedSource, err := c.cfg.Highlight(source, lang, "")
if err != nil { if err != nil {
logger.ERROR.Printf("Could not highlight source as lang %s. Using raw source.", lang) logger.Errorf("Could not highlight source as lang %s. Using raw source.", lang)
return source return source
} }
return highlightedSource return highlightedSource
@ -63,7 +63,7 @@ func (c *orgConverter) Convert(ctx converter.RenderContext) (converter.Result, e
html, err := config.Parse(bytes.NewReader(ctx.Src), c.ctx.DocumentName).Write(writer) html, err := config.Parse(bytes.NewReader(ctx.Src), c.ctx.DocumentName).Write(writer)
if err != nil { if err != nil {
logger.ERROR.Printf("Could not render org: %s. Using unrendered content.", err) logger.Errorf("Could not render org: %s. Using unrendered content.", err)
return converter.Bytes(ctx.Src), nil return converter.Bytes(ctx.Src), nil
} }
return converter.Bytes([]byte(html)), nil return converter.Bytes([]byte(html)), nil

View file

@ -57,7 +57,7 @@ func (c *pandocConverter) getPandocContent(src []byte, ctx converter.DocumentCon
logger := c.cfg.Logger logger := c.cfg.Logger
path := getPandocExecPath() path := getPandocExecPath()
if path == "" { if path == "" {
logger.ERROR.Println("pandoc not found in $PATH: Please install.\n", logger.Println("pandoc not found in $PATH: Please install.\n",
" Leaving pandoc content unrendered.") " Leaving pandoc content unrendered.")
return src return src
} }

View file

@ -60,11 +60,11 @@ func (c *rstConverter) getRstContent(src []byte, ctx converter.DocumentContext)
path := getRstExecPath() path := getRstExecPath()
if path == "" { if path == "" {
logger.ERROR.Println("rst2html / rst2html.py not found in $PATH: Please install.\n", logger.Println("rst2html / rst2html.py not found in $PATH: Please install.\n",
" Leaving reStructuredText content unrendered.") " Leaving reStructuredText content unrendered.")
return src return src
} }
logger.INFO.Println("Rendering", ctx.DocumentName, "with", path, "...") logger.Println("Rendering", ctx.DocumentName, "with", path, "...")
var result []byte var result []byte
// certain *nix based OSs wrap executables in scripted launchers // certain *nix based OSs wrap executables in scripted launchers
// invoking binaries on these OSs via python interpreter causes SyntaxError // invoking binaries on these OSs via python interpreter causes SyntaxError

View file

@ -119,7 +119,7 @@ func NewClient(cfg ClientConfig) *Client {
// Client contains most of the API provided by this package. // Client contains most of the API provided by this package.
type Client struct { type Client struct {
fs afero.Fs fs afero.Fs
logger *loggers.Logger logger loggers.Logger
noVendor glob.Glob noVendor glob.Glob
@ -329,7 +329,7 @@ func (c *Client) Get(args ...string) error {
} }
func (c *Client) get(args ...string) error { func (c *Client) get(args ...string) error {
if err := c.runGo(context.Background(), c.logger.Out, append([]string{"get"}, args...)...); err != nil { if err := c.runGo(context.Background(), c.logger.Out(), append([]string{"get"}, args...)...); err != nil {
errors.Wrapf(err, "failed to get %q", args) errors.Wrapf(err, "failed to get %q", args)
} }
return nil return nil
@ -339,7 +339,7 @@ func (c *Client) get(args ...string) error {
// If path is empty, Go will try to guess. // If path is empty, Go will try to guess.
// If this succeeds, this project will be marked as Go Module. // If this succeeds, this project will be marked as Go Module.
func (c *Client) Init(path string) error { func (c *Client) Init(path string) error {
err := c.runGo(context.Background(), c.logger.Out, "mod", "init", path) err := c.runGo(context.Background(), c.logger.Out(), "mod", "init", path)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to init modules") return errors.Wrap(err, "failed to init modules")
} }
@ -403,7 +403,7 @@ func (c *Client) Clean(pattern string) error {
} }
_, err = hugofs.MakeReadableAndRemoveAllModulePkgDir(c.fs, m.Dir) _, err = hugofs.MakeReadableAndRemoveAllModulePkgDir(c.fs, m.Dir)
if err == nil { if err == nil {
c.logger.FEEDBACK.Printf("hugo: cleaned module cache for %q", m.Path) c.logger.Printf("hugo: cleaned module cache for %q", m.Path)
} }
} }
return err return err
@ -560,7 +560,7 @@ func (c *Client) runGo(
if strings.Contains(stderr.String(), "invalid version: unknown revision") { if strings.Contains(stderr.String(), "invalid version: unknown revision") {
// See https://github.com/gohugoio/hugo/issues/6825 // See https://github.com/gohugoio/hugo/issues/6825
c.logger.FEEDBACK.Println(`hugo: you need to manually edit go.mod to resolve the unknown revision.`) c.logger.Println(`hugo: you need to manually edit go.mod to resolve the unknown revision.`)
} }
_, ok := err.(*exec.ExitError) _, ok := err.(*exec.ExitError)
@ -616,7 +616,7 @@ func (c *Client) shouldVendor(path string) bool {
// ClientConfig configures the module Client. // ClientConfig configures the module Client.
type ClientConfig struct { type ClientConfig struct {
Fs afero.Fs Fs afero.Fs
Logger *loggers.Logger Logger loggers.Logger
// If set, it will be run before we do any duplicate checks for modules // If set, it will be run before we do any duplicate checks for modules
// etc. // etc.

View file

@ -124,11 +124,11 @@ type ModulesConfig struct {
GoModulesFilename string GoModulesFilename string
} }
func (m *ModulesConfig) setActiveMods(logger *loggers.Logger) error { func (m *ModulesConfig) setActiveMods(logger loggers.Logger) error {
var activeMods Modules var activeMods Modules
for _, mod := range m.AllModules { for _, mod := range m.AllModules {
if !mod.Config().HugoVersion.IsValid() { if !mod.Config().HugoVersion.IsValid() {
logger.WARN.Printf(`Module %q is not compatible with this Hugo version; run "hugo mod graph" for more information.`, mod.Path()) logger.Warnf(`Module %q is not compatible with this Hugo version; run "hugo mod graph" for more information.`, mod.Path())
} }
if !mod.Disabled() { if !mod.Disabled() {
activeMods = append(activeMods, mod) activeMods = append(activeMods, mod)
@ -140,7 +140,7 @@ func (m *ModulesConfig) setActiveMods(logger *loggers.Logger) error {
return nil return nil
} }
func (m *ModulesConfig) finalize(logger *loggers.Logger) error { func (m *ModulesConfig) finalize(logger loggers.Logger) error {
for _, mod := range m.AllModules { for _, mod := range m.AllModules {
m := mod.(*moduleAdapter) m := mod.(*moduleAdapter)
m.mounts = filterUnwantedMounts(m.mounts) m.mounts = filterUnwantedMounts(m.mounts)
@ -422,7 +422,7 @@ func (c *collector) applyThemeConfig(tc *moduleAdapter) error {
} }
themeCfg, err = metadecoders.Default.UnmarshalToMap(data, metadecoders.TOML) themeCfg, err = metadecoders.Default.UnmarshalToMap(data, metadecoders.TOML)
if err != nil { if err != nil {
c.logger.WARN.Printf("Failed to read module config for %q in %q: %s", tc.Path(), themeTOML, err) c.logger.Warnf("Failed to read module config for %q in %q: %s", tc.Path(), themeTOML, err)
} else { } else {
maps.ToLower(themeCfg) maps.ToLower(themeCfg)
} }
@ -480,7 +480,7 @@ func (c *collector) collect() {
defer c.logger.PrintTimerIfDelayed(time.Now(), "hugo: collected modules") defer c.logger.PrintTimerIfDelayed(time.Now(), "hugo: collected modules")
d := debounce.New(2 * time.Second) d := debounce.New(2 * time.Second)
d(func() { d(func() {
c.logger.FEEDBACK.Println("hugo: downloading modules …") c.logger.Println("hugo: downloading modules …")
}) })
defer d(func() {}) defer d(func() {})

View file

@ -38,7 +38,7 @@ type FrontMatterHandler struct {
// A map of all date keys configured, including any custom. // A map of all date keys configured, including any custom.
allDateKeys map[string]bool allDateKeys map[string]bool
logger *loggers.Logger logger loggers.Logger
} }
// FrontMatterDescriptor describes how to handle front matter for a given Page. // FrontMatterDescriptor describes how to handle front matter for a given Page.
@ -148,7 +148,7 @@ func (f FrontMatterHandler) newChainedFrontMatterFieldHandler(handlers ...frontM
// First successful handler wins. // First successful handler wins.
success, err := h(d) success, err := h(d)
if err != nil { if err != nil {
f.logger.ERROR.Println(err) f.logger.Errorln(err)
} else if success { } else if success {
return true, nil return true, nil
} }
@ -262,7 +262,7 @@ func toLowerSlice(in interface{}) []string {
// NewFrontmatterHandler creates a new FrontMatterHandler with the given logger and configuration. // NewFrontmatterHandler creates a new FrontMatterHandler with the given logger and configuration.
// If no logger is provided, one will be created. // If no logger is provided, one will be created.
func NewFrontmatterHandler(logger *loggers.Logger, cfg config.Provider) (FrontMatterHandler, error) { func NewFrontmatterHandler(logger loggers.Logger, cfg config.Provider) (FrontMatterHandler, error) {
if logger == nil { if logger == nil {
logger = loggers.NewErrorLogger() logger = loggers.NewErrorLogger()

View file

@ -47,7 +47,7 @@ func NewSpec(
s *helpers.PathSpec, s *helpers.PathSpec,
fileCaches filecache.Caches, fileCaches filecache.Caches,
incr identity.Incrementer, incr identity.Incrementer,
logger *loggers.Logger, logger loggers.Logger,
errorHandler herrors.ErrorSender, errorHandler herrors.ErrorSender,
outputFormats output.Formats, outputFormats output.Formats,
mimeTypes media.Types) (*Spec, error) { mimeTypes media.Types) (*Spec, error) {
@ -105,7 +105,7 @@ type Spec struct {
MediaTypes media.Types MediaTypes media.Types
OutputFormats output.Formats OutputFormats output.Formats
Logger *loggers.Logger Logger loggers.Logger
ErrorSender herrors.ErrorSender ErrorSender herrors.ErrorSender
TextTemplates tpl.TemplateParseFinder TextTemplates tpl.TemplateParseFinder

View file

@ -121,7 +121,7 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
logger := t.rs.Logger logger := t.rs.Logger
var errBuf bytes.Buffer var errBuf bytes.Buffer
infoW := loggers.LoggerToWriterWithPrefix(logger.INFO, "babel") infoW := loggers.LoggerToWriterWithPrefix(logger.Info(), "babel")
if t.options.Config != "" { if t.options.Config != "" {
configFile = t.options.Config configFile = t.options.Config
@ -143,7 +143,7 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
var cmdArgs []string var cmdArgs []string
if configFile != "" { if configFile != "" {
logger.INFO.Println("babel: use config file", configFile) logger.Infoln("babel: use config file", configFile)
cmdArgs = []string{"--config-file", configFile} cmdArgs = []string{"--config-file", configFile}
} }

View file

@ -181,7 +181,7 @@ func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationC
var cmdArgs []string var cmdArgs []string
if configFile != "" { if configFile != "" {
logger.INFO.Println("postcss: use config file", configFile) logger.Infoln("postcss: use config file", configFile)
cmdArgs = []string{"--config", configFile} cmdArgs = []string{"--config", configFile}
} }
@ -192,7 +192,7 @@ func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationC
cmd := exec.Command(binary, cmdArgs...) cmd := exec.Command(binary, cmdArgs...)
var errBuf bytes.Buffer var errBuf bytes.Buffer
infoW := loggers.LoggerToWriterWithPrefix(logger.INFO, "postcss") infoW := loggers.LoggerToWriterWithPrefix(logger.Info(), "postcss")
cmd.Stdout = ctx.To cmd.Stdout = ctx.To
cmd.Stderr = io.MultiWriter(infoW, &errBuf) cmd.Stderr = io.MultiWriter(infoW, &errBuf)
@ -245,10 +245,10 @@ type importResolver struct {
contentSeen map[string]bool contentSeen map[string]bool
linemap map[int]fileOffset linemap map[int]fileOffset
fs afero.Fs fs afero.Fs
logger *loggers.Logger logger loggers.Logger
} }
func newImportResolver(r io.Reader, inPath string, fs afero.Fs, logger *loggers.Logger) *importResolver { func newImportResolver(r io.Reader, inPath string, fs afero.Fs, logger loggers.Logger) *importResolver {
return &importResolver{ return &importResolver{
r: r, r: r,
inPath: inPath, inPath: inPath,
@ -296,7 +296,7 @@ func (imp *importResolver) importRecursive(
importContent, hash := imp.contentHash(filename) importContent, hash := imp.contentHash(filename)
if importContent == nil { if importContent == nil {
trackLine(i, offset, "ERROR") trackLine(i, offset, "ERROR")
imp.logger.WARN.Printf("postcss: Failed to resolve CSS @import in %q for path %q", inPath, filename) imp.logger.Warnf("postcss: Failed to resolve CSS @import in %q for path %q", inPath, filename)
continue continue
} }

View file

@ -290,7 +290,7 @@ func (r *resourceAdapter) publish() {
r.publisherErr = r.target.Publish() r.publisherErr = r.target.Publish()
if r.publisherErr != nil { if r.publisherErr != nil {
r.spec.Logger.ERROR.Printf("Failed to publish Resource: %s", r.publisherErr) r.spec.Logger.Errorf("Failed to publish Resource: %s", r.publisherErr)
} }
}) })
@ -546,7 +546,7 @@ func (r *resourceAdapter) initTransform(publish, setContent bool) {
if r.spec.ErrorSender != nil { if r.spec.ErrorSender != nil {
r.spec.ErrorSender.SendError(r.transformationsErr) r.spec.ErrorSender.SendError(r.transformationsErr)
} else { } else {
r.spec.Logger.ERROR.Printf("Transformation failed: %s", r.transformationsErr) r.spec.Logger.Errorf("Transformation failed: %s", r.transformationsErr)
} }
} }
}) })

View file

@ -23,6 +23,9 @@ import (
"net/http" "net/http"
"strings" "strings"
"github.com/gohugoio/hugo/common/constants"
"github.com/gohugoio/hugo/common/loggers"
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/cache/filecache"
@ -85,7 +88,7 @@ func (ns *Namespace) GetCSV(sep string, urlParts ...interface{}) (d [][]string,
err = ns.getResource(cache, unmarshal, req) err = ns.getResource(cache, unmarshal, req)
if err != nil { if err != nil {
ns.deps.Log.ERROR.Printf("Failed to get CSV resource %q: %s", url, err) ns.deps.Log.(loggers.IgnorableLogger).Errorsf(constants.ErrRemoteGetCSV, "Failed to get CSV resource %q: %s", url, err)
return nil, nil return nil, nil
} }
@ -117,7 +120,7 @@ func (ns *Namespace) GetJSON(urlParts ...interface{}) (interface{}, error) {
err = ns.getResource(cache, unmarshal, req) err = ns.getResource(cache, unmarshal, req)
if err != nil { if err != nil {
ns.deps.Log.ERROR.Printf("Failed to get JSON resource %q: %s", url, err) ns.deps.Log.(loggers.IgnorableLogger).Errorsf(constants.ErrRemoteGetJSON, "Failed to get JSON resource %q: %s", url, err)
return nil, nil return nil, nil
} }

View file

@ -108,14 +108,14 @@ func TestGetCSV(t *testing.T) {
got, err := ns.GetCSV(test.sep, test.url) got, err := ns.GetCSV(test.sep, test.url)
if _, ok := test.expect.(bool); ok { if _, ok := test.expect.(bool); ok {
c.Assert(int(ns.deps.Log.ErrorCounter.Count()), qt.Equals, 1) c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 1)
//c.Assert(err, msg, qt.Not(qt.IsNil)) //c.Assert(err, msg, qt.Not(qt.IsNil))
c.Assert(got, qt.IsNil) c.Assert(got, qt.IsNil)
continue continue
} }
c.Assert(err, qt.IsNil, msg) c.Assert(err, qt.IsNil, msg)
c.Assert(int(ns.deps.Log.ErrorCounter.Count()), qt.Equals, 0) c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0)
c.Assert(got, qt.Not(qt.IsNil), msg) c.Assert(got, qt.Not(qt.IsNil), msg)
c.Assert(got, qt.DeepEquals, test.expect, msg) c.Assert(got, qt.DeepEquals, test.expect, msg)
@ -198,12 +198,12 @@ func TestGetJSON(t *testing.T) {
got, _ := ns.GetJSON(test.url) got, _ := ns.GetJSON(test.url)
if _, ok := test.expect.(bool); ok { if _, ok := test.expect.(bool); ok {
c.Assert(int(ns.deps.Log.ErrorCounter.Count()), qt.Equals, 1) c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 1)
//c.Assert(err, msg, qt.Not(qt.IsNil)) //c.Assert(err, msg, qt.Not(qt.IsNil))
continue continue
} }
c.Assert(int(ns.deps.Log.ErrorCounter.Count()), qt.Equals, 0, msg) c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0, msg)
c.Assert(got, qt.Not(qt.IsNil), msg) c.Assert(got, qt.Not(qt.IsNil), msg)
c.Assert(got, qt.DeepEquals, test.expect) c.Assert(got, qt.DeepEquals, test.expect)
} }

View file

@ -45,7 +45,7 @@ func (ns *Namespace) getRemote(cache *filecache.Cache, unmarshal func([]byte) (b
var err error var err error
handled = true handled = true
for i := 0; i <= resRetries; i++ { for i := 0; i <= resRetries; i++ {
ns.deps.Log.INFO.Printf("Downloading: %s ...", url) ns.deps.Log.Infof("Downloading: %s ...", url)
var res *http.Response var res *http.Response
res, err = ns.client.Do(req) res, err = ns.client.Do(req)
if err != nil { if err != nil {
@ -75,8 +75,8 @@ func (ns *Namespace) getRemote(cache *filecache.Cache, unmarshal func([]byte) (b
return nil, err return nil, err
} }
ns.deps.Log.INFO.Printf("Cannot read remote resource %s: %s", url, err) ns.deps.Log.Infof("Cannot read remote resource %s: %s", url, err)
ns.deps.Log.INFO.Printf("Retry #%d for %s and sleeping for %s", i+1, url, resSleep) ns.deps.Log.Infof("Retry #%d for %s and sleeping for %s", i+1, url, resSleep)
time.Sleep(resSleep) time.Sleep(resSleep)
} }

View file

@ -195,13 +195,13 @@ func newDeps(cfg config.Provider) *deps.Deps {
} }
cfg.Set("allModules", modules.Modules{mod}) cfg.Set("allModules", modules.Modules{mod})
cs, err := helpers.NewContentSpec(cfg, loggers.NewErrorLogger(), afero.NewMemMapFs()) logger := loggers.NewIgnorableLogger(loggers.NewErrorLogger(), "none")
cs, err := helpers.NewContentSpec(cfg, logger, afero.NewMemMapFs())
if err != nil { if err != nil {
panic(err) panic(err)
} }
fs := hugofs.NewMem(cfg) fs := hugofs.NewMem(cfg)
logger := loggers.NewErrorLogger()
p, err := helpers.NewPathSpec(fs, cfg, nil) p, err := helpers.NewPathSpec(fs, cfg, nil)
if err != nil { if err != nil {
@ -219,7 +219,7 @@ func newDeps(cfg config.Provider) *deps.Deps {
FileCaches: fileCaches, FileCaches: fileCaches,
ContentSpec: cs, ContentSpec: cs,
Log: logger, Log: logger,
DistinctErrorLog: helpers.NewDistinctLogger(logger.ERROR), DistinctErrorLog: helpers.NewDistinctLogger(logger.Error()),
} }
} }

View file

@ -24,8 +24,8 @@ import (
// New returns a new instance of the fmt-namespaced template functions. // New returns a new instance of the fmt-namespaced template functions.
func New(d *deps.Deps) *Namespace { func New(d *deps.Deps) *Namespace {
ns := &Namespace{ ns := &Namespace{
errorLogger: helpers.NewDistinctLogger(d.Log.ERROR), errorLogger: helpers.NewDistinctLogger(d.Log.Error()),
warnLogger: helpers.NewDistinctLogger(d.Log.WARN), warnLogger: helpers.NewDistinctLogger(d.Log.Warn()),
} }
d.BuildStartListeners.Add(func() { d.BuildStartListeners.Add(func() {