You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

246 lines
7.2 KiB

  1. package logx
  2. import (
  3. "os"
  4. "strings"
  5. "time"
  6. "go.uber.org/zap"
  7. "go.uber.org/zap/zapcore"
  8. )
  9. type LogConfig struct {
  10. AppName string `yaml:"app_name" json:"app_name" toml:"app_name"`
  11. Level string `yaml:"level" json:"level" toml:"level"`
  12. StacktraceLevel string `yaml:"stacktrace_level" json:"stacktrace_level" toml:"stacktrace_level"`
  13. IsStdOut bool `yaml:"is_stdout" json:"is_stdout" toml:"is_stdout"`
  14. TimeFormat string `yaml:"time_format" json:"time_format" toml:"time_format"` // second, milli, nano, standard, iso,
  15. Encoding string `yaml:"encoding" json:"encoding" toml:"encoding"` // console, json
  16. Skip int `yaml:"skip" json:"skip" toml:"skip"`
  17. IsFileOut bool `yaml:"is_file_out" json:"is_file_out" toml:"is_file_out"`
  18. FileDir string `yaml:"file_dir" json:"file_dir" toml:"file_dir"`
  19. FileName string `yaml:"file_name" json:"file_name" toml:"file_name"`
  20. FileMaxSize int `yaml:"file_max_size" json:"file_max_size" toml:"file_max_size"`
  21. FileMaxAge int `yaml:"file_max_age" json:"file_max_age" toml:"file_max_age"`
  22. }
  23. var (
  24. l *LogX = defaultLogger()
  25. conf *LogConfig
  26. )
  27. // default logger setting
  28. func defaultLogger() *LogX {
  29. conf = &LogConfig{
  30. Level: "debug",
  31. StacktraceLevel: "error",
  32. IsStdOut: true,
  33. TimeFormat: "standard",
  34. Encoding: "console",
  35. Skip: 2,
  36. }
  37. writers := []zapcore.WriteSyncer{os.Stdout}
  38. lg, lv := newZapLogger(setLogLevel(conf.Level), setLogLevel(conf.StacktraceLevel), conf.Encoding, conf.TimeFormat, conf.Skip, zapcore.NewMultiWriteSyncer(writers...))
  39. zap.RedirectStdLog(lg)
  40. return &LogX{logger: lg, atomLevel: lv}
  41. }
  42. // initial standard log, if you don't init, it will use default logger setting
  43. func InitDefaultLogger(cfg *LogConfig) {
  44. var writers []zapcore.WriteSyncer
  45. if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) {
  46. writers = append(writers, os.Stdout)
  47. }
  48. if cfg.IsFileOut {
  49. writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge))
  50. }
  51. lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...))
  52. zap.RedirectStdLog(lg)
  53. if cfg.AppName != "" {
  54. lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称
  55. }
  56. l = &LogX{logger: lg, atomLevel: lv}
  57. }
  58. // create a new logger
  59. func NewLogger(cfg *LogConfig) *LogX {
  60. var writers []zapcore.WriteSyncer
  61. if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) {
  62. writers = append(writers, os.Stdout)
  63. }
  64. if cfg.IsFileOut {
  65. writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge))
  66. }
  67. lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...))
  68. zap.RedirectStdLog(lg)
  69. if cfg.AppName != "" {
  70. lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称
  71. }
  72. return &LogX{logger: lg, atomLevel: lv}
  73. }
  74. // create a new zaplog logger
  75. func newZapLogger(level, stacktrace zapcore.Level, encoding, timeType string, skip int, output zapcore.WriteSyncer) (*zap.Logger, *zap.AtomicLevel) {
  76. encCfg := zapcore.EncoderConfig{
  77. TimeKey: "T",
  78. LevelKey: "L",
  79. NameKey: "N",
  80. CallerKey: "C",
  81. MessageKey: "M",
  82. StacktraceKey: "S",
  83. LineEnding: zapcore.DefaultLineEnding,
  84. EncodeCaller: zapcore.ShortCallerEncoder,
  85. EncodeDuration: zapcore.NanosDurationEncoder,
  86. EncodeLevel: zapcore.LowercaseLevelEncoder,
  87. }
  88. setTimeFormat(timeType, &encCfg) // set time type
  89. atmLvl := zap.NewAtomicLevel() // set level
  90. atmLvl.SetLevel(level)
  91. encoder := zapcore.NewJSONEncoder(encCfg) // 确定encoder格式
  92. if encoding == "console" {
  93. encoder = zapcore.NewConsoleEncoder(encCfg)
  94. }
  95. return zap.New(zapcore.NewCore(encoder, output, atmLvl), zap.AddCaller(), zap.AddStacktrace(stacktrace), zap.AddCallerSkip(skip)), &atmLvl
  96. }
  97. // set log level
  98. func setLogLevel(lvl string) zapcore.Level {
  99. switch strings.ToLower(lvl) {
  100. case "panic":
  101. return zapcore.PanicLevel
  102. case "fatal":
  103. return zapcore.FatalLevel
  104. case "error":
  105. return zapcore.ErrorLevel
  106. case "warn", "warning":
  107. return zapcore.WarnLevel
  108. case "info":
  109. return zapcore.InfoLevel
  110. default:
  111. return zapcore.DebugLevel
  112. }
  113. }
  114. // set time format
  115. func setTimeFormat(timeType string, z *zapcore.EncoderConfig) {
  116. switch strings.ToLower(timeType) {
  117. case "iso": // iso8601 standard
  118. z.EncodeTime = zapcore.ISO8601TimeEncoder
  119. case "sec": // only for unix second, without millisecond
  120. z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  121. enc.AppendInt64(t.Unix())
  122. }
  123. case "second": // unix second, with millisecond
  124. z.EncodeTime = zapcore.EpochTimeEncoder
  125. case "milli", "millisecond": // millisecond
  126. z.EncodeTime = zapcore.EpochMillisTimeEncoder
  127. case "nano", "nanosecond": // nanosecond
  128. z.EncodeTime = zapcore.EpochNanosTimeEncoder
  129. default: // standard format
  130. z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  131. enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
  132. }
  133. }
  134. }
  135. func GetLevel() string {
  136. switch l.atomLevel.Level() {
  137. case zapcore.PanicLevel:
  138. return "panic"
  139. case zapcore.FatalLevel:
  140. return "fatal"
  141. case zapcore.ErrorLevel:
  142. return "error"
  143. case zapcore.WarnLevel:
  144. return "warn"
  145. case zapcore.InfoLevel:
  146. return "info"
  147. default:
  148. return "debug"
  149. }
  150. }
  151. func SetLevel(lvl string) {
  152. l.atomLevel.SetLevel(setLogLevel(lvl))
  153. }
  154. // temporary add call skip
  155. func AddCallerSkip(skip int) *LogX {
  156. l.logger.WithOptions(zap.AddCallerSkip(skip))
  157. return l
  158. }
  159. // permanent add call skip
  160. func AddDepth(skip int) *LogX {
  161. l.logger = l.logger.WithOptions(zap.AddCallerSkip(skip))
  162. return l
  163. }
  164. // permanent add options
  165. func AddOptions(opts ...zap.Option) *LogX {
  166. l.logger = l.logger.WithOptions(opts...)
  167. return l
  168. }
  169. func AddField(k string, v interface{}) {
  170. l.logger.With(zap.Any(k, v))
  171. }
  172. func AddFields(fields map[string]interface{}) *LogX {
  173. for k, v := range fields {
  174. l.logger.With(zap.Any(k, v))
  175. }
  176. return l
  177. }
  178. // Normal log
  179. func Debug(e interface{}, args ...interface{}) error {
  180. return l.Debug(e, args...)
  181. }
  182. func Info(e interface{}, args ...interface{}) error {
  183. return l.Info(e, args...)
  184. }
  185. func Warn(e interface{}, args ...interface{}) error {
  186. return l.Warn(e, args...)
  187. }
  188. func Error(e interface{}, args ...interface{}) error {
  189. return l.Error(e, args...)
  190. }
  191. func Panic(e interface{}, args ...interface{}) error {
  192. return l.Panic(e, args...)
  193. }
  194. func Fatal(e interface{}, args ...interface{}) error {
  195. return l.Fatal(e, args...)
  196. }
  197. // Format logs
  198. func Debugf(format string, args ...interface{}) error {
  199. return l.Debugf(format, args...)
  200. }
  201. func Infof(format string, args ...interface{}) error {
  202. return l.Infof(format, args...)
  203. }
  204. func Warnf(format string, args ...interface{}) error {
  205. return l.Warnf(format, args...)
  206. }
  207. func Errorf(format string, args ...interface{}) error {
  208. return l.Errorf(format, args...)
  209. }
  210. func Panicf(format string, args ...interface{}) error {
  211. return l.Panicf(format, args...)
  212. }
  213. func Fatalf(format string, args ...interface{}) error {
  214. return l.Fatalf(format, args...)
  215. }
  216. func formatFieldMap(m FieldMap) []Field {
  217. var res []Field
  218. for k, v := range m {
  219. res = append(res, zap.Any(k, v))
  220. }
  221. return res
  222. }