logger.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package logger
  2. import (
  3. "go.uber.org/zap"
  4. "go.uber.org/zap/zapcore"
  5. "gopkg.in/natefinch/lumberjack.v2"
  6. "os"
  7. "sync"
  8. )
  9. // Logger 封装后的日志器
  10. type Logger struct {
  11. *zap.SugaredLogger
  12. opts *Options
  13. zap *zap.Logger
  14. once sync.Once
  15. }
  16. var (
  17. globalLogger *Logger
  18. globalMutex sync.Mutex
  19. )
  20. // NewLogger 创建新的日志器
  21. func NewLogger(opts *Options) *Logger {
  22. if opts == nil {
  23. opts = DefaultOptions()
  24. }
  25. // 创建 encoder 配置
  26. encoderConfig := zapcore.EncoderConfig{
  27. TimeKey: "time",
  28. LevelKey: "level",
  29. NameKey: "logger",
  30. CallerKey: "caller",
  31. MessageKey: "msg",
  32. StacktraceKey: "stacktrace",
  33. LineEnding: zapcore.DefaultLineEnding,
  34. EncodeLevel: zapcore.CapitalLevelEncoder,
  35. EncodeTime: zapcore.ISO8601TimeEncoder,
  36. EncodeDuration: zapcore.SecondsDurationEncoder,
  37. EncodeCaller: zapcore.ShortCallerEncoder,
  38. }
  39. // 设置 encoder
  40. var encoder zapcore.Encoder
  41. if opts.Format == "json" {
  42. encoder = zapcore.NewJSONEncoder(encoderConfig)
  43. } else {
  44. encoder = zapcore.NewConsoleEncoder(encoderConfig)
  45. }
  46. // 设置日志级别
  47. level := parseLogLevel(opts.Level)
  48. // 创建 core
  49. core := zapcore.NewCore(
  50. encoder,
  51. getWriteSyncer(opts),
  52. level,
  53. )
  54. // 创建 zap logger
  55. zapLogger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
  56. if opts.Caller {
  57. zapLogger = zapLogger.WithOptions(zap.AddCaller())
  58. }
  59. logger := &Logger{
  60. SugaredLogger: zapLogger.Sugar(),
  61. zap: zapLogger,
  62. opts: opts,
  63. }
  64. return logger
  65. }
  66. // parseLogLevel 解析日志级别
  67. func parseLogLevel(level LogLevel) zapcore.Level {
  68. switch level {
  69. case DebugLevel:
  70. return zapcore.DebugLevel
  71. case InfoLevel:
  72. return zapcore.InfoLevel
  73. case WarnLevel:
  74. return zapcore.WarnLevel
  75. case ErrorLevel:
  76. return zapcore.ErrorLevel
  77. default:
  78. return zapcore.InfoLevel
  79. }
  80. }
  81. // getWriteSyncer 获取日志输出
  82. func getWriteSyncer(opts *Options) zapcore.WriteSyncer {
  83. if opts.OutputPath == "" {
  84. return zapcore.AddSync(os.Stdout)
  85. }
  86. // 使用 lumberjack 实现日志轮转
  87. lumberJackLogger := &lumberjack.Logger{
  88. Filename: opts.OutputPath,
  89. MaxSize: opts.MaxSize,
  90. MaxBackups: opts.MaxBackups,
  91. MaxAge: opts.MaxAge,
  92. Compress: opts.Compress,
  93. LocalTime: true,
  94. }
  95. return zapcore.AddSync(lumberJackLogger)
  96. }
  97. // InitGlobalLogger 初始化全局日志器
  98. func InitGlobalLogger(opts *Options) {
  99. globalMutex.Lock()
  100. defer globalMutex.Unlock()
  101. globalLogger = NewLogger(opts)
  102. }
  103. // GetGlobalLogger 获取全局日志器
  104. func GetGlobalLogger() *Logger {
  105. if globalLogger == nil {
  106. globalMutex.Lock()
  107. defer globalMutex.Unlock()
  108. if globalLogger == nil {
  109. globalLogger = NewLogger(DefaultOptions())
  110. }
  111. }
  112. return globalLogger
  113. }
  114. // Sync 刷新日志缓冲区
  115. func (l *Logger) Sync() error {
  116. return l.zap.Sync()
  117. }
  118. // WithFields 添加结构化字段
  119. func (l *Logger) WithFields(fields map[string]interface{}) *Logger {
  120. zapFields := make([]zap.Field, 0, len(fields))
  121. for k, v := range fields {
  122. zapFields = append(zapFields, zap.Any(k, v))
  123. }
  124. newZapLogger := l.zap.With(zapFields...)
  125. return &Logger{
  126. SugaredLogger: newZapLogger.Sugar(),
  127. zap: newZapLogger,
  128. opts: l.opts,
  129. }
  130. }
  131. // WithField 添加单个字段
  132. func (l *Logger) WithField(key string, value interface{}) *Logger {
  133. return l.WithFields(map[string]interface{}{key: value})
  134. }
  135. // 快捷方法 - 使用全局日志器
  136. func Debug(args ...interface{}) {
  137. GetGlobalLogger().Debug(args...)
  138. }
  139. func Debugf(template string, args ...interface{}) {
  140. GetGlobalLogger().Debugf(template, args...)
  141. }
  142. func Info(args ...interface{}) {
  143. GetGlobalLogger().Info(args...)
  144. }
  145. func Infof(template string, args ...interface{}) {
  146. GetGlobalLogger().Infof(template, args...)
  147. }
  148. func Warn(args ...interface{}) {
  149. GetGlobalLogger().Warn(args...)
  150. }
  151. func Warnf(template string, args ...interface{}) {
  152. GetGlobalLogger().Warnf(template, args...)
  153. }
  154. func Error(args ...interface{}) {
  155. GetGlobalLogger().Error(args...)
  156. }
  157. func Errorf(template string, args ...interface{}) {
  158. GetGlobalLogger().Errorf(template, args...)
  159. }
  160. func Fatal(args ...interface{}) {
  161. GetGlobalLogger().Fatal(args...)
  162. }
  163. func Fatalf(template string, args ...interface{}) {
  164. GetGlobalLogger().Fatalf(template, args...)
  165. }
  166. func Panic(args ...interface{}) {
  167. GetGlobalLogger().Panic(args...)
  168. }
  169. func Panicf(template string, args ...interface{}) {
  170. GetGlobalLogger().Panicf(template, args...)
  171. }
  172. // SyncGlobal 刷新全局日志器缓冲区
  173. func SyncGlobal() error {
  174. if globalLogger != nil {
  175. return globalLogger.Sync()
  176. }
  177. return nil
  178. }