github.com/lingyao2333/mo-zero@v1.4.1/core/logx/richlogger.go (about)

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