From 14b098bac22343de959779be03dfdf7c59780fca Mon Sep 17 00:00:00 2001 From: Azareal Date: Wed, 7 Apr 2021 12:10:05 +1000 Subject: [PATCH] Add DisableStdout config setting. Add DisableStderr config setting. Eliminate boilerplate in main.go Increase the number of cached q strings. Use the ErrLogger in LogError() and LogWarning() Add the experimental LocalErrorf() Add Err() log function. --- common/common.go | 15 ++- common/errors.go | 9 +- common/site.go | 2 + docs/configuration.md | 4 + main.go | 286 ++++++++++++++++++++++-------------------- 5 files changed, 174 insertions(+), 142 deletions(-) diff --git a/common/common.go b/common/common.go index 2bb8672f..c876675a 100644 --- a/common/common.go +++ b/common/common.go @@ -167,7 +167,9 @@ func StoppedServer(msg ...interface{}) { var StopServerChan = make(chan []interface{}) -var LogWriter = io.MultiWriter(os.Stderr) +var LogWriter = io.MultiWriter(os.Stdout) +var ErrLogWriter = io.MultiWriter(os.Stderr) +var ErrLogger = log.New(os.Stderr, "", log.LstdFlags) func DebugDetail(args ...interface{}) { if Dev.SuperDebug { @@ -196,6 +198,9 @@ func DebugLogf(str string, args ...interface{}) { func Log(args ...interface{}) { log.Print(args...) } +func Err(args ...interface{}) { + ErrLogger.Print(args...) +} func Logf(str string, args ...interface{}) { log.Printf(str, args...) @@ -223,10 +228,10 @@ func eachall(stmt *sql.Stmt, f func(r *sql.Rows) error) error { return rows.Err() } -var qcache = []string{0: "?", 1: "?,?", 2: "?,?,?", 3: "?,?,?,?", 4: "?,?,?,?,?", 5: "?,?,?,?,?,?", 6: "?,?,?,?,?,?,?", 7: "?,?,?,?,?,?,?,?"} +var qcache = []string{0: "?", 1: "?,?", 2: "?,?,?", 3: "?,?,?,?", 4: "?,?,?,?,?", 5: "?,?,?,?,?,?", 6: "?,?,?,?,?,?,?", 7: "?,?,?,?,?,?,?,?", 8: "?,?,?,?,?,?,?,?,?"} func inqbuild(ids []int) ([]interface{}, string) { - if len(ids) < 7 { + if len(ids) < 8 { idList := make([]interface{}, len(ids)) for i, id := range ids { idList[i] = strconv.Itoa(id) @@ -249,7 +254,7 @@ func inqbuild(ids []int) ([]interface{}, string) { } func inqbuild2(count int) string { - if count <= 7 { + if count <= 8 { return qcache[count-1] } var sb strings.Builder @@ -265,7 +270,7 @@ func inqbuild2(count int) string { } func inqbuildstr(strs []string) ([]interface{}, string) { - if len(strs) < 7 { + if len(strs) < 8 { idList := make([]interface{}, len(strs)) for i, id := range strs { idList[i] = id diff --git a/common/errors.go b/common/errors.go index d4405ff7..7f24802e 100644 --- a/common/errors.go +++ b/common/errors.go @@ -1,6 +1,7 @@ package common import ( + "fmt" "log" "net/http" "runtime/debug" @@ -105,7 +106,7 @@ func SysError(errmsg string) RouteError { // TODO: Clean-up extra as a way of passing additional context func LogError(err error, extra ...string) { LogWarning(err, extra...) - log.Fatal("") + ErrLogger.Fatal("") } func LogWarning(err error, extra ...string) { @@ -121,7 +122,7 @@ func LogWarning(err error, extra ...string) { errorBufferMutex.Lock() defer errorBufferMutex.Unlock() stack := debug.Stack() // debug.Stack() can't be executed concurrently, so we'll guard this with a mutex too - log.Print(errmsg+"\n", string(stack)) + Err(errmsg+"\n", string(stack)) errorBuffer = append(errorBuffer, ErrorItem{err, stack}) } @@ -220,6 +221,10 @@ func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user *Use return SimpleError(errmsg, w, r, errorHeader(w, user, "")) } +func LocalErrorf(errmsg string, w http.ResponseWriter, r *http.Request, user *User, params ...interface{}) RouteError { + return LocalError(fmt.Sprintf(errmsg, params), w, r, user) +} + func SimpleError(errmsg string, w http.ResponseWriter, r *http.Request, h *Header) RouteError { if h == nil { h = errorHeader(w, &GuestUser, phrases.GetErrorPhrase("local_error_title")) diff --git a/common/site.go b/common/site.go index 5ce3817e..411602b0 100644 --- a/common/site.go +++ b/common/site.go @@ -138,6 +138,8 @@ type config struct { LogDir string DisableSuspLog bool DisableBadRouteLog bool + DisableStdout bool + DisableStderr bool } type devConfig struct { diff --git a/docs/configuration.md b/docs/configuration.md index f3b22551..33afb377 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -152,6 +152,10 @@ DisableSuspLog - Whether suspicious requests are logged in the suspicious reques DisableBadRouteLog - Whether requests referencing routes which don't exist should be individually logged. Enabling this may make a site faster. Default: false +DisableStdout - Stop writing logs to stdout. Default: false. + +DisableStderr - Stop writing errors to stderr. Default: false + Related: https://support.cloudflare.com/hc/en-us/articles/212794707-General-Best-Practices-for-Load-Balancing-at-your-origin-with-Cloudflare diff --git a/main.go b/main.go index 7a1338f0..2d5ad60f 100644 --- a/main.go +++ b/main.go @@ -124,72 +124,77 @@ func afterDBInit() (err error) { // Experimenting with a new error package here to try to reduce the amount of debugging we have to do // TODO: Dynamically register these items to avoid maintaining as much code here? -func storeInit() (err error) { +func storeInit() (e error) { acc := qgen.NewAcc() + ws := errors.WithStack var rcache c.ReplyCache if c.Config.ReplyCache == "static" { rcache = c.NewMemoryReplyCache(c.Config.ReplyCacheCapacity) } - c.Rstore, err = c.NewSQLReplyStore(acc, rcache) - if err != nil { - return errors.WithStack(err) + c.Rstore, e = c.NewSQLReplyStore(acc, rcache) + if e != nil { + return ws(e) } - c.Prstore, err = c.NewSQLProfileReplyStore(acc) - if err != nil { - return errors.WithStack(err) + c.Prstore, e = c.NewSQLProfileReplyStore(acc) + if e != nil { + return ws(e) } - c.Likes, err = c.NewDefaultLikeStore(acc) - if err != nil { - return errors.WithStack(err) + c.Likes, e = c.NewDefaultLikeStore(acc) + if e != nil { + return ws(e) } - c.Convos, err = c.NewDefaultConversationStore(acc) - if err != nil { - return errors.WithStack(err) + c.ForumActionStore, e = c.NewDefaultForumActionStore(acc) + if e != nil { + return ws(e) } - c.UserBlocks, err = c.NewDefaultBlockStore(acc) - if err != nil { - return errors.WithStack(err) + c.Convos, e = c.NewDefaultConversationStore(acc) + if e != nil { + return ws(e) } - c.GroupPromotions, err = c.NewDefaultGroupPromotionStore(acc) - if err != nil { - return errors.WithStack(err) + c.UserBlocks, e = c.NewDefaultBlockStore(acc) + if e != nil { + return ws(e) + } + c.GroupPromotions, e = c.NewDefaultGroupPromotionStore(acc) + if e != nil { + return ws(e) } - if err = p.InitPhrases(c.Site.Language); err != nil { - return errors.WithStack(err) + if e = p.InitPhrases(c.Site.Language); e != nil { + return ws(e) } - if err = c.InitEmoji(); err != nil { - return errors.WithStack(err) + if e = c.InitEmoji(); e != nil { + return ws(e) } - if err = c.InitWeakPasswords(); err != nil { - return errors.WithStack(err) + if e = c.InitWeakPasswords(); e != nil { + return ws(e) } log.Print("Loading the static files.") - if err = c.Themes.LoadStaticFiles(); err != nil { - return errors.WithStack(err) + if e = c.Themes.LoadStaticFiles(); e != nil { + return ws(e) } - if err = c.StaticFiles.Init(); err != nil { - return errors.WithStack(err) + if e = c.StaticFiles.Init(); e != nil { + return ws(e) } - if err = c.StaticFiles.JSTmplInit(); err != nil { - return errors.WithStack(err) + if e = c.StaticFiles.JSTmplInit(); e != nil { + return ws(e) } log.Print("Initialising the widgets") c.Widgets = c.NewDefaultWidgetStore() - if err = c.InitWidgets(); err != nil { - return errors.WithStack(err) + if e = c.InitWidgets(); e != nil { + return ws(e) } log.Print("Initialising the menu item list") c.Menus = c.NewDefaultMenuStore() - if err = c.Menus.Load(1); err != nil { // 1 = the default menu - return errors.WithStack(err) + if e = c.Menus.Load(1); e != nil { // 1 = the default menu + return ws(e) } - menuHold, err := c.Menus.Get(1) - if err != nil { - return errors.WithStack(err) + menuHold, e := c.Menus.Get(1) + if e != nil { + return ws(e) } fmt.Printf("menuHold: %+v\n", menuHold) var b bytes.Buffer @@ -197,147 +202,147 @@ func storeInit() (err error) { fmt.Println("menuHold output: ", string(b.Bytes())) log.Print("Initialising the authentication system") - c.Auth, err = c.NewDefaultAuth() - if err != nil { - return errors.WithStack(err) + c.Auth, e = c.NewDefaultAuth() + if e != nil { + return ws(e) } log.Print("Initialising the stores") - c.WordFilters, err = c.NewDefaultWordFilterStore(acc) - if err != nil { - return errors.WithStack(err) + c.WordFilters, e = c.NewDefaultWordFilterStore(acc) + if e != nil { + return ws(e) } - c.MFAstore, err = c.NewSQLMFAStore(acc) - if err != nil { - return errors.WithStack(err) + c.MFAstore, e = c.NewSQLMFAStore(acc) + if e != nil { + return ws(e) } - c.Pages, err = c.NewDefaultPageStore(acc) - if err != nil { - return errors.WithStack(err) + c.Pages, e = c.NewDefaultPageStore(acc) + if e != nil { + return ws(e) } - c.Reports, err = c.NewDefaultReportStore(acc) - if err != nil { - return errors.WithStack(err) + c.Reports, e = c.NewDefaultReportStore(acc) + if e != nil { + return ws(e) } - c.Emails, err = c.NewDefaultEmailStore(acc) - if err != nil { - return errors.WithStack(err) + c.Emails, e = c.NewDefaultEmailStore(acc) + if e != nil { + return ws(e) } - c.LoginLogs, err = c.NewLoginLogStore(acc) - if err != nil { - return errors.WithStack(err) + c.LoginLogs, e = c.NewLoginLogStore(acc) + if e != nil { + return ws(e) } - c.RegLogs, err = c.NewRegLogStore(acc) - if err != nil { - return errors.WithStack(err) + c.RegLogs, e = c.NewRegLogStore(acc) + if e != nil { + return ws(e) } - c.ModLogs, err = c.NewModLogStore(acc) - if err != nil { - return errors.WithStack(err) + c.ModLogs, e = c.NewModLogStore(acc) + if e != nil { + return ws(e) } - c.AdminLogs, err = c.NewAdminLogStore(acc) - if err != nil { - return errors.WithStack(err) + c.AdminLogs, e = c.NewAdminLogStore(acc) + if e != nil { + return ws(e) } - c.IPSearch, err = c.NewDefaultIPSearcher() - if err != nil { - return errors.WithStack(err) + c.IPSearch, e = c.NewDefaultIPSearcher() + if e != nil { + return ws(e) } if c.Config.Search == "" || c.Config.Search == "sql" { - c.RepliesSearch, err = c.NewSQLSearcher(acc) - if err != nil { - return errors.WithStack(err) + c.RepliesSearch, e = c.NewSQLSearcher(acc) + if e != nil { + return ws(e) } } - c.Subscriptions, err = c.NewDefaultSubscriptionStore() - if err != nil { - return errors.WithStack(err) + c.Subscriptions, e = c.NewDefaultSubscriptionStore() + if e != nil { + return ws(e) } - c.Attachments, err = c.NewDefaultAttachmentStore(acc) - if err != nil { - return errors.WithStack(err) + c.Attachments, e = c.NewDefaultAttachmentStore(acc) + if e != nil { + return ws(e) } - c.Polls, err = c.NewDefaultPollStore(c.NewMemoryPollCache(100)) // TODO: Max number of polls held in cache, make this a config item - if err != nil { - return errors.WithStack(err) + c.Polls, e = c.NewDefaultPollStore(c.NewMemoryPollCache(100)) // TODO: Max number of polls held in cache, make this a config item + if e != nil { + return ws(e) } - c.TopicList, err = c.NewDefaultTopicList(acc) - if err != nil { - return errors.WithStack(err) + c.TopicList, e = c.NewDefaultTopicList(acc) + if e != nil { + return ws(e) } - c.PasswordResetter, err = c.NewDefaultPasswordResetter(acc) - if err != nil { - return errors.WithStack(err) + c.PasswordResetter, e = c.NewDefaultPasswordResetter(acc) + if e != nil { + return ws(e) } - c.Activity, err = c.NewDefaultActivityStream(acc) - if err != nil { - return errors.WithStack(err) + c.Activity, e = c.NewDefaultActivityStream(acc) + if e != nil { + return ws(e) } // TODO: Let the admin choose other thumbnailers, maybe ones defined in plugins c.Thumbnailer = c.NewCaireThumbnailer() - c.Recalc, err = c.NewDefaultRecalc(acc) - if err != nil { - return errors.WithStack(err) + c.Recalc, e = c.NewDefaultRecalc(acc) + if e != nil { + return ws(e) } log.Print("Initialising the meta store") - c.Meta, err = meta.NewDefaultMetaStore(acc) - if err != nil { - return errors.WithStack(err) + c.Meta, e = meta.NewDefaultMetaStore(acc) + if e != nil { + return ws(e) } log.Print("Initialising the view counters") if !c.Config.DisableAnalytics { - co.GlobalViewCounter, err = co.NewGlobalViewCounter(acc) - if err != nil { - return errors.WithStack(err) + co.GlobalViewCounter, e = co.NewGlobalViewCounter(acc) + if e != nil { + return ws(e) } - co.AgentViewCounter, err = co.NewDefaultAgentViewCounter(acc) - if err != nil { - return errors.WithStack(err) + co.AgentViewCounter, e = co.NewDefaultAgentViewCounter(acc) + if e != nil { + return ws(e) } - co.OSViewCounter, err = co.NewDefaultOSViewCounter(acc) - if err != nil { - return errors.WithStack(err) + co.OSViewCounter, e = co.NewDefaultOSViewCounter(acc) + if e != nil { + return ws(e) } - co.LangViewCounter, err = co.NewDefaultLangViewCounter(acc) - if err != nil { - return errors.WithStack(err) + co.LangViewCounter, e = co.NewDefaultLangViewCounter(acc) + if e != nil { + return ws(e) } if !c.Config.RefNoTrack { - co.ReferrerTracker, err = co.NewDefaultReferrerTracker() - if err != nil { - return errors.WithStack(err) + co.ReferrerTracker, e = co.NewDefaultReferrerTracker() + if e != nil { + return ws(e) } } - co.MemoryCounter, err = co.NewMemoryCounter(acc) - if err != nil { - return errors.WithStack(err) + co.MemoryCounter, e = co.NewMemoryCounter(acc) + if e != nil { + return ws(e) } - co.PerfCounter, err = co.NewDefaultPerfCounter(acc) - if err != nil { - return errors.WithStack(err) + co.PerfCounter, e = co.NewDefaultPerfCounter(acc) + if e != nil { + return ws(e) } } - co.RouteViewCounter, err = co.NewDefaultRouteViewCounter(acc) - if err != nil { - return errors.WithStack(err) + co.RouteViewCounter, e = co.NewDefaultRouteViewCounter(acc) + if e != nil { + return ws(e) } - co.PostCounter, err = co.NewPostCounter() - if err != nil { - return errors.WithStack(err) + co.PostCounter, e = co.NewPostCounter() + if e != nil { + return ws(e) } - co.TopicCounter, err = co.NewTopicCounter() - if err != nil { - return errors.WithStack(err) + co.TopicCounter, e = co.NewTopicCounter() + if e != nil { + return ws(e) } - co.TopicViewCounter, err = co.NewDefaultTopicViewCounter() - if err != nil { - return errors.WithStack(err) + co.TopicViewCounter, e = co.NewDefaultTopicViewCounter() + if e != nil { + return ws(e) } - co.ForumViewCounter, err = co.NewDefaultForumViewCounter() - if err != nil { - return errors.WithStack(err) + co.ForumViewCounter, e = co.NewDefaultForumViewCounter() + if e != nil { + return ws(e) } return nil @@ -361,8 +366,11 @@ func main() { if err != nil { log.Fatal(err) } - c.LogWriter = io.MultiWriter(os.Stderr, f) + //c.LogWriter = io.MultiWriter(os.Stderr, f) + c.LogWriter = io.MultiWriter(os.Stdout, f) + c.ErrLogWriter = io.MultiWriter(os.Stderr, f) log.SetOutput(c.LogWriter) + c.ErrLogger = log.New(c.ErrLogWriter, "", log.LstdFlags) log.Print("Running Gosora v" + c.SoftwareVersion.String()) fmt.Println("") @@ -396,6 +404,14 @@ func main() { if err != nil { log.Fatal(err) } + if c.Config.DisableStdout { + c.LogWriter = f + log.SetOutput(c.LogWriter) + } + if c.Config.DisableStderr { + c.ErrLogWriter = f + c.ErrLogger = log.New(c.ErrLogWriter, "", log.LstdFlags) + } err = c.InitTemplates() if err != nil {