基于 `zap` 包封装。除了实现 `Go` 日志包的基本功能外,还实现了很多高级功能 本包基于`github.com/tkestack/tke/pkg/util/log`裁剪
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.

553 lines
16 KiB

2 years ago
  1. package log
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "sync"
  7. "cynking.com/pkg/log/klog"
  8. "go.uber.org/zap"
  9. "go.uber.org/zap/zapcore"
  10. )
  11. // InfoLogger represents the ability to log non-error messages, at a particular verbosity.
  12. type InfoLogger interface {
  13. // Info logs a non-error message with the given key/value pairs as context.
  14. //
  15. // The msg argument should be used to add some constant description to
  16. // the log line. The key/value pairs can then be used to add additional
  17. // variable information. The key/value pairs should alternate string
  18. // keys and arbitrary values.
  19. Info(msg string, fields ...Field)
  20. Infof(format string, v ...interface{})
  21. Infow(msg string, keysAndValues ...interface{})
  22. // Enabled tests whether this InfoLogger is enabled. For example,
  23. // commandline flags might be used to set the logging verbosity and disable
  24. // some info logs.
  25. Enabled() bool
  26. }
  27. // Logger represents the ability to log messages, both errors and not.
  28. type Logger interface {
  29. // All Loggers implement InfoLogger. Calling InfoLogger methods directly on
  30. // a Logger value is equivalent to calling them on a V(0) InfoLogger. For
  31. // example, logger.Info() produces the same result as logger.V(0).Info.
  32. InfoLogger
  33. Debug(msg string, fields ...Field)
  34. Debugf(format string, v ...interface{})
  35. Debugw(msg string, keysAndValues ...interface{})
  36. Warn(msg string, fields ...Field)
  37. Warnf(format string, v ...interface{})
  38. Warnw(msg string, keysAndValues ...interface{})
  39. Error(msg string, fields ...Field)
  40. Errorf(format string, v ...interface{})
  41. Errorw(msg string, keysAndValues ...interface{})
  42. Panic(msg string, fields ...Field)
  43. Panicf(format string, v ...interface{})
  44. Panicw(msg string, keysAndValues ...interface{})
  45. Fatal(msg string, fields ...Field)
  46. Fatalf(format string, v ...interface{})
  47. Fatalw(msg string, keysAndValues ...interface{})
  48. // V returns an InfoLogger value for a specific verbosity level. A higher
  49. // verbosity level means a log message is less important. It's illegal to
  50. // pass a log level less than zero.
  51. V(level Level) InfoLogger
  52. Write(p []byte) (n int, err error)
  53. // WithValues adds some key-value pairs of context to a logger.
  54. // See Info for documentation on how key/value pairs work.
  55. WithValues(keysAndValues ...interface{}) Logger
  56. // WithName adds a new element to the logger's name.
  57. // Successive calls with WithName continue to append
  58. // suffixes to the logger's name. It's strongly recommended
  59. // that name segments contain only letters, digits, and hyphens
  60. // (see the package documentation for more information).
  61. WithName(name string) Logger
  62. // WithContext returns a copy of context in which the log value is set.
  63. WithContext(ctx context.Context) context.Context
  64. // Flush calls the underlying Core's Sync method, flushing any buffered
  65. // log entries. Applications should take care to call Sync before exiting.
  66. Flush()
  67. }
  68. var _ Logger = &zapLogger{}
  69. // noopInfoLogger is a logr.InfoLogger that's always disabled, and does nothing.
  70. type noopInfoLogger struct{}
  71. func (l *noopInfoLogger) Enabled() bool { return false }
  72. func (l *noopInfoLogger) Info(_ string, _ ...Field) {}
  73. func (l *noopInfoLogger) Infof(_ string, _ ...interface{}) {}
  74. func (l *noopInfoLogger) Infow(_ string, _ ...interface{}) {}
  75. var disabledInfoLogger = &noopInfoLogger{}
  76. // NB: right now, we always use the equivalent of sugared logging.
  77. // This is necessary, since logr doesn't define non-suggared types,
  78. // and using zap-specific non-suggared types would make uses tied
  79. // directly to Zap.
  80. // infoLogger is a logr.InfoLogger that uses Zap to log at a particular
  81. // level. The level has already been converted to a Zap level, which
  82. // is to say that `logrLevel = -1*zapLevel`.
  83. type infoLogger struct {
  84. level zapcore.Level
  85. log *zap.Logger
  86. }
  87. func (l *infoLogger) Enabled() bool { return true }
  88. func (l *infoLogger) Info(msg string, fields ...Field) {
  89. if checkedEntry := l.log.Check(l.level, msg); checkedEntry != nil {
  90. checkedEntry.Write(fields...)
  91. }
  92. }
  93. func (l *infoLogger) Infof(format string, args ...interface{}) {
  94. if checkedEntry := l.log.Check(l.level, fmt.Sprintf(format, args...)); checkedEntry != nil {
  95. checkedEntry.Write()
  96. }
  97. }
  98. func (l *infoLogger) Infow(msg string, keysAndValues ...interface{}) {
  99. if checkedEntry := l.log.Check(l.level, msg); checkedEntry != nil {
  100. checkedEntry.Write(handleFields(l.log, keysAndValues)...)
  101. }
  102. }
  103. // zapLogger is a logr.Logger that uses Zap to log.
  104. type zapLogger struct {
  105. // NB: this looks very similar to zap.SugaredLogger, but
  106. // deals with our desire to have multiple verbosity levels.
  107. zapLogger *zap.Logger
  108. infoLogger
  109. }
  110. // handleFields converts a bunch of arbitrary key-value pairs into Zap fields. It takes
  111. // additional pre-converted Zap fields, for use with automatically attached fields, like
  112. // `error`.
  113. func handleFields(l *zap.Logger, args []interface{}, additional ...zap.Field) []zap.Field {
  114. // a slightly modified version of zap.SugaredLogger.sweetenFields
  115. if len(args) == 0 {
  116. // fast-return if we have no suggared fields.
  117. return additional
  118. }
  119. // unlike Zap, we can be pretty sure users aren't passing structured
  120. // fields (since logr has no concept of that), so guess that we need a
  121. // little less space.
  122. fields := make([]zap.Field, 0, len(args)/2+len(additional))
  123. for i := 0; i < len(args); {
  124. // check just in case for strongly-typed Zap fields, which is illegal (since
  125. // it breaks implementation agnosticism), so we can give a better error message.
  126. if _, ok := args[i].(zap.Field); ok {
  127. l.DPanic("strongly-typed Zap Field passed to logr", zap.Any("zap field", args[i]))
  128. break
  129. }
  130. // make sure this isn't a mismatched key
  131. if i == len(args)-1 {
  132. l.DPanic("odd number of arguments passed as key-value pairs for logging", zap.Any("ignored key", args[i]))
  133. break
  134. }
  135. // process a key-value pair,
  136. // ensuring that the key is a string
  137. key, val := args[i], args[i+1]
  138. keyStr, isString := key.(string)
  139. if !isString {
  140. // if the key isn't a string, DPanic and stop logging
  141. l.DPanic(
  142. "non-string key argument passed to logging, ignoring all later arguments",
  143. zap.Any("invalid key", key),
  144. )
  145. break
  146. }
  147. fields = append(fields, zap.Any(keyStr, val))
  148. i += 2
  149. }
  150. return append(fields, additional...)
  151. }
  152. var (
  153. std = New(NewOptions())
  154. mu sync.Mutex
  155. )
  156. // Init initializes logger with specified options.
  157. func Init(opts *Options) {
  158. mu.Lock()
  159. defer mu.Unlock()
  160. std = New(opts)
  161. }
  162. // New create logger by opts which can custmoized by command arguments.
  163. func New(opts *Options) *zapLogger {
  164. if opts == nil {
  165. opts = NewOptions()
  166. }
  167. var zapLevel zapcore.Level
  168. if err := zapLevel.UnmarshalText([]byte(opts.Level)); err != nil {
  169. zapLevel = zapcore.InfoLevel
  170. }
  171. encodeLevel := zapcore.CapitalLevelEncoder
  172. // when output to local path, with color is forbidden
  173. if opts.Format == ConsoleFormat && opts.EnableColor {
  174. encodeLevel = zapcore.CapitalColorLevelEncoder
  175. }
  176. encoderConfig := zapcore.EncoderConfig{
  177. MessageKey: "message",
  178. LevelKey: "level",
  179. TimeKey: "timestamp",
  180. NameKey: "logger",
  181. CallerKey: "caller",
  182. StacktraceKey: "stacktrace",
  183. LineEnding: zapcore.DefaultLineEnding,
  184. EncodeLevel: encodeLevel,
  185. EncodeTime: timeEncoder,
  186. EncodeDuration: autoDurationEncoder,
  187. EncodeCaller: zapcore.ShortCallerEncoder,
  188. }
  189. loggerConfig := &zap.Config{
  190. Level: zap.NewAtomicLevelAt(zapLevel),
  191. Development: opts.Development,
  192. DisableCaller: opts.DisableCaller,
  193. DisableStacktrace: opts.DisableStacktrace,
  194. Sampling: &zap.SamplingConfig{
  195. Initial: 100,
  196. Thereafter: 100,
  197. },
  198. Encoding: opts.Format,
  199. EncoderConfig: encoderConfig,
  200. OutputPaths: opts.OutputPaths,
  201. ErrorOutputPaths: opts.ErrorOutputPaths,
  202. }
  203. var err error
  204. l, err := loggerConfig.Build(zap.AddStacktrace(zapcore.PanicLevel), zap.AddCallerSkip(1))
  205. if err != nil {
  206. panic(err)
  207. }
  208. logger := &zapLogger{
  209. zapLogger: l.Named(opts.Name),
  210. infoLogger: infoLogger{
  211. log: l,
  212. level: zap.InfoLevel,
  213. },
  214. }
  215. klog.InitLogger(l)
  216. zap.RedirectStdLog(l)
  217. return logger
  218. }
  219. // SugaredLogger returns global sugared logger.
  220. func SugaredLogger() *zap.SugaredLogger {
  221. return std.zapLogger.Sugar()
  222. }
  223. // StdErrLogger returns logger of standard library which writes to supplied zap
  224. // logger at error level.
  225. func StdErrLogger() *log.Logger {
  226. if std == nil {
  227. return nil
  228. }
  229. if l, err := zap.NewStdLogAt(std.zapLogger, zapcore.ErrorLevel); err == nil {
  230. return l
  231. }
  232. return nil
  233. }
  234. // StdInfoLogger returns logger of standard library which writes to supplied zap
  235. // logger at info level.
  236. func StdInfoLogger() *log.Logger {
  237. if std == nil {
  238. return nil
  239. }
  240. if l, err := zap.NewStdLogAt(std.zapLogger, zapcore.InfoLevel); err == nil {
  241. return l
  242. }
  243. return nil
  244. }
  245. // V return a leveled InfoLogger.
  246. func V(level Level) InfoLogger { return std.V(level) }
  247. func (l *zapLogger) V(level Level) InfoLogger {
  248. if l.zapLogger.Core().Enabled(level) {
  249. return &infoLogger{
  250. level: level,
  251. log: l.zapLogger,
  252. }
  253. }
  254. return disabledInfoLogger
  255. }
  256. func (l *zapLogger) Write(p []byte) (n int, err error) {
  257. l.zapLogger.Info(string(p))
  258. return len(p), nil
  259. }
  260. // WithValues creates a child logger and adds adds Zap fields to it.
  261. func WithValues(keysAndValues ...interface{}) Logger { return std.WithValues(keysAndValues...) }
  262. func (l *zapLogger) WithValues(keysAndValues ...interface{}) Logger {
  263. newLogger := l.zapLogger.With(handleFields(l.zapLogger, keysAndValues)...)
  264. return NewLogger(newLogger)
  265. }
  266. // WithName adds a new path segment to the logger's name. Segments are joined by
  267. // periods. By default, Loggers are unnamed.
  268. func WithName(s string) Logger { return std.WithName(s) }
  269. func (l *zapLogger) WithName(name string) Logger {
  270. newLogger := l.zapLogger.Named(name)
  271. return NewLogger(newLogger)
  272. }
  273. // Flush calls the underlying Core's Sync method, flushing any buffered
  274. // log entries. Applications should take care to call Sync before exiting.
  275. func Flush() { std.Flush() }
  276. func (l *zapLogger) Flush() {
  277. _ = l.zapLogger.Sync()
  278. }
  279. // NewLogger creates a new logr.Logger using the given Zap Logger to log.
  280. func NewLogger(l *zap.Logger) Logger {
  281. return &zapLogger{
  282. zapLogger: l,
  283. infoLogger: infoLogger{
  284. log: l,
  285. level: zap.InfoLevel,
  286. },
  287. }
  288. }
  289. // ZapLogger used for other log wrapper such as klog.
  290. func ZapLogger() *zap.Logger {
  291. return std.zapLogger
  292. }
  293. // CheckIntLevel used for other log wrapper such as klog which return if logging a
  294. // message at the specified level is enabled.
  295. func CheckIntLevel(level int32) bool {
  296. var lvl zapcore.Level
  297. if level < 5 {
  298. lvl = zapcore.InfoLevel
  299. } else {
  300. lvl = zapcore.DebugLevel
  301. }
  302. checkEntry := std.zapLogger.Check(lvl, "")
  303. return checkEntry != nil
  304. }
  305. // Debug method output debug level log.
  306. func Debug(msg string, fields ...Field) {
  307. std.zapLogger.Debug(msg, fields...)
  308. }
  309. func (l *zapLogger) Debug(msg string, fields ...Field) {
  310. l.zapLogger.Debug(msg, fields...)
  311. }
  312. // Debugf method output debug level log.
  313. func Debugf(format string, v ...interface{}) {
  314. std.zapLogger.Sugar().Debugf(format, v...)
  315. }
  316. func (l *zapLogger) Debugf(format string, v ...interface{}) {
  317. l.zapLogger.Sugar().Debugf(format, v...)
  318. }
  319. // Debugw method output debug level log.
  320. func Debugw(msg string, keysAndValues ...interface{}) {
  321. std.zapLogger.Sugar().Debugw(msg, keysAndValues...)
  322. }
  323. func (l *zapLogger) Debugw(msg string, keysAndValues ...interface{}) {
  324. l.zapLogger.Sugar().Debugw(msg, keysAndValues...)
  325. }
  326. // Info method output info level log.
  327. func Info(msg string, fields ...Field) {
  328. std.zapLogger.Info(msg, fields...)
  329. }
  330. func (l *zapLogger) Info(msg string, fields ...Field) {
  331. l.zapLogger.Info(msg, fields...)
  332. }
  333. // Infof method output info level log.
  334. func Infof(format string, v ...interface{}) {
  335. std.zapLogger.Sugar().Infof(format, v...)
  336. }
  337. func (l *zapLogger) Infof(format string, v ...interface{}) {
  338. l.zapLogger.Sugar().Infof(format, v...)
  339. }
  340. // Infow method output info level log.
  341. func Infow(msg string, keysAndValues ...interface{}) {
  342. std.zapLogger.Sugar().Infow(msg, keysAndValues...)
  343. }
  344. func (l *zapLogger) Infow(msg string, keysAndValues ...interface{}) {
  345. l.zapLogger.Sugar().Infow(msg, keysAndValues...)
  346. }
  347. // Warn method output warning level log.
  348. func Warn(msg string, fields ...Field) {
  349. std.zapLogger.Warn(msg, fields...)
  350. }
  351. func (l *zapLogger) Warn(msg string, fields ...Field) {
  352. l.zapLogger.Warn(msg, fields...)
  353. }
  354. // Warnf method output warning level log.
  355. func Warnf(format string, v ...interface{}) {
  356. std.zapLogger.Sugar().Warnf(format, v...)
  357. }
  358. func (l *zapLogger) Warnf(format string, v ...interface{}) {
  359. l.zapLogger.Sugar().Warnf(format, v...)
  360. }
  361. // Warnw method output warning level log.
  362. func Warnw(msg string, keysAndValues ...interface{}) {
  363. std.zapLogger.Sugar().Warnw(msg, keysAndValues...)
  364. }
  365. func (l *zapLogger) Warnw(msg string, keysAndValues ...interface{}) {
  366. l.zapLogger.Sugar().Warnw(msg, keysAndValues...)
  367. }
  368. // Error method output error level log.
  369. func Error(msg string, fields ...Field) {
  370. std.zapLogger.Error(msg, fields...)
  371. }
  372. func (l *zapLogger) Error(msg string, fields ...Field) {
  373. l.zapLogger.Error(msg, fields...)
  374. }
  375. // Errorf method output error level log.
  376. func Errorf(format string, v ...interface{}) {
  377. std.zapLogger.Sugar().Errorf(format, v...)
  378. }
  379. func (l *zapLogger) Errorf(format string, v ...interface{}) {
  380. l.zapLogger.Sugar().Errorf(format, v...)
  381. }
  382. // Errorw method output error level log.
  383. func Errorw(msg string, keysAndValues ...interface{}) {
  384. std.zapLogger.Sugar().Errorw(msg, keysAndValues...)
  385. }
  386. func (l *zapLogger) Errorw(msg string, keysAndValues ...interface{}) {
  387. l.zapLogger.Sugar().Errorw(msg, keysAndValues...)
  388. }
  389. // Panic method output panic level log and shutdown application.
  390. func Panic(msg string, fields ...Field) {
  391. std.zapLogger.Panic(msg, fields...)
  392. }
  393. func (l *zapLogger) Panic(msg string, fields ...Field) {
  394. l.zapLogger.Panic(msg, fields...)
  395. }
  396. // Panicf method output panic level log and shutdown application.
  397. func Panicf(format string, v ...interface{}) {
  398. std.zapLogger.Sugar().Panicf(format, v...)
  399. }
  400. func (l *zapLogger) Panicf(format string, v ...interface{}) {
  401. l.zapLogger.Sugar().Panicf(format, v...)
  402. }
  403. // Panicw method output panic level log.
  404. func Panicw(msg string, keysAndValues ...interface{}) {
  405. std.zapLogger.Sugar().Panicw(msg, keysAndValues...)
  406. }
  407. func (l *zapLogger) Panicw(msg string, keysAndValues ...interface{}) {
  408. l.zapLogger.Sugar().Panicw(msg, keysAndValues...)
  409. }
  410. // Fatal method output fatal level log.
  411. func Fatal(msg string, fields ...Field) {
  412. std.zapLogger.Fatal(msg, fields...)
  413. }
  414. func (l *zapLogger) Fatal(msg string, fields ...Field) {
  415. l.zapLogger.Fatal(msg, fields...)
  416. }
  417. // Fatalf method output fatal level log.
  418. func Fatalf(format string, v ...interface{}) {
  419. std.zapLogger.Sugar().Fatalf(format, v...)
  420. }
  421. func (l *zapLogger) Fatalf(format string, v ...interface{}) {
  422. l.zapLogger.Sugar().Fatalf(format, v...)
  423. }
  424. // Fatalw method output Fatalw level log.
  425. func Fatalw(msg string, keysAndValues ...interface{}) {
  426. std.zapLogger.Sugar().Fatalw(msg, keysAndValues...)
  427. }
  428. func (l *zapLogger) Fatalw(msg string, keysAndValues ...interface{}) {
  429. l.zapLogger.Sugar().Fatalw(msg, keysAndValues...)
  430. }
  431. // L method output with specified context value.
  432. func L(ctx context.Context) *zapLogger {
  433. return std.L(ctx)
  434. }
  435. func (l *zapLogger) L(ctx context.Context) *zapLogger {
  436. lg := l.clone()
  437. if requestID := ctx.Value(KeyRequestID); requestID != nil {
  438. lg.zapLogger = lg.zapLogger.With(zap.Any(KeyRequestID, requestID))
  439. }
  440. if username := ctx.Value(KeyUsername); username != nil {
  441. lg.zapLogger = lg.zapLogger.With(zap.Any(KeyUsername, username))
  442. }
  443. if watcherName := ctx.Value(KeyWatcherName); watcherName != nil {
  444. lg.zapLogger = lg.zapLogger.With(zap.Any(KeyWatcherName, watcherName))
  445. }
  446. return lg
  447. }
  448. //nolint:predeclared
  449. func (l *zapLogger) clone() *zapLogger {
  450. clone := *l
  451. return &clone
  452. }