richlogger.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package logx
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. "github.com/zeromicro/go-zero/core/timex"
  7. "go.opentelemetry.io/otel/trace"
  8. )
  9. // WithCallerSkip returns a Logger with given caller skip.
  10. func WithCallerSkip(skip int) Logger {
  11. if skip <= 0 {
  12. return new(richLogger)
  13. }
  14. return &richLogger{
  15. callerSkip: skip,
  16. }
  17. }
  18. // WithContext sets ctx to log, for keeping tracing information.
  19. func WithContext(ctx context.Context) Logger {
  20. return &richLogger{
  21. ctx: ctx,
  22. }
  23. }
  24. // WithDuration returns a Logger with given duration.
  25. func WithDuration(d time.Duration) Logger {
  26. return &richLogger{
  27. fields: []LogField{Field(durationKey, timex.ReprOfDuration(d))},
  28. }
  29. }
  30. type richLogger struct {
  31. ctx context.Context
  32. callerSkip int
  33. fields []LogField
  34. }
  35. func (l *richLogger) Debug(v ...interface{}) {
  36. l.debug(fmt.Sprint(v...))
  37. }
  38. func (l *richLogger) Debugf(format string, v ...interface{}) {
  39. l.debug(fmt.Sprintf(format, v...))
  40. }
  41. func (l *richLogger) Debugv(v interface{}) {
  42. l.debug(v)
  43. }
  44. func (l *richLogger) Debugw(msg string, fields ...LogField) {
  45. l.debug(msg, fields...)
  46. }
  47. func (l *richLogger) Error(v ...interface{}) {
  48. l.err(fmt.Sprint(v...))
  49. }
  50. func (l *richLogger) Errorf(format string, v ...interface{}) {
  51. l.err(fmt.Sprintf(format, v...))
  52. }
  53. func (l *richLogger) Errorv(v interface{}) {
  54. l.err(fmt.Sprint(v))
  55. }
  56. func (l *richLogger) Errorw(msg string, fields ...LogField) {
  57. l.err(msg, fields...)
  58. }
  59. func (l *richLogger) Info(v ...interface{}) {
  60. l.info(fmt.Sprint(v...))
  61. }
  62. func (l *richLogger) Infof(format string, v ...interface{}) {
  63. l.info(fmt.Sprintf(format, v...))
  64. }
  65. func (l *richLogger) Infov(v interface{}) {
  66. l.info(v)
  67. }
  68. func (l *richLogger) Infow(msg string, fields ...LogField) {
  69. l.info(msg, fields...)
  70. }
  71. func (l *richLogger) Slow(v ...interface{}) {
  72. l.slow(fmt.Sprint(v...))
  73. }
  74. func (l *richLogger) Slowf(format string, v ...interface{}) {
  75. l.slow(fmt.Sprintf(format, v...))
  76. }
  77. func (l *richLogger) Slowv(v interface{}) {
  78. l.slow(v)
  79. }
  80. func (l *richLogger) Sloww(msg string, fields ...LogField) {
  81. l.slow(msg, fields...)
  82. }
  83. func (l *richLogger) WithCallerSkip(skip int) Logger {
  84. if skip <= 0 {
  85. return l
  86. }
  87. l.callerSkip = skip
  88. return l
  89. }
  90. func (l *richLogger) WithContext(ctx context.Context) Logger {
  91. l.ctx = ctx
  92. return l
  93. }
  94. func (l *richLogger) WithDuration(duration time.Duration) Logger {
  95. l.fields = append(l.fields, Field(durationKey, timex.ReprOfDuration(duration)))
  96. return l
  97. }
  98. func (l *richLogger) buildFields(fields ...LogField) []LogField {
  99. fields = append(l.fields, fields...)
  100. fields = append(fields, Field(callerKey, getCaller(callerDepth+l.callerSkip)))
  101. if l.ctx == nil {
  102. return fields
  103. }
  104. traceID := traceIdFromContext(l.ctx)
  105. if len(traceID) > 0 {
  106. fields = append(fields, Field(traceKey, traceID))
  107. }
  108. spanID := spanIdFromContext(l.ctx)
  109. if len(spanID) > 0 {
  110. fields = append(fields, Field(spanKey, spanID))
  111. }
  112. val := l.ctx.Value(fieldsContextKey)
  113. if val != nil {
  114. if arr, ok := val.([]LogField); ok {
  115. fields = append(fields, arr...)
  116. }
  117. }
  118. return fields
  119. }
  120. func (l *richLogger) debug(v interface{}, fields ...LogField) {
  121. if shallLog(DebugLevel) {
  122. getWriter().Debug(v, l.buildFields(fields...)...)
  123. }
  124. }
  125. func (l *richLogger) err(v interface{}, fields ...LogField) {
  126. if shallLog(ErrorLevel) {
  127. getWriter().Error(v, l.buildFields(fields...)...)
  128. }
  129. }
  130. func (l *richLogger) info(v interface{}, fields ...LogField) {
  131. if shallLog(InfoLevel) {
  132. getWriter().Info(v, l.buildFields(fields...)...)
  133. }
  134. }
  135. func (l *richLogger) slow(v interface{}, fields ...LogField) {
  136. if shallLog(ErrorLevel) {
  137. getWriter().Slow(v, l.buildFields(fields...)...)
  138. }
  139. }
  140. func spanIdFromContext(ctx context.Context) string {
  141. spanCtx := trace.SpanContextFromContext(ctx)
  142. if spanCtx.HasSpanID() {
  143. return spanCtx.SpanID().String()
  144. }
  145. return ""
  146. }
  147. func traceIdFromContext(ctx context.Context) string {
  148. spanCtx := trace.SpanContextFromContext(ctx)
  149. if spanCtx.HasTraceID() {
  150. return spanCtx.TraceID().String()
  151. }
  152. return ""
  153. }