logger.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. package mhayaLogger
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "sync"
  7. "time"
  8. cfacade "github.com/mhaya/facade"
  9. "github.com/mhaya/logger/rotatelogs"
  10. cprofile "github.com/mhaya/profile"
  11. "go.uber.org/zap"
  12. "go.uber.org/zap/zapcore"
  13. )
  14. var (
  15. rw sync.RWMutex // mutex
  16. DefaultLogger *MhayaLogger // 默认日志对象(控制台输出)
  17. loggers map[string]*MhayaLogger // 日志实例存储map(key:日志名称,value:日志实例)
  18. nodeId string // current node id
  19. printLevel zapcore.Level // mhaya log print level
  20. fileNameVarMap = map[string]string{} // 日志输出文件名自定义变量
  21. )
  22. func init() {
  23. DefaultLogger = NewConfigLogger(defaultConsoleConfig(), zap.AddCallerSkip(1))
  24. loggers = make(map[string]*MhayaLogger)
  25. }
  26. type MhayaLogger struct {
  27. *zap.SugaredLogger
  28. *Config
  29. }
  30. func (c *MhayaLogger) Print(v ...interface{}) {
  31. c.Warn(v)
  32. }
  33. func SetNodeLogger(node cfacade.INode) {
  34. nodeId = node.NodeId()
  35. refLoggerName := node.Settings().Get("ref_logger").ToString()
  36. if refLoggerName == "" {
  37. DefaultLogger.Infof("RefLoggerName not found, used default console logger.")
  38. return
  39. }
  40. SetFileNameVar("nodeId", node.NodeId()) // %nodeId
  41. SetFileNameVar("nodeType", node.NodeType()) // %nodeTyp
  42. DefaultLogger = NewLogger(refLoggerName, zap.AddCallerSkip(1))
  43. printLevel = GetLevel(cprofile.PrintLevel())
  44. }
  45. func SetFileNameVar(key, value string) {
  46. fileNameVarMap[key] = value
  47. }
  48. func Flush() {
  49. _ = DefaultLogger.Sync()
  50. for _, logger := range loggers {
  51. _ = logger.Sync()
  52. }
  53. }
  54. func NewLogger(refLoggerName string, opts ...zap.Option) *MhayaLogger {
  55. if refLoggerName == "" {
  56. return nil
  57. }
  58. defer rw.Unlock()
  59. rw.Lock()
  60. if logger, found := loggers[refLoggerName]; found {
  61. return logger
  62. }
  63. config, err := NewConfigWithName(refLoggerName)
  64. if err != nil {
  65. Panicf("New Config fail. err = %v", err)
  66. }
  67. logger := NewConfigLogger(config, opts...)
  68. loggers[refLoggerName] = logger
  69. return logger
  70. }
  71. func NewConfigLogger(config *Config, opts ...zap.Option) *MhayaLogger {
  72. if config.EnableWriteFile {
  73. for key, value := range fileNameVarMap {
  74. config.FileLinkPath = strings.ReplaceAll(config.FileLinkPath, "%"+key, value)
  75. config.FilePathFormat = strings.ReplaceAll(config.FilePathFormat, "%"+key, value)
  76. }
  77. }
  78. encoderConfig := zapcore.EncoderConfig{
  79. TimeKey: "ts",
  80. LevelKey: "level",
  81. CallerKey: "caller",
  82. MessageKey: "msg",
  83. NameKey: "name",
  84. StacktraceKey: "stack",
  85. LineEnding: zapcore.DefaultLineEnding,
  86. EncodeDuration: zapcore.StringDurationEncoder,
  87. EncodeCaller: zapcore.ShortCallerEncoder,
  88. }
  89. encoderConfig.EncodeLevel = func(level zapcore.Level, encoder zapcore.PrimitiveArrayEncoder) {
  90. if nodeId != "" {
  91. encoder.AppendString(fmt.Sprintf("%s %-5s", nodeId, level.CapitalString()))
  92. } else {
  93. encoder.AppendString(level.CapitalString())
  94. }
  95. }
  96. if config.PrintCaller {
  97. encoderConfig.EncodeTime = config.TimeEncoder()
  98. encoderConfig.EncodeName = zapcore.FullNameEncoder
  99. encoderConfig.FunctionKey = zapcore.OmitKey
  100. opts = append(opts, zap.AddCaller())
  101. }
  102. opts = append(opts, zap.AddStacktrace(GetLevel(config.StackLevel)))
  103. var writers []zapcore.WriteSyncer
  104. if config.EnableWriteFile {
  105. hook, err := rotatelogs.New(
  106. config.FilePathFormat, //filename+"_%Y%m%d%H%M.log",
  107. rotatelogs.WithLinkName(config.FileLinkPath),
  108. rotatelogs.WithMaxAge(time.Hour*24*time.Duration(config.MaxAge)),
  109. rotatelogs.WithRotationTime(time.Second*time.Duration(config.RotationTime)),
  110. )
  111. if err != nil {
  112. panic(err)
  113. }
  114. writers = append(writers, zapcore.AddSync(hook))
  115. }
  116. if config.EnableConsole {
  117. writers = append(writers, zapcore.AddSync(os.Stderr))
  118. }
  119. if config.IncludeStdout {
  120. writers = append(writers, zapcore.Lock(os.Stdout))
  121. }
  122. if config.IncludeStderr {
  123. writers = append(writers, zapcore.Lock(os.Stderr))
  124. }
  125. core := zapcore.NewCore(
  126. zapcore.NewConsoleEncoder(encoderConfig),
  127. zapcore.AddSync(zapcore.NewMultiWriteSyncer(writers...)),
  128. zap.NewAtomicLevelAt(GetLevel(config.LogLevel)),
  129. )
  130. mhayaLogger := &MhayaLogger{
  131. SugaredLogger: NewSugaredLogger(core, opts...),
  132. Config: config,
  133. }
  134. return mhayaLogger
  135. }
  136. func NewSugaredLogger(core zapcore.Core, opts ...zap.Option) *zap.SugaredLogger {
  137. zapLogger := zap.New(core, opts...)
  138. return zapLogger.Sugar()
  139. }
  140. func Enable(level zapcore.Level) bool {
  141. return DefaultLogger.Desugar().Core().Enabled(level)
  142. }
  143. func Debug(args ...interface{}) {
  144. DefaultLogger.Debug(args...)
  145. }
  146. func Info(args ...interface{}) {
  147. DefaultLogger.Info(args...)
  148. }
  149. // Warn uses fmt.Sprint to construct and log a message.
  150. func Warn(args ...interface{}) {
  151. DefaultLogger.Warn(args...)
  152. }
  153. // Error uses fmt.Sprint to construct and log a message.
  154. func Error(args ...interface{}) {
  155. DefaultLogger.Error(args...)
  156. }
  157. // DPanic uses fmt.Sprint to construct and log a message. In development, the
  158. // logger then panics. (See DPanicLevel for details.)
  159. func DPanic(args ...interface{}) {
  160. DefaultLogger.DPanic(args...)
  161. }
  162. // Panic uses fmt.Sprint to construct and log a message, then panics.
  163. func Panic(args ...interface{}) {
  164. DefaultLogger.Panic(args...)
  165. }
  166. // Fatal uses fmt.Sprint to construct and log a message, then calls os.Exit.
  167. func Fatal(args ...interface{}) {
  168. DefaultLogger.Fatal(args...)
  169. }
  170. // Debugf uses fmt.Sprintf to log a templated message.
  171. func Debugf(template string, args ...interface{}) {
  172. DefaultLogger.Debugf(template, args...)
  173. }
  174. // Infof uses fmt.Sprintf to log a templated message.
  175. func Infof(template string, args ...interface{}) {
  176. DefaultLogger.Infof(template, args...)
  177. }
  178. // Warnf uses fmt.Sprintf to log a templated message.
  179. func Warnf(template string, args ...interface{}) {
  180. DefaultLogger.Warnf(template, args...)
  181. }
  182. // Errorf uses fmt.Sprintf to log a templated message.
  183. func Errorf(template string, args ...interface{}) {
  184. DefaultLogger.Errorf(template, args...)
  185. }
  186. // DPanicf uses fmt.Sprintf to log a templated message. In development, the
  187. // logger then panics. (See DPanicLevel for details.)
  188. func DPanicf(template string, args ...interface{}) {
  189. DefaultLogger.DPanicf(template, args...)
  190. }
  191. // Panicf uses fmt.Sprintf to log a templated message, then panics.
  192. func Panicf(template string, args ...interface{}) {
  193. DefaultLogger.Panicf(template, args...)
  194. }
  195. // Fatalf uses fmt.Sprintf to log a templated message, then calls os.Exit.
  196. func Fatalf(template string, args ...interface{}) {
  197. DefaultLogger.Fatalf(template, args...)
  198. }
  199. // Debugw logs a message with some additional context. The variadic key-value
  200. // pairs are treated as they are in With.
  201. //
  202. // When debug-level logging is disabled, this is much faster than
  203. //
  204. // s.With(keysAndValues).Debug(msg)
  205. func Debugw(msg string, keysAndValues ...interface{}) {
  206. DefaultLogger.Debugw(msg, keysAndValues...)
  207. }
  208. // Infow logs a message with some additional context. The variadic key-value
  209. // pairs are treated as they are in With.
  210. func Infow(msg string, keysAndValues ...interface{}) {
  211. DefaultLogger.Infow(msg, keysAndValues...)
  212. }
  213. // Warnw logs a message with some additional context. The variadic key-value
  214. // pairs are treated as they are in With.
  215. func Warnw(msg string, keysAndValues ...interface{}) {
  216. DefaultLogger.Warnw(msg, keysAndValues...)
  217. }
  218. // Errorw logs a message with some additional context. The variadic key-value
  219. // pairs are treated as they are in With.
  220. func Errorw(msg string, keysAndValues ...interface{}) {
  221. DefaultLogger.Errorw(msg, keysAndValues...)
  222. }
  223. // DPanicw logs a message with some additional context. In development, the
  224. // logger then panics. (See DPanicLevel for details.) The variadic key-value
  225. // pairs are treated as they are in With.
  226. func DPanicw(msg string, keysAndValues ...interface{}) {
  227. DefaultLogger.DPanicw(msg, keysAndValues...)
  228. }
  229. // Panicw logs a message with some additional context, then panics. The
  230. // variadic key-value pairs are treated as they are in With.
  231. func Panicw(msg string, keysAndValues ...interface{}) {
  232. DefaultLogger.Panicw(msg, keysAndValues...)
  233. }
  234. // Fatalw logs a message with some additional context, then calls os.Exit. The
  235. // variadic key-value pairs are treated as they are in With.
  236. func Fatalw(msg string, keysAndValues ...interface{}) {
  237. DefaultLogger.Fatalw(msg, keysAndValues...)
  238. }
  239. func PrintLevel(level zapcore.Level) bool {
  240. return level >= printLevel
  241. }
  242. func GetLevel(level string) zapcore.Level {
  243. switch strings.ToLower(level) {
  244. case "debug":
  245. return zapcore.DebugLevel
  246. case "info":
  247. return zapcore.InfoLevel
  248. case "warn":
  249. return zapcore.WarnLevel
  250. case "error":
  251. return zapcore.ErrorLevel
  252. case "panic":
  253. return zapcore.PanicLevel
  254. case "fatal":
  255. return zapcore.FatalLevel
  256. default:
  257. return zapcore.DebugLevel
  258. }
  259. }