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.
This commit is contained in:
Azareal 2021-04-07 12:10:05 +10:00
parent b5e8cbf87c
commit 14b098bac2
5 changed files with 174 additions and 142 deletions

View File

@ -167,7 +167,9 @@ func StoppedServer(msg ...interface{}) {
var StopServerChan = make(chan []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{}) { func DebugDetail(args ...interface{}) {
if Dev.SuperDebug { if Dev.SuperDebug {
@ -196,6 +198,9 @@ func DebugLogf(str string, args ...interface{}) {
func Log(args ...interface{}) { func Log(args ...interface{}) {
log.Print(args...) log.Print(args...)
} }
func Err(args ...interface{}) {
ErrLogger.Print(args...)
}
func Logf(str string, args ...interface{}) { func Logf(str string, args ...interface{}) {
log.Printf(str, args...) log.Printf(str, args...)
@ -223,10 +228,10 @@ func eachall(stmt *sql.Stmt, f func(r *sql.Rows) error) error {
return rows.Err() 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) { func inqbuild(ids []int) ([]interface{}, string) {
if len(ids) < 7 { if len(ids) < 8 {
idList := make([]interface{}, len(ids)) idList := make([]interface{}, len(ids))
for i, id := range ids { for i, id := range ids {
idList[i] = strconv.Itoa(id) idList[i] = strconv.Itoa(id)
@ -249,7 +254,7 @@ func inqbuild(ids []int) ([]interface{}, string) {
} }
func inqbuild2(count int) string { func inqbuild2(count int) string {
if count <= 7 { if count <= 8 {
return qcache[count-1] return qcache[count-1]
} }
var sb strings.Builder var sb strings.Builder
@ -265,7 +270,7 @@ func inqbuild2(count int) string {
} }
func inqbuildstr(strs []string) ([]interface{}, string) { func inqbuildstr(strs []string) ([]interface{}, string) {
if len(strs) < 7 { if len(strs) < 8 {
idList := make([]interface{}, len(strs)) idList := make([]interface{}, len(strs))
for i, id := range strs { for i, id := range strs {
idList[i] = id idList[i] = id

View File

@ -1,6 +1,7 @@
package common package common
import ( import (
"fmt"
"log" "log"
"net/http" "net/http"
"runtime/debug" "runtime/debug"
@ -105,7 +106,7 @@ func SysError(errmsg string) RouteError {
// TODO: Clean-up extra as a way of passing additional context // TODO: Clean-up extra as a way of passing additional context
func LogError(err error, extra ...string) { func LogError(err error, extra ...string) {
LogWarning(err, extra...) LogWarning(err, extra...)
log.Fatal("") ErrLogger.Fatal("")
} }
func LogWarning(err error, extra ...string) { func LogWarning(err error, extra ...string) {
@ -121,7 +122,7 @@ func LogWarning(err error, extra ...string) {
errorBufferMutex.Lock() errorBufferMutex.Lock()
defer errorBufferMutex.Unlock() defer errorBufferMutex.Unlock()
stack := debug.Stack() // debug.Stack() can't be executed concurrently, so we'll guard this with a mutex too 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}) 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, "")) 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 { func SimpleError(errmsg string, w http.ResponseWriter, r *http.Request, h *Header) RouteError {
if h == nil { if h == nil {
h = errorHeader(w, &GuestUser, phrases.GetErrorPhrase("local_error_title")) h = errorHeader(w, &GuestUser, phrases.GetErrorPhrase("local_error_title"))

View File

@ -138,6 +138,8 @@ type config struct {
LogDir string LogDir string
DisableSuspLog bool DisableSuspLog bool
DisableBadRouteLog bool DisableBadRouteLog bool
DisableStdout bool
DisableStderr bool
} }
type devConfig struct { type devConfig struct {

View File

@ -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 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 Related: https://support.cloudflare.com/hc/en-us/articles/212794707-General-Best-Practices-for-Load-Balancing-at-your-origin-with-Cloudflare

286
main.go
View File

@ -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 // 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? // TODO: Dynamically register these items to avoid maintaining as much code here?
func storeInit() (err error) { func storeInit() (e error) {
acc := qgen.NewAcc() acc := qgen.NewAcc()
ws := errors.WithStack
var rcache c.ReplyCache var rcache c.ReplyCache
if c.Config.ReplyCache == "static" { if c.Config.ReplyCache == "static" {
rcache = c.NewMemoryReplyCache(c.Config.ReplyCacheCapacity) rcache = c.NewMemoryReplyCache(c.Config.ReplyCacheCapacity)
} }
c.Rstore, err = c.NewSQLReplyStore(acc, rcache) c.Rstore, e = c.NewSQLReplyStore(acc, rcache)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Prstore, err = c.NewSQLProfileReplyStore(acc) c.Prstore, e = c.NewSQLProfileReplyStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Likes, err = c.NewDefaultLikeStore(acc) c.Likes, e = c.NewDefaultLikeStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Convos, err = c.NewDefaultConversationStore(acc) c.ForumActionStore, e = c.NewDefaultForumActionStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.UserBlocks, err = c.NewDefaultBlockStore(acc) c.Convos, e = c.NewDefaultConversationStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.GroupPromotions, err = c.NewDefaultGroupPromotionStore(acc) c.UserBlocks, e = c.NewDefaultBlockStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
}
c.GroupPromotions, e = c.NewDefaultGroupPromotionStore(acc)
if e != nil {
return ws(e)
} }
if err = p.InitPhrases(c.Site.Language); err != nil { if e = p.InitPhrases(c.Site.Language); e != nil {
return errors.WithStack(err) return ws(e)
} }
if err = c.InitEmoji(); err != nil { if e = c.InitEmoji(); e != nil {
return errors.WithStack(err) return ws(e)
} }
if err = c.InitWeakPasswords(); err != nil { if e = c.InitWeakPasswords(); e != nil {
return errors.WithStack(err) return ws(e)
} }
log.Print("Loading the static files.") log.Print("Loading the static files.")
if err = c.Themes.LoadStaticFiles(); err != nil { if e = c.Themes.LoadStaticFiles(); e != nil {
return errors.WithStack(err) return ws(e)
} }
if err = c.StaticFiles.Init(); err != nil { if e = c.StaticFiles.Init(); e != nil {
return errors.WithStack(err) return ws(e)
} }
if err = c.StaticFiles.JSTmplInit(); err != nil { if e = c.StaticFiles.JSTmplInit(); e != nil {
return errors.WithStack(err) return ws(e)
} }
log.Print("Initialising the widgets") log.Print("Initialising the widgets")
c.Widgets = c.NewDefaultWidgetStore() c.Widgets = c.NewDefaultWidgetStore()
if err = c.InitWidgets(); err != nil { if e = c.InitWidgets(); e != nil {
return errors.WithStack(err) return ws(e)
} }
log.Print("Initialising the menu item list") log.Print("Initialising the menu item list")
c.Menus = c.NewDefaultMenuStore() c.Menus = c.NewDefaultMenuStore()
if err = c.Menus.Load(1); err != nil { // 1 = the default menu if e = c.Menus.Load(1); e != nil { // 1 = the default menu
return errors.WithStack(err) return ws(e)
} }
menuHold, err := c.Menus.Get(1) menuHold, e := c.Menus.Get(1)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
fmt.Printf("menuHold: %+v\n", menuHold) fmt.Printf("menuHold: %+v\n", menuHold)
var b bytes.Buffer var b bytes.Buffer
@ -197,147 +202,147 @@ func storeInit() (err error) {
fmt.Println("menuHold output: ", string(b.Bytes())) fmt.Println("menuHold output: ", string(b.Bytes()))
log.Print("Initialising the authentication system") log.Print("Initialising the authentication system")
c.Auth, err = c.NewDefaultAuth() c.Auth, e = c.NewDefaultAuth()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
log.Print("Initialising the stores") log.Print("Initialising the stores")
c.WordFilters, err = c.NewDefaultWordFilterStore(acc) c.WordFilters, e = c.NewDefaultWordFilterStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.MFAstore, err = c.NewSQLMFAStore(acc) c.MFAstore, e = c.NewSQLMFAStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Pages, err = c.NewDefaultPageStore(acc) c.Pages, e = c.NewDefaultPageStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Reports, err = c.NewDefaultReportStore(acc) c.Reports, e = c.NewDefaultReportStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Emails, err = c.NewDefaultEmailStore(acc) c.Emails, e = c.NewDefaultEmailStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.LoginLogs, err = c.NewLoginLogStore(acc) c.LoginLogs, e = c.NewLoginLogStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.RegLogs, err = c.NewRegLogStore(acc) c.RegLogs, e = c.NewRegLogStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.ModLogs, err = c.NewModLogStore(acc) c.ModLogs, e = c.NewModLogStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.AdminLogs, err = c.NewAdminLogStore(acc) c.AdminLogs, e = c.NewAdminLogStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.IPSearch, err = c.NewDefaultIPSearcher() c.IPSearch, e = c.NewDefaultIPSearcher()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
if c.Config.Search == "" || c.Config.Search == "sql" { if c.Config.Search == "" || c.Config.Search == "sql" {
c.RepliesSearch, err = c.NewSQLSearcher(acc) c.RepliesSearch, e = c.NewSQLSearcher(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
} }
c.Subscriptions, err = c.NewDefaultSubscriptionStore() c.Subscriptions, e = c.NewDefaultSubscriptionStore()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Attachments, err = c.NewDefaultAttachmentStore(acc) c.Attachments, e = c.NewDefaultAttachmentStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Polls, err = c.NewDefaultPollStore(c.NewMemoryPollCache(100)) // TODO: Max number of polls held in cache, make this a config item c.Polls, e = c.NewDefaultPollStore(c.NewMemoryPollCache(100)) // TODO: Max number of polls held in cache, make this a config item
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.TopicList, err = c.NewDefaultTopicList(acc) c.TopicList, e = c.NewDefaultTopicList(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.PasswordResetter, err = c.NewDefaultPasswordResetter(acc) c.PasswordResetter, e = c.NewDefaultPasswordResetter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
c.Activity, err = c.NewDefaultActivityStream(acc) c.Activity, e = c.NewDefaultActivityStream(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
// TODO: Let the admin choose other thumbnailers, maybe ones defined in plugins // TODO: Let the admin choose other thumbnailers, maybe ones defined in plugins
c.Thumbnailer = c.NewCaireThumbnailer() c.Thumbnailer = c.NewCaireThumbnailer()
c.Recalc, err = c.NewDefaultRecalc(acc) c.Recalc, e = c.NewDefaultRecalc(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
log.Print("Initialising the meta store") log.Print("Initialising the meta store")
c.Meta, err = meta.NewDefaultMetaStore(acc) c.Meta, e = meta.NewDefaultMetaStore(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
log.Print("Initialising the view counters") log.Print("Initialising the view counters")
if !c.Config.DisableAnalytics { if !c.Config.DisableAnalytics {
co.GlobalViewCounter, err = co.NewGlobalViewCounter(acc) co.GlobalViewCounter, e = co.NewGlobalViewCounter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.AgentViewCounter, err = co.NewDefaultAgentViewCounter(acc) co.AgentViewCounter, e = co.NewDefaultAgentViewCounter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.OSViewCounter, err = co.NewDefaultOSViewCounter(acc) co.OSViewCounter, e = co.NewDefaultOSViewCounter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.LangViewCounter, err = co.NewDefaultLangViewCounter(acc) co.LangViewCounter, e = co.NewDefaultLangViewCounter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
if !c.Config.RefNoTrack { if !c.Config.RefNoTrack {
co.ReferrerTracker, err = co.NewDefaultReferrerTracker() co.ReferrerTracker, e = co.NewDefaultReferrerTracker()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
} }
co.MemoryCounter, err = co.NewMemoryCounter(acc) co.MemoryCounter, e = co.NewMemoryCounter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.PerfCounter, err = co.NewDefaultPerfCounter(acc) co.PerfCounter, e = co.NewDefaultPerfCounter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
} }
co.RouteViewCounter, err = co.NewDefaultRouteViewCounter(acc) co.RouteViewCounter, e = co.NewDefaultRouteViewCounter(acc)
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.PostCounter, err = co.NewPostCounter() co.PostCounter, e = co.NewPostCounter()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.TopicCounter, err = co.NewTopicCounter() co.TopicCounter, e = co.NewTopicCounter()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.TopicViewCounter, err = co.NewDefaultTopicViewCounter() co.TopicViewCounter, e = co.NewDefaultTopicViewCounter()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
co.ForumViewCounter, err = co.NewDefaultForumViewCounter() co.ForumViewCounter, e = co.NewDefaultForumViewCounter()
if err != nil { if e != nil {
return errors.WithStack(err) return ws(e)
} }
return nil return nil
@ -361,8 +366,11 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) 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) log.SetOutput(c.LogWriter)
c.ErrLogger = log.New(c.ErrLogWriter, "", log.LstdFlags)
log.Print("Running Gosora v" + c.SoftwareVersion.String()) log.Print("Running Gosora v" + c.SoftwareVersion.String())
fmt.Println("") fmt.Println("")
@ -396,6 +404,14 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) 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() err = c.InitTemplates()
if err != nil { if err != nil {