log.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2020 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package conf
  5. import (
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "github.com/pkg/errors"
  10. "gopkg.in/ini.v1"
  11. log "unknwon.dev/clog/v2"
  12. )
  13. type loggerConf struct {
  14. Buffer int64
  15. Config interface{}
  16. }
  17. type logConf struct {
  18. RootPath string
  19. Modes []string
  20. Configs []*loggerConf
  21. }
  22. // Log settings
  23. var Log *logConf
  24. // initLogConf returns parsed logging configuration from given INI file.
  25. // NOTE: Because we always create a console logger as the primary logger at init time,
  26. // we need to remove it in case the user doesn't configure to use it after the logging
  27. // service is initalized.
  28. func initLogConf(cfg *ini.File) (_ *logConf, hasConsole bool, _ error) {
  29. rootPath := cfg.Section("log").Key("ROOT_PATH").MustString(filepath.Join(WorkDir(), "log"))
  30. modes := strings.Split(cfg.Section("log").Key("MODE").MustString("console"), ",")
  31. lc := &logConf{
  32. RootPath: ensureAbs(rootPath),
  33. Modes: make([]string, 0, len(modes)),
  34. Configs: make([]*loggerConf, 0, len(modes)),
  35. }
  36. // Iterate over [log.*] sections to initialize individual logger.
  37. levelMappings := map[string]log.Level{
  38. "trace": log.LevelTrace,
  39. "info": log.LevelInfo,
  40. "warn": log.LevelWarn,
  41. "error": log.LevelError,
  42. "fatal": log.LevelFatal,
  43. }
  44. for i := range modes {
  45. modes[i] = strings.ToLower(strings.TrimSpace(modes[i]))
  46. secName := "log." + modes[i]
  47. sec, err := cfg.GetSection(secName)
  48. if err != nil {
  49. return nil, hasConsole, errors.Errorf("missing configuration section [%s] for %q logger", secName, modes[i])
  50. }
  51. level := levelMappings[strings.ToLower(sec.Key("LEVEL").MustString("trace"))]
  52. buffer := sec.Key("BUFFER_LEN").MustInt64(100)
  53. var c *loggerConf
  54. switch modes[i] {
  55. case log.DefaultConsoleName:
  56. hasConsole = true
  57. c = &loggerConf{
  58. Buffer: buffer,
  59. Config: log.ConsoleConfig{
  60. Level: level,
  61. },
  62. }
  63. case log.DefaultFileName:
  64. logPath := filepath.Join(lc.RootPath, "gogs.log")
  65. c = &loggerConf{
  66. Buffer: buffer,
  67. Config: log.FileConfig{
  68. Level: level,
  69. Filename: logPath,
  70. FileRotationConfig: log.FileRotationConfig{
  71. Rotate: sec.Key("LOG_ROTATE").MustBool(true),
  72. Daily: sec.Key("DAILY_ROTATE").MustBool(true),
  73. MaxSize: 1 << uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
  74. MaxLines: sec.Key("MAX_LINES").MustInt64(1000000),
  75. MaxDays: sec.Key("MAX_DAYS").MustInt64(7),
  76. },
  77. },
  78. }
  79. case log.DefaultSlackName:
  80. c = &loggerConf{
  81. Buffer: buffer,
  82. Config: log.SlackConfig{
  83. Level: level,
  84. URL: sec.Key("URL").String(),
  85. },
  86. }
  87. case log.DefaultDiscordName:
  88. c = &loggerConf{
  89. Buffer: buffer,
  90. Config: log.DiscordConfig{
  91. Level: level,
  92. URL: sec.Key("URL").String(),
  93. Username: sec.Key("USERNAME").String(),
  94. },
  95. }
  96. default:
  97. continue
  98. }
  99. lc.Modes = append(lc.Modes, modes[i])
  100. lc.Configs = append(lc.Configs, c)
  101. }
  102. return lc, hasConsole, nil
  103. }
  104. // InitLogging initializes the logging service of the application.
  105. func InitLogging() {
  106. logConf, hasConsole, err := initLogConf(File)
  107. if err != nil {
  108. log.Fatal("Failed to init logging configuration: %v", err)
  109. }
  110. err = os.MkdirAll(logConf.RootPath, os.ModePerm)
  111. if err != nil {
  112. log.Fatal("Failed to create log directory: %v", err)
  113. }
  114. for i, mode := range logConf.Modes {
  115. c := logConf.Configs[i]
  116. var err error
  117. var level log.Level
  118. switch mode {
  119. case log.DefaultConsoleName:
  120. level = c.Config.(log.ConsoleConfig).Level
  121. err = log.NewConsole(c.Buffer, c.Config)
  122. case log.DefaultFileName:
  123. level = c.Config.(log.FileConfig).Level
  124. err = log.NewFile(c.Buffer, c.Config)
  125. case log.DefaultSlackName:
  126. level = c.Config.(log.SlackConfig).Level
  127. err = log.NewSlack(c.Buffer, c.Config)
  128. case log.DefaultDiscordName:
  129. level = c.Config.(log.DiscordConfig).Level
  130. err = log.NewDiscord(c.Buffer, c.Config)
  131. default:
  132. panic("unreachable")
  133. }
  134. if err != nil {
  135. log.Fatal("Failed to init %s logger: %v", mode, err)
  136. return
  137. }
  138. log.Trace("Log mode: %s (%s)", strings.Title(mode), strings.Title(strings.ToLower(level.String())))
  139. }
  140. if !hasConsole {
  141. log.Remove(log.DefaultConsoleName)
  142. }
  143. Log = logConf
  144. }