From f286a5abb42f94d7c597f41b25990f2ccee0bb77 Mon Sep 17 00:00:00 2001 From: zeripath Date: Wed, 6 Feb 2019 03:06:41 +0000 Subject: [PATCH] Allow Macaron to be set to log through to gitea.log (#5667) * Allow Macaron to be set to log through gitea.log Fix #4291 --- custom/conf/app.ini.sample | 1 + .../doc/advanced/config-cheat-sheet.en-us.md | 1 + modules/log/log.go | 42 +++++++++++++++++++ modules/setting/setting.go | 10 +++-- routers/routes/routes.go | 29 +++++++++++-- 5 files changed, 76 insertions(+), 7 deletions(-) diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index aebcfafa9..31fed0c02 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -497,6 +497,7 @@ MODE = console BUFFER_LEN = 10000 ; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" LEVEL = Trace +REDIRECT_MACARON_LOG = false ; For "console" mode only [log.console] diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 825431671..89eb9af78 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -279,6 +279,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`. - `ROOT_PATH`: **\**: Root path for log files. - `MODE`: **console**: Logging mode. For multiple modes, use a comma to separate values. - `LEVEL`: **Trace**: General log level. \[Trace, Debug, Info, Warn, Error, Critical\] +- `REDIRECT_MACARON_LOG`: **false**: Redirects the Macaron log to the Gitea logger. ## Cron (`cron`) diff --git a/modules/log/log.go b/modules/log/log.go index 36038d3d0..98a8014b5 100644 --- a/modules/log/log.go +++ b/modules/log/log.go @@ -154,6 +154,48 @@ type LoggerInterface interface { type loggerType func() LoggerInterface +// LoggerAsWriter is a io.Writer shim around the gitea log +type LoggerAsWriter struct { + level int +} + +// NewLoggerAsWriter creates a Writer representation of the logger with setable log level +func NewLoggerAsWriter(level string) *LoggerAsWriter { + l := &LoggerAsWriter{} + switch strings.ToUpper(level) { + case "TRACE": + l.level = TRACE + case "DEBUG": + l.level = DEBUG + case "INFO": + l.level = INFO + case "WARN": + l.level = WARN + case "ERROR": + l.level = ERROR + case "CRITICAL": + l.level = CRITICAL + case "FATAL": + l.level = FATAL + default: + l.level = INFO + } + return l +} + +// Write implements the io.Writer interface to allow spoofing of macaron +func (l *LoggerAsWriter) Write(p []byte) (int, error) { + l.Log(string(p)) + return len(p), nil +} + +// Log takes a given string and logs it at the set log-level +func (l *LoggerAsWriter) Log(msg string) { + for _, logger := range loggers { + logger.writerMsg(0, l.level, msg) + } +} + var adapters = make(map[string]loggerType) // Register registers given logger provider to adapters. diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 77f0725d0..0859b81c4 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -393,10 +393,11 @@ var ( LibravatarService *libravatar.Libravatar // Log settings - LogLevel string - LogRootPath string - LogModes []string - LogConfigs []string + LogLevel string + LogRootPath string + LogModes []string + LogConfigs []string + RedirectMacaronLog bool // Attachment settings AttachmentPath string @@ -767,6 +768,7 @@ func NewContext() { LogLevel = getLogLevel("log", "LEVEL", "Info") LogRootPath = Cfg.Section("log").Key("ROOT_PATH").MustString(path.Join(AppWorkPath, "log")) forcePathSeparator(LogRootPath) + RedirectMacaronLog = Cfg.Section("log").Key("REDIRECT_MACARON_LOG").MustBool(false) sec := Cfg.Section("server") AppName = Cfg.Section("").Key("APP_NAME").MustString("Gitea: Git with a cup of tea") diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 48d1dc6a7..58274626c 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -6,6 +6,7 @@ package routes import ( "encoding/gob" + "fmt" "net/http" "os" "path" @@ -45,12 +46,34 @@ import ( macaron "gopkg.in/macaron.v1" ) +func giteaLogger(l *log.LoggerAsWriter) macaron.Handler { + return func(ctx *macaron.Context) { + start := time.Now() + + l.Log(fmt.Sprintf("[Macaron] Started %s %s for %s", ctx.Req.Method, ctx.Req.RequestURI, ctx.RemoteAddr())) + + ctx.Next() + + rw := ctx.Resp.(macaron.ResponseWriter) + l.Log(fmt.Sprintf("[Macaron] Completed %s %s %v %s in %v", ctx.Req.Method, ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))) + } +} + // NewMacaron initializes Macaron instance. func NewMacaron() *macaron.Macaron { gob.Register(&u2f.Challenge{}) - m := macaron.New() - if !setting.DisableRouterLog { - m.Use(macaron.Logger()) + var m *macaron.Macaron + if setting.RedirectMacaronLog { + loggerAsWriter := log.NewLoggerAsWriter("INFO") + m = macaron.NewWithLogger(loggerAsWriter) + if !setting.DisableRouterLog { + m.Use(giteaLogger(loggerAsWriter)) + } + } else { + m = macaron.New() + if !setting.DisableRouterLog { + m.Use(macaron.Logger()) + } } m.Use(macaron.Recovery()) if setting.EnableGzip {