You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by zr...@apache.org on 2021/09/29 19:08:06 UTC

[trafficcontrol] branch master updated: Fix t3c report mode to be less spammy (#6220)

This is an automated email from the ASF dual-hosted git repository.

zrhoffman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new f394887  Fix t3c report mode to be less spammy (#6220)
f394887 is described below

commit f394887bbd1c6edad4812257e3ef39dd7dbeada7
Author: Robert O Butts <ro...@users.noreply.github.com>
AuthorDate: Wed Sep 29 13:06:34 2021 -0600

    Fix t3c report mode to be less spammy (#6220)
    
    * Fix t3c report mode to be less spammy
    
    Fixes #6201
    
    * Fix t3c sub-app logs.
    
    Fixes t3c sub-app logging to conform to the logger format,
    so all lines are prefixed, to prevent breaking
    people's log parsing.
---
 cache-config/t3c-apply/config/config.go       |  23 ++++-
 cache-config/t3c-apply/t3c-apply.go           |   8 +-
 cache-config/t3c-apply/torequest/cmd.go       | 140 +++++++++++++++-----------
 cache-config/t3c-apply/torequest/torequest.go |  30 +++---
 cache-config/t3c-apply/util/gitutil.go        |   1 +
 cache-config/t3c-diff/t3c-diff.go             |   6 +-
 lib/go-log/log.go                             |  48 ++++++---
 lib/go-log/standardlogger.go                  |   2 +-
 8 files changed, 159 insertions(+), 99 deletions(-)

diff --git a/cache-config/t3c-apply/config/config.go b/cache-config/t3c-apply/config/config.go
index 1c4f416..f283e91 100644
--- a/cache-config/t3c-apply/config/config.go
+++ b/cache-config/t3c-apply/config/config.go
@@ -239,7 +239,8 @@ func GetCfg() (Cfg, error) {
 	defaultClientTLSVersions := getopt.StringLong("default-client-tls-versions", 'V', "", "Comma-delimited list of default TLS versions for Delivery Services with no Parameter, e.g. --default-tls-versions='1.1,1.2,1.3'. If omitted, all versions are enabled.")
 	maxmindLocationPtr := getopt.StringLong("maxmind-location", 'M', "", "URL of a maxmind gzipped database file, to be installed into the trafficserver etc directory.")
 	verbosePtr := getopt.CounterLong("verbose", 'v', `Log verbosity. Logging is output to stderr. By default, errors are logged. To log warnings, pass '-v'. To log info, pass '-vv'. To omit error logging, see '-s'`)
-	silentPtr := getopt.BoolLong("silent", 's', `Silent. Errors are not logged, and the 'verbose' flag is ignored. If a fatal error occurs, the return code will be non-zero but no text will be output to stderr`)
+	const silentFlagName = "silent"
+	silentPtr := getopt.BoolLong(silentFlagName, 's', `Silent. Errors are not logged, and the 'verbose' flag is ignored. If a fatal error occurs, the return code will be non-zero but no text will be output to stderr`)
 
 	const waitForParentsFlagName = "wait-for-parents"
 	waitForParentsPtr := getopt.BoolLong(waitForParentsFlagName, 'W', "[true | false] do not update if parent_pending = 1 in the update json. Default is false")
@@ -282,6 +283,8 @@ badass     sets --install-packages=true
                 --ignore-update-flag=true
                 --update-ipallow=true
 report     sets --report-only=true
+                --no-unset-update-flag=true
+                --silent
 
 Note the 'syncds' settings are all the flag defaults. Hence, if no mode is set, the default is effectively 'syncds'.
 
@@ -332,6 +335,14 @@ If any of the related flags are also set, they override the mode's default behav
 				modeLogStrs = append(modeLogStrs, runMode.String()+" setting --"+reportOnlyFlagName+"="+"true")
 				*reportOnlyPtr = true
 			}
+			if !getopt.IsSet(ignoreUpdateFlagName) {
+				modeLogStrs = append(modeLogStrs, runMode.String()+" setting --"+ignoreUpdateFlagName+"="+"true")
+				*ignoreUpdateFlagPtr = true
+			}
+			if !getopt.IsSet(silentFlagName) {
+				modeLogStrs = append(modeLogStrs, runMode.String()+" setting --"+silentFlagName+"="+"true")
+				*silentPtr = true
+			}
 		}
 	}
 
@@ -511,9 +522,17 @@ If any of the related flags are also set, they override the mode's default behav
 	}
 
 	for _, str := range modeLogStrs {
+		str = strings.TrimSpace(str)
+		if str == "" {
+			continue
+		}
 		log.Infoln(str)
 	}
-	for msg := range toInfoLog {
+	for _, msg := range toInfoLog {
+		msg = strings.TrimSpace(msg)
+		if msg == "" {
+			continue
+		}
 		log.Infoln(msg)
 	}
 
diff --git a/cache-config/t3c-apply/t3c-apply.go b/cache-config/t3c-apply/t3c-apply.go
index ba75326..7498cb4 100644
--- a/cache-config/t3c-apply/t3c-apply.go
+++ b/cache-config/t3c-apply/t3c-apply.go
@@ -110,7 +110,7 @@ func main() {
 		}
 	}
 
-	log.Infoln(time.Now().Format(time.UnixDate))
+	log.Infoln(time.Now().Format(time.RFC3339))
 
 	if !util.CheckUser(cfg) {
 		lock.UnlockAndExit(UserCheckError)
@@ -231,12 +231,8 @@ func main() {
 		runSysctl(cfg)
 	}
 
-	// update Traffic Ops
-	result, err := trops.UpdateTrafficOps(&syncdsUpdate)
-	if err != nil {
+	if err := trops.UpdateTrafficOps(&syncdsUpdate); err != nil {
 		log.Errorf("failed to update Traffic Ops: %s\n", err.Error())
-	} else if result {
-		log.Infoln("Traffic Ops has been updated.")
 	}
 
 	GitCommitAndExit(Success, cfg)
diff --git a/cache-config/t3c-apply/torequest/cmd.go b/cache-config/t3c-apply/torequest/cmd.go
index 6d5e1dc..53fa7ec 100644
--- a/cache-config/t3c-apply/torequest/cmd.go
+++ b/cache-config/t3c-apply/torequest/cmd.go
@@ -27,6 +27,7 @@ import (
 	"errors"
 	"fmt"
 	"io/ioutil"
+	golog "log"
 	"os"
 	"os/exec"
 	"strconv"
@@ -81,12 +82,11 @@ func generate(cfg config.Cfg) ([]t3cutil.ATSConfigFile, error) {
 
 	generatedFiles, stdErr, code := t3cutil.DoInput(configData, config.GenerateCmd, args...)
 	if code != 0 {
-		return nil, fmt.Errorf("t3c-generate returned non-zero exit code %v stdout '%v' stderr '%v'", code, string(generatedFiles), string(stdErr))
-	}
-	if len(bytes.TrimSpace(stdErr)) > 0 {
-		log.Warnln(`t3c-generate stderr start` + "\n" + string(stdErr))
-		log.Warnln(`t3c-generate stderr end`)
+		logSubAppErr(`t3c-generate stdout`, generatedFiles)
+		logSubAppErr(`t3c-generate stderr`, stdErr)
+		return nil, fmt.Errorf("t3c-generate returned non-zero exit code %v, see log for output", code)
 	}
+	logSubApp(`t3c-generate`, stdErr)
 
 	preprocessedBytes, err := preprocess(cfg, configData, generatedFiles)
 	if err != nil {
@@ -156,11 +156,11 @@ func preprocess(cfg config.Cfg, configData []byte, generatedFiles []byte) ([]byt
 	stdOut := outbuf.Bytes()
 	stdErr := errbuf.Bytes()
 	if code != 0 {
-		return nil, fmt.Errorf("t3c-preprocess returned non-zero exit code %v stdout '%v' stderr '%v'", code, string(stdOut), string(stdErr))
-	}
-	if len(bytes.TrimSpace(stdErr)) > 0 {
-		log.Warnf("t3c-preprocess returned code 0 but stderr '%v'", string(stdErr)) // usually warnings
+		logSubAppErr(`t3c-preprocess stdout`, stdOut)
+		logSubAppErr(`t3c-preprocess stderr`, stdErr)
+		return nil, fmt.Errorf("t3c-preprocess returned non-zero exit code %v, see log for output", code)
 	}
+	logSubApp(`t3c-preprocess`, stdErr)
 	return stdOut, nil
 }
 
@@ -245,11 +245,11 @@ func sendUpdate(cfg config.Cfg, updateStatus bool, revalStatus bool) error {
 	}
 	stdOut, stdErr, code := t3cutil.Do(`t3c-update`, args...)
 	if code != 0 {
-		return fmt.Errorf("t3c-update returned non-zero exit code %v stdout '%v' stderr '%v'", code, string(stdOut), string(stdErr))
-	}
-	if len(bytes.TrimSpace(stdErr)) > 0 {
-		log.Warnf("t3c-update returned code 0 but stderr '%v'", string(stdErr)) // usually warnings
+		logSubAppErr(`t3c-update stdout`, stdOut)
+		logSubAppErr(`t3c-update stderr`, stdErr)
+		return fmt.Errorf("t3c-update returned non-zero exit code %v, see log for output", code)
 	}
+	logSubApp(`t3c-update`, stdErr)
 	log.Infoln("t3c-update succeeded")
 	return nil
 }
@@ -257,27 +257,44 @@ func sendUpdate(cfg config.Cfg, updateStatus bool, revalStatus bool) error {
 // diff calls t3c-diff to diff the given new file and the file on disk. Returns whether they're different.
 // Logs the difference.
 // If the file on disk doesn't exist, returns true and logs the entire file as a diff.
-func diff(cfg config.Cfg, newFile []byte, fileLocation string) (bool, error) {
+func diff(cfg config.Cfg, newFile []byte, fileLocation string, reportOnly bool) (bool, error) {
+	diffMsg := ""
+
 	stdOut, stdErr, code := t3cutil.DoInput(newFile, `t3c-diff`, `stdin`, fileLocation)
 	if code > 1 {
 		return false, fmt.Errorf("t3c-diff returned error code %v stdout '%v' stderr '%v'", code, string(stdOut), string(stdErr))
 	}
-	if len(bytes.TrimSpace(stdErr)) > 0 {
-		log.Warnf("t3c-diff returned non-error code %v but stderr '%v'", code, string(stdErr))
-	}
+	logSubApp(`t3c-diff`, stdErr)
 
 	if code == 0 {
-		log.Infof("All lines match TrOps for config file: %s\n", fileLocation)
+		diffMsg += fmt.Sprintf("All lines match TrOps for config file: %s\n", fileLocation)
 		return false, nil // 0 is only returned if there's no diff
 	}
 	// code 1 means a diff, difference text will be on stdout
 
+	stdOut = bytes.TrimSpace(stdOut) // the shell output includes a trailing newline that isn't part of the diff; remove it
 	lines := strings.Split(string(stdOut), "\n")
-	log.Infoln("file '" + fileLocation + "' changes begin")
+	diffMsg += "file '" + fileLocation + "' changes begin\n"
 	for _, line := range lines {
-		log.Infoln("diff: " + line)
+		diffMsg += "diff: " + line + "\n"
+	}
+	diffMsg += "file '" + fileLocation + "' changes end" // no trailing newline, becuase we're using log*ln, the last line will get a newline appropriately
+
+	if reportOnly {
+		// Create our own info logger, to log the diff.
+		// We can't use the logger initialized in the config package because
+		// we don't want to log all the other Info logs.
+		// But we want the standard log.Info prefix, timestamp, etc.
+		reportLocation := os.Stdout
+		goLogger := golog.New(reportLocation, log.InfoPrefix, log.InfoFlags)
+		for _, line := range strings.Split(diffMsg, "\n") {
+			log.Logln(goLogger, line)
+		}
+	} else {
+		for _, line := range strings.Split(diffMsg, "\n") {
+			log.Infoln(line)
+		}
 	}
-	log.Infoln("file '" + fileLocation + "' changes end")
 
 	return true, nil
 }
@@ -302,22 +319,12 @@ func checkRefs(cfg config.Cfg, cfgFile []byte, filesAdding []string) error {
 	stdOut, stdErr, code := t3cutil.DoInput(cfgFile, `t3c`, args...)
 
 	if code != 0 {
-		log.Errorf(`check-refs errors start
-` + string(stdOut))
-		log.Errorf(`check-refs errors end`)
-		if strings.TrimSpace(string(stdErr)) != "" {
-			log.Errorf(`check-refs output start
-` + string(stdErr))
-			log.Errorf(`check-refs output end`)
-		}
+		logSubAppErr(`t3c-check-refs stdout`, stdOut)
+		logSubAppErr(`t3c-check-refs stderr`, stdErr)
 		return fmt.Errorf("%d plugins failed to verify. See log for details.", code)
 	}
-	if len(bytes.TrimSpace(stdErr)) > 0 {
-		log.Warnf("t3c-check-refs returned non-error code %v but stderr '%v'", code, string(stdErr))
-	}
-	if len(bytes.TrimSpace(stdOut)) > 0 {
-		log.Warnf("t3c-check-refs returned non-error code %v but output '%v'", code, string(stdOut))
-	}
+	logSubApp(`t3c-check-refs stdout`, stdOut)
+	logSubApp(`t3c-check-refs stderr`, stdErr)
 	return nil
 }
 
@@ -331,21 +338,13 @@ func checkReload(pluginPackagesInstalled []string, changedConfigFiles []string)
 	)
 
 	if code != 0 {
-		log.Errorf(`t3c-check-reload errors start
-` + string(stdErr))
-		log.Errorf(`t3c-check-reload errors end`)
-		if strings.TrimSpace(string(stdErr)) != "" {
-			log.Errorf(`t3c-check-reload output start
-` + string(stdOut))
-			log.Errorf(`t3c-check-reload output end`)
-		}
+		logSubAppErr(`t3c-check-reload stdout`, stdOut)
+		logSubAppErr(`t3c-check-reload stderr`, stdErr)
 		return t3cutil.ServiceNeedsInvalid, fmt.Errorf("t3c-check-reload returned error code %d - see log for details.", code)
-	} else if strings.TrimSpace(string(stdErr)) != "" {
-		log.Errorf(`t3c-check-reload returned success code but nonempty stderr. determine-restart errors start
-` + string(stdErr))
-		log.Errorf(`t3c-check-reload errors end`)
-
 	}
+
+	logSubApp(`t3c-check-reload`, stdErr)
+
 	needs := t3cutil.StrToServiceNeeds(strings.TrimSpace(string(stdOut)))
 	if needs == t3cutil.ServiceNeedsInvalid {
 		return t3cutil.ServiceNeedsInvalid, errors.New("t3c-check-reload returned unknown string '" + string(stdOut) + "'")
@@ -395,11 +394,13 @@ func request(cfg config.Cfg, command string) ([]byte, error) {
 	}
 	stdOut, stdErr, code := t3cutil.Do(`t3c-request`, args...)
 	if code != 0 {
-		return nil, fmt.Errorf("t3c-request returned non-zero exit code %v stdout '%v' stderr '%v'", code, string(stdOut), string(stdErr))
-	}
-	if len(bytes.TrimSpace(stdErr)) > 0 {
-		log.Warnf("t3c-request returned code 0 but stderr '%v'", string(stdErr)) // usually warnings
+		logSubAppErr(`t3c-request stdout`, stdOut)
+		logSubAppErr(`t3c-request stderr`, stdErr)
+		return nil, fmt.Errorf("t3c-request returned non-zero exit code %v, see log for output", code)
 	}
+
+	logSubApp(`t3c-request`, stdErr)
+
 	return stdOut, nil
 }
 
@@ -459,11 +460,11 @@ func requestConfig(cfg config.Cfg) ([]byte, error) {
 		stdOut, stdErr, code = t3cutil.Do(`t3c`, args...)
 	}
 	if code != 0 {
-		return nil, fmt.Errorf("t3c-request returned non-zero exit code %v stdout '%v' stderr '%v'", code, string(stdOut), string(stdErr))
-	}
-	if len(bytes.TrimSpace(stdErr)) > 0 {
-		log.Warnf("t3c-request returned code 0 but stderr '%v'", string(stdErr)) // usually warnings
+		logSubAppErr(`t3c-request stdout`, stdOut)
+		logSubAppErr(`t3c-request stderr`, stdErr)
+		return nil, fmt.Errorf("t3c-request returned non-zero exit code %v, see log for details", code)
 	}
+	logSubApp(`t3c-request`, stdErr)
 
 	if err := ioutil.WriteFile(t3cutil.ApplyCachePath, stdOut, 0600); err != nil {
 		log.Errorln("writing config data to cache failed: " + err.Error())
@@ -472,6 +473,33 @@ func requestConfig(cfg config.Cfg) ([]byte, error) {
 	return stdOut, nil
 }
 
+func logSubApp(appName string, stdErr []byte)    { logSubAppWarnOrErr(appName, stdErr, false) }
+func logSubAppErr(appName string, stdErr []byte) { logSubAppWarnOrErr(appName, stdErr, true) }
+func logSubAppWarnOrErr(appName string, stdErr []byte, isErr bool) {
+	stdErr = bytes.TrimSpace(stdErr)
+	if len(stdErr) == 0 {
+		return
+	}
+
+	logF := log.Warnln
+	logger := log.Warning
+	if isErr {
+		logF = log.Errorln
+		logger = log.Error
+	}
+
+	if logger == nil {
+		return
+	}
+
+	logF(appName + ` start`)
+	// write directly to the underlying logger, to avoid duplicating the prefix
+	for _, msg := range bytes.Split(stdErr, []byte{'\n'}) {
+		logger.Writer().Write([]byte(string(msg) + "\n"))
+	}
+	logF(appName + ` end`)
+}
+
 // outToErr returns stderr if logLocation is stdout, otherwise returns logLocation unchanged.
 // This is a helper to avoid logging to stdout for commands whose output is on stdout.
 func outToErr(logLocation string) string {
diff --git a/cache-config/t3c-apply/torequest/torequest.go b/cache-config/t3c-apply/torequest/torequest.go
index f106471..2ba5b40 100644
--- a/cache-config/t3c-apply/torequest/torequest.go
+++ b/cache-config/t3c-apply/torequest/torequest.go
@@ -217,7 +217,7 @@ func (r *TrafficOpsReq) checkConfigFile(cfg *ConfigFile, filesAdding []string) e
 		log.Infoln("Successfully verified plugins used by '" + cfg.Name + "'")
 	}
 
-	changeNeeded, err := diff(r.Cfg, cfg.Body, cfg.Path)
+	changeNeeded, err := diff(r.Cfg, cfg.Body, cfg.Path, r.Cfg.ReportOnly)
 	if err != nil {
 		return errors.New("getting diff: " + err.Error())
 	}
@@ -1012,9 +1012,7 @@ func (r *TrafficOpsReq) RevalidateWhileSleeping() (UpdateStatus, error) {
 			return updateStatus, errors.New("failed to start services: " + err.Error())
 		}
 
-		// update Traffic Ops
-		_, err = r.UpdateTrafficOps(&updateStatus)
-		if err != nil {
+		if err := r.UpdateTrafficOps(&updateStatus); err != nil {
 			log.Errorf("failed to update Traffic Ops: %s\n", err.Error())
 		}
 
@@ -1117,12 +1115,12 @@ func (r *TrafficOpsReq) getPluginPackagesInstalled() []string {
 	return installedPluginPkgs
 }
 
-func (r *TrafficOpsReq) UpdateTrafficOps(syncdsUpdate *UpdateStatus) (bool, error) {
+func (r *TrafficOpsReq) UpdateTrafficOps(syncdsUpdate *UpdateStatus) error {
 	var updateResult bool
 
 	serverStatus, err := getUpdateStatus(r.Cfg)
 	if err != nil {
-		return false, errors.New("failed to update Traffic Ops: " + err.Error())
+		return errors.New("failed to update Traffic Ops: " + err.Error())
 	}
 
 	if *syncdsUpdate == UpdateTropsNotNeeded && (serverStatus.UpdatePending == true || serverStatus.RevalPending == true) {
@@ -1130,21 +1128,21 @@ func (r *TrafficOpsReq) UpdateTrafficOps(syncdsUpdate *UpdateStatus) (bool, erro
 		log.Errorln("Traffic Ops is signaling that an update is ready to be applied but, none was found! Clearing update state in Traffic Ops anyway.")
 	} else if *syncdsUpdate == UpdateTropsNotNeeded {
 		log.Errorln("Traffic Ops does not require an update at this time")
-		return true, nil
+		return nil
 	} else if *syncdsUpdate == UpdateTropsFailed {
 		log.Errorln("Traffic Ops requires an update but, applying the update locally failed.  Traffic Ops is not being updated.")
-		return true, nil
+		return nil
 	} else if *syncdsUpdate == UpdateTropsSuccessful {
 		updateResult = true
 		log.Errorln("Traffic Ops requires an update and it was applied successfully.  Clearing update state in Traffic Ops.")
 	}
 
 	if !updateResult {
-		return true, nil
+		return nil
 	}
 	if r.Cfg.ReportOnly {
 		log.Errorln("In Report mode and Traffic Ops needs updated you should probably do that manually.")
-		return true, nil
+		return nil
 	}
 
 	if !r.Cfg.ReportOnly && !r.Cfg.NoUnsetUpdateFlag {
@@ -1161,12 +1159,10 @@ func (r *TrafficOpsReq) UpdateTrafficOps(syncdsUpdate *UpdateStatus) (bool, erro
 				err = sendUpdate(r.Cfg, false, false)
 			}
 		}
+		if err != nil {
+			return errors.New("Traffic Ops Update failed: " + err.Error())
+		}
+		log.Infoln("Traffic Ops has been updated.")
 	}
-
-	if err != nil {
-		return false, errors.New("Traffic Ops Update failed: " + err.Error())
-	}
-
-	log.Errorln("Traffic Ops has been updated.")
-	return true, nil
+	return nil
 }
diff --git a/cache-config/t3c-apply/util/gitutil.go b/cache-config/t3c-apply/util/gitutil.go
index ef3e9e2..9dca3db 100644
--- a/cache-config/t3c-apply/util/gitutil.go
+++ b/cache-config/t3c-apply/util/gitutil.go
@@ -140,6 +140,7 @@ func MakeGitCommitAll(cfg config.Cfg, self bool, success bool) error {
 		cmd := exec.Command("git", "status", "--porcelain")
 		cmd.Dir = cfg.TsConfigDir
 		output, err := cmd.CombinedOutput()
+		output = bytes.TrimSpace(output)
 		if err != nil {
 			return fmt.Errorf("git status error: in config dir '%v' returned err %v msg '%v'", cfg.TsConfigDir, err, string(output))
 		}
diff --git a/cache-config/t3c-diff/t3c-diff.go b/cache-config/t3c-diff/t3c-diff.go
index 854047f..22a1d44 100644
--- a/cache-config/t3c-diff/t3c-diff.go
+++ b/cache-config/t3c-diff/t3c-diff.go
@@ -21,13 +21,15 @@ package main
 
 import (
 	"errors"
-	"github.com/apache/trafficcontrol/lib/go-log"
+	"fmt"
 	"io/ioutil"
 	"os"
 	"regexp"
 	"strings"
 
 	"github.com/apache/trafficcontrol/cache-config/t3cutil"
+	"github.com/apache/trafficcontrol/lib/go-log"
+
 	"github.com/kylelemons/godebug/diff"
 	"github.com/pborman/getopt/v2"
 )
@@ -81,7 +83,7 @@ func main() {
 		match := regexp.MustCompile(`(?m)^\+.*|^-.*`)
 		changes := diff.Diff(fileA, fileB)
 		for _, change := range match.FindAllString(changes, -1) {
-			log.Infoln(change)
+			fmt.Println(change)
 		}
 		os.Exit(1)
 	}
diff --git a/lib/go-log/log.go b/lib/go-log/log.go
index afb20e3..8484472 100644
--- a/lib/go-log/log.go
+++ b/lib/go-log/log.go
@@ -63,23 +63,41 @@ func initLogger(logger **log.Logger, oldLogCloser *io.Closer, newLogWriter io.Wr
 	*oldLogCloser = newLogWriter
 }
 
+const DebugPrefix = "DEBUG: "
+const InfoPrefix = "INFO: "
+const WarnPrefix = "WARNING: "
+const ErrPrefix = "ERROR: "
+const EventPrefix = ""
+
+const DebugFlags = log.Lshortfile
+const InfoFlags = log.Lshortfile
+const WarnFlags = log.Lshortfile
+const ErrFlags = log.Lshortfile
+const EventFlags = 0
+
 // Init initailizes the logs with the given io.WriteClosers. If `Init` was previously called, existing loggers are Closed. If you have loggers which are not Closers or which must not be Closed, wrap them with `log.NopCloser`.
 func Init(eventW, errW, warnW, infoW, debugW io.WriteCloser) {
-	initLogger(&Debug, &debugCloser, debugW, "DEBUG: ", log.Lshortfile)
-	initLogger(&Info, &infoCloser, infoW, "INFO: ", log.Lshortfile)
-	initLogger(&Warning, &warnCloser, warnW, "WARNING: ", log.Lshortfile)
-	initLogger(&Error, &errCloser, errW, "ERROR: ", log.Lshortfile)
-	initLogger(&Event, &eventCloser, eventW, "", 0)
+	initLogger(&Debug, &debugCloser, debugW, DebugPrefix, DebugFlags)
+	initLogger(&Info, &infoCloser, infoW, InfoPrefix, InfoFlags)
+	initLogger(&Warning, &warnCloser, warnW, WarnPrefix, WarnFlags)
+	initLogger(&Error, &errCloser, errW, ErrPrefix, ErrFlags)
+	initLogger(&Event, &eventCloser, eventW, EventPrefix, EventFlags)
 }
 
-func logf(logger *log.Logger, format string, v ...interface{}) {
+// Logf should generally be avoided, use the built-in Init or InitCfg and Errorf, Warnln, etc functions instead.
+// It logs to the given logger, in the same format as the standard log functions.
+// This should only be used in rare and unusual circumstances when the standard loggers and functions can't.
+func Logf(logger *log.Logger, format string, v ...interface{}) {
 	if logger == nil {
 		return
 	}
 	logger.Output(stackFrame, time.Now().UTC().Format(timeFormat)+": "+fmt.Sprintf(format, v...))
 }
 
-func logln(logger *log.Logger, v ...interface{}) {
+// Logln should generally be avoided, use the built-in Init or InitCfg and Errorf, Warnln, etc functions instead.
+// It logs to the given logger, in the same format as the standard log functions.
+// This should only be used in rare and unusual circumstances when the standard loggers and functions can't.
+func Logln(logger *log.Logger, v ...interface{}) {
 	if logger == nil {
 		return
 	}
@@ -89,14 +107,14 @@ func logln(logger *log.Logger, v ...interface{}) {
 const timeFormat = time.RFC3339Nano
 const stackFrame = 3
 
-func Errorf(format string, v ...interface{}) { logf(Error, format, v...) }
-func Errorln(v ...interface{})               { logln(Error, v...) }
-func Warnf(format string, v ...interface{})  { logf(Warning, format, v...) }
-func Warnln(v ...interface{})                { logln(Warning, v...) }
-func Infof(format string, v ...interface{})  { logf(Info, format, v...) }
-func Infoln(v ...interface{})                { logln(Info, v...) }
-func Debugf(format string, v ...interface{}) { logf(Debug, format, v...) }
-func Debugln(v ...interface{})               { logln(Debug, v...) }
+func Errorf(format string, v ...interface{}) { Logf(Error, format, v...) }
+func Errorln(v ...interface{})               { Logln(Error, v...) }
+func Warnf(format string, v ...interface{})  { Logf(Warning, format, v...) }
+func Warnln(v ...interface{})                { Logln(Warning, v...) }
+func Infof(format string, v ...interface{})  { Logf(Info, format, v...) }
+func Infoln(v ...interface{})                { Logln(Info, v...) }
+func Debugf(format string, v ...interface{}) { Logf(Debug, format, v...) }
+func Debugln(v ...interface{})               { Logln(Debug, v...) }
 
 const eventFormat = "%.3f %s"
 
diff --git a/lib/go-log/standardlogger.go b/lib/go-log/standardlogger.go
index 71c775d..3df5d2e 100644
--- a/lib/go-log/standardlogger.go
+++ b/lib/go-log/standardlogger.go
@@ -43,6 +43,6 @@ type standardLoggerWriter struct {
 // The writer.realLogger may be nil, in which case this does nothing.
 // This always returns len(p) and nil, claiming it successfully wrote even if it didn't.
 func (writer *standardLoggerWriter) Write(p []byte) (n int, err error) {
-	logln(writer.realLogger, writer.prefix+strings.TrimSpace(string(p)))
+	Logln(writer.realLogger, writer.prefix+strings.TrimSpace(string(p)))
 	return len(p), nil
 }