| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 | 
							- // Copyright 2020 The Gogs 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 conf
 
- import (
 
- 	"os"
 
- 	"path/filepath"
 
- 	"strings"
 
- 	"github.com/pkg/errors"
 
- 	"gopkg.in/ini.v1"
 
- 	log "unknwon.dev/clog/v2"
 
- )
 
- type loggerConf struct {
 
- 	Buffer int64
 
- 	Config any
 
- }
 
- type logConf struct {
 
- 	RootPath string
 
- 	Modes    []string
 
- 	Configs  []*loggerConf
 
- }
 
- // Log settings
 
- var Log *logConf
 
- // initLogConf returns parsed logging configuration from given INI file. When the
 
- // argument "hookMode" is true, it only initializes the root path for log files.
 
- // NOTE: Because we always create a console logger as the primary logger at init time,
 
- // we need to remove it in case the user doesn't configure to use it after the logging
 
- // service is initialized.
 
- func initLogConf(cfg *ini.File, hookMode bool) (_ *logConf, hasConsole bool, _ error) {
 
- 	rootPath := cfg.Section("log").Key("ROOT_PATH").MustString(filepath.Join(WorkDir(), "log"))
 
- 	if hookMode {
 
- 		return &logConf{
 
- 			RootPath: ensureAbs(rootPath),
 
- 		}, false, nil
 
- 	}
 
- 	modes := strings.Split(cfg.Section("log").Key("MODE").MustString("console"), ",")
 
- 	lc := &logConf{
 
- 		RootPath: ensureAbs(rootPath),
 
- 		Modes:    make([]string, 0, len(modes)),
 
- 		Configs:  make([]*loggerConf, 0, len(modes)),
 
- 	}
 
- 	// Iterate over [log.*] sections to initialize individual logger.
 
- 	levelMappings := map[string]log.Level{
 
- 		"trace": log.LevelTrace,
 
- 		"info":  log.LevelInfo,
 
- 		"warn":  log.LevelWarn,
 
- 		"error": log.LevelError,
 
- 		"fatal": log.LevelFatal,
 
- 	}
 
- 	for i := range modes {
 
- 		modes[i] = strings.ToLower(strings.TrimSpace(modes[i]))
 
- 		secName := "log." + modes[i]
 
- 		sec, err := cfg.GetSection(secName)
 
- 		if err != nil {
 
- 			return nil, hasConsole, errors.Errorf("missing configuration section [%s] for %q logger", secName, modes[i])
 
- 		}
 
- 		level := levelMappings[strings.ToLower(sec.Key("LEVEL").MustString("trace"))]
 
- 		buffer := sec.Key("BUFFER_LEN").MustInt64(100)
 
- 		var c *loggerConf
 
- 		switch modes[i] {
 
- 		case log.DefaultConsoleName:
 
- 			hasConsole = true
 
- 			c = &loggerConf{
 
- 				Buffer: buffer,
 
- 				Config: log.ConsoleConfig{
 
- 					Level: level,
 
- 				},
 
- 			}
 
- 		case log.DefaultFileName:
 
- 			logPath := filepath.Join(lc.RootPath, "gogs.log")
 
- 			c = &loggerConf{
 
- 				Buffer: buffer,
 
- 				Config: log.FileConfig{
 
- 					Level:    level,
 
- 					Filename: logPath,
 
- 					FileRotationConfig: log.FileRotationConfig{
 
- 						Rotate:   sec.Key("LOG_ROTATE").MustBool(true),
 
- 						Daily:    sec.Key("DAILY_ROTATE").MustBool(true),
 
- 						MaxSize:  1 << uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
 
- 						MaxLines: sec.Key("MAX_LINES").MustInt64(1000000),
 
- 						MaxDays:  sec.Key("MAX_DAYS").MustInt64(7),
 
- 					},
 
- 				},
 
- 			}
 
- 		case log.DefaultSlackName:
 
- 			c = &loggerConf{
 
- 				Buffer: buffer,
 
- 				Config: log.SlackConfig{
 
- 					Level: level,
 
- 					URL:   sec.Key("URL").String(),
 
- 				},
 
- 			}
 
- 		case log.DefaultDiscordName:
 
- 			c = &loggerConf{
 
- 				Buffer: buffer,
 
- 				Config: log.DiscordConfig{
 
- 					Level:    level,
 
- 					URL:      sec.Key("URL").String(),
 
- 					Username: sec.Key("USERNAME").String(),
 
- 				},
 
- 			}
 
- 		default:
 
- 			continue
 
- 		}
 
- 		lc.Modes = append(lc.Modes, modes[i])
 
- 		lc.Configs = append(lc.Configs, c)
 
- 	}
 
- 	return lc, hasConsole, nil
 
- }
 
- // InitLogging initializes the logging service of the application. When the
 
- // "hookMode" is true, it only initializes the root path for log files without
 
- // creating any logger. It will also not remove the primary logger in "hookMode"
 
- // and is up to the caller to decide when to remove it.
 
- func InitLogging(hookMode bool) {
 
- 	logConf, hasConsole, err := initLogConf(File, hookMode)
 
- 	if err != nil {
 
- 		log.Fatal("Failed to init logging configuration: %v", err)
 
- 	}
 
- 	defer func() {
 
- 		Log = logConf
 
- 	}()
 
- 	if hookMode {
 
- 		return
 
- 	}
 
- 	err = os.MkdirAll(logConf.RootPath, os.ModePerm)
 
- 	if err != nil {
 
- 		log.Fatal("Failed to create log directory: %v", err)
 
- 	}
 
- 	for i, mode := range logConf.Modes {
 
- 		c := logConf.Configs[i]
 
- 		var err error
 
- 		var level log.Level
 
- 		switch mode {
 
- 		case log.DefaultConsoleName:
 
- 			level = c.Config.(log.ConsoleConfig).Level
 
- 			err = log.NewConsole(c.Buffer, c.Config)
 
- 		case log.DefaultFileName:
 
- 			level = c.Config.(log.FileConfig).Level
 
- 			err = log.NewFile(c.Buffer, c.Config)
 
- 		case log.DefaultSlackName:
 
- 			level = c.Config.(log.SlackConfig).Level
 
- 			err = log.NewSlack(c.Buffer, c.Config)
 
- 		case log.DefaultDiscordName:
 
- 			level = c.Config.(log.DiscordConfig).Level
 
- 			err = log.NewDiscord(c.Buffer, c.Config)
 
- 		default:
 
- 			panic("unreachable")
 
- 		}
 
- 		if err != nil {
 
- 			log.Fatal("Failed to init %s logger: %v", mode, err)
 
- 			return
 
- 		}
 
- 		log.Trace("Log mode: %s (%s)", strings.Title(mode), strings.Title(strings.ToLower(level.String())))
 
- 	}
 
- 	// ⚠️ WARNING: It is only safe to remove the primary logger until
 
- 	// there are other loggers that are initialized. Otherwise, the
 
- 	// application will print errors to nowhere.
 
- 	if !hasConsole {
 
- 		log.Remove(log.DefaultConsoleName)
 
- 	}
 
- }
 
 
  |