diff --git a/cmd/admin.go b/cmd/admin.go index f4782195e..698504424 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -74,6 +74,8 @@ func runCreateUser(c *cli.Context) error { setting.NewContext() models.LoadConfigs() + + setting.NewXORMLogService(false) if err := models.SetEngine(); err != nil { return fmt.Errorf("models.SetEngine: %v", err) } diff --git a/cmd/serve.go b/cmd/serve.go index c69254e3f..7141d85c9 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -50,7 +50,6 @@ var CmdServ = cli.Command{ func setup(logPath string) error { setting.NewContext() log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath)) - models.LoadConfigs() if setting.UseSQLite3 || setting.UseTiDB { @@ -60,6 +59,7 @@ func setup(logPath string) error { } } + setting.NewXORMLogService(true) return models.SetEngine() } diff --git a/models/models.go b/models/models.go index 27b49755a..33268fabb 100644 --- a/models/models.go +++ b/models/models.go @@ -25,6 +25,7 @@ import ( _ "github.com/denisenkom/go-mssqldb" "code.gitea.io/gitea/models/migrations" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) @@ -226,6 +227,7 @@ func getEngine() (*xorm.Engine, error) { default: return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type) } + return xorm.NewEngine(DbCfg.Type, connStr) } @@ -236,6 +238,8 @@ func NewTestEngine(x *xorm.Engine) (err error) { return fmt.Errorf("Connect to database: %v", err) } + setting.NewXORMLogService(false) + x.SetMapper(core.GonicMapper{}) return x.StoreEngine("InnoDB").Sync2(tables...) } @@ -248,20 +252,9 @@ func SetEngine() (err error) { } x.SetMapper(core.GonicMapper{}) - // WARNING: for serv command, MUST remove the output to os.stdout, // so use log file to instead print to stdout. - logPath := path.Join(setting.LogRootPath, "xorm.log") - - if err := os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil { - return fmt.Errorf("Failed to create dir %s: %v", logPath, err) - } - - f, err := os.Create(logPath) - if err != nil { - return fmt.Errorf("Failed to create xorm.log: %v", err) - } - x.SetLogger(xorm.NewSimpleLogger(f)) + x.SetLogger(log.XORMLogger) x.ShowSQL(true) return nil } diff --git a/modules/log/xorm.go b/modules/log/xorm.go new file mode 100644 index 000000000..9b23d9f37 --- /dev/null +++ b/modules/log/xorm.go @@ -0,0 +1,136 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package log + +import ( + "fmt" + + "github.com/go-xorm/core" +) + +// XORMLogBridge a logger bridge from Logger to xorm +type XORMLogBridge struct { + loggers []*Logger + showSQL bool + level core.LogLevel +} + +var ( + // XORMLogger the logger for xorm + XORMLogger *XORMLogBridge +) + +// NewXORMLogger generate logger for xorm FIXME: configable +func NewXORMLogger(bufferlen int64, mode, config string) { + logger := newLogger(bufferlen) + logger.SetLogger(mode, config) + if XORMLogger == nil { + XORMLogger = &XORMLogBridge{ + showSQL: true, + } + } + XORMLogger.loggers = append(XORMLogger.loggers, logger) +} + +func (l *XORMLogBridge) writerMsg(skip, level int, msg string) error { + for _, logger := range l.loggers { + if err := logger.writerMsg(skip, level, msg); err != nil { + return err + } + } + return nil +} + +// Debug show debug log +func (l *XORMLogBridge) Debug(v ...interface{}) { + if l.level <= core.LOG_DEBUG { + msg := fmt.Sprint(v...) + l.writerMsg(0, DEBUG, "[D]"+msg) + } +} + +// Debugf show debug log +func (l *XORMLogBridge) Debugf(format string, v ...interface{}) { + if l.level <= core.LOG_DEBUG { + for _, logger := range l.loggers { + logger.Debug(format, v...) + } + } +} + +// Error show error log +func (l *XORMLogBridge) Error(v ...interface{}) { + if l.level <= core.LOG_ERR { + msg := fmt.Sprint(v...) + l.writerMsg(0, ERROR, "[E]"+msg) + } +} + +// Errorf show error log +func (l *XORMLogBridge) Errorf(format string, v ...interface{}) { + if l.level <= core.LOG_ERR { + for _, logger := range l.loggers { + logger.Error(0, format, v...) + } + } +} + +// Info show information level log +func (l *XORMLogBridge) Info(v ...interface{}) { + if l.level <= core.LOG_INFO { + msg := fmt.Sprint(v...) + l.writerMsg(0, INFO, "[I]"+msg) + } +} + +// Infof show information level log +func (l *XORMLogBridge) Infof(format string, v ...interface{}) { + if l.level <= core.LOG_INFO { + for _, logger := range l.loggers { + logger.Info(format, v...) + } + } +} + +// Warn show warnning log +func (l *XORMLogBridge) Warn(v ...interface{}) { + if l.level <= core.LOG_WARNING { + msg := fmt.Sprint(v...) + l.writerMsg(0, WARN, "[W] "+msg) + } +} + +// Warnf show warnning log +func (l *XORMLogBridge) Warnf(format string, v ...interface{}) { + if l.level <= core.LOG_WARNING { + for _, logger := range l.loggers { + logger.Warn(format, v...) + } + } +} + +// Level get logger level +func (l *XORMLogBridge) Level() core.LogLevel { + return l.level +} + +// SetLevel set logger level +func (l *XORMLogBridge) SetLevel(level core.LogLevel) { + l.level = level +} + +// ShowSQL set if record SQL +func (l *XORMLogBridge) ShowSQL(show ...bool) { + if len(show) > 0 { + l.showSQL = show[0] + } else { + l.showSQL = true + } +} + +// IsShowSQL if record SQL +func (l *XORMLogBridge) IsShowSQL() bool { + return l.showSQL +} diff --git a/modules/setting/setting.go b/modules/setting/setting.go index bbccb44ea..e69cfaa32 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -30,6 +30,7 @@ import ( _ "github.com/go-macaron/cache/redis" "github.com/go-macaron/session" _ "github.com/go-macaron/session/redis" // redis plugin for store session + "github.com/go-xorm/core" ini "gopkg.in/ini.v1" "strk.kbt.io/projects/go/libravatar" ) @@ -944,18 +945,18 @@ func newLogService() { LogConfigs = make([]string, len(LogModes)) useConsole := false - for _, mode := range LogModes { - if mode == "console" { + for i := 0; i < len(LogModes); i++ { + LogModes[i] = strings.TrimSpace(LogModes[i]) + if LogModes[i] == "console" { useConsole = true } } + if !useConsole { log.DelLogger("console") } for i, mode := range LogModes { - mode = strings.TrimSpace(mode) - sec, err := Cfg.GetSection("log." + mode) if err != nil { @@ -1014,6 +1015,87 @@ func newLogService() { } } +// NewXORMLogService initializes xorm logger service +func NewXORMLogService(disableConsole bool) { + logModes := strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",") + var logConfigs string + for _, mode := range logModes { + mode = strings.TrimSpace(mode) + + if disableConsole && mode == "console" { + continue + } + sec, err := Cfg.GetSection("log." + mode) + if err != nil { + log.Fatal(4, "Unknown log mode: %s", mode) + } + + validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"} + // Log level. + levelName := Cfg.Section("log."+mode).Key("LEVEL").In( + Cfg.Section("log").Key("LEVEL").In("Trace", validLevels), + validLevels) + level, ok := logLevels[levelName] + if !ok { + log.Fatal(4, "Unknown log level: %s", levelName) + } + + // Generate log configuration. + switch mode { + case "console": + logConfigs = fmt.Sprintf(`{"level":%s}`, level) + case "file": + logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "xorm.log")) + if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil { + panic(err.Error()) + } + logPath = filepath.Join(filepath.Dir(logPath), "xorm.log") + + logConfigs = fmt.Sprintf( + `{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level, + logPath, + sec.Key("LOG_ROTATE").MustBool(true), + sec.Key("MAX_LINES").MustInt(1000000), + 1<