github.com/songzhibin97/gkit@v1.2.13/log/value.go (about)

     1  package log
     2  
     3  import (
     4  	"context"
     5  	"runtime"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	"go.opentelemetry.io/otel/trace"
    11  )
    12  
    13  var (
    14  	// DefaultCaller is a Valuer that returns the file and line.
    15  	DefaultCaller = Caller(3)
    16  
    17  	// DefaultTimestamp is a Valuer that returns the current wallclock time.
    18  	DefaultTimestamp = Timestamp(time.RFC3339)
    19  )
    20  
    21  type (
    22  	// Valuer log返回携带值
    23  	Valuer func(ctx context.Context) interface{}
    24  )
    25  
    26  // Value 尝试调用Valuer接口返回
    27  func Value(ctx context.Context, value interface{}) interface{} {
    28  	if v, ok := value.(Valuer); ok {
    29  		return v(ctx)
    30  	}
    31  	return value
    32  }
    33  
    34  // Caller 返回调用方的堆信息
    35  func Caller(depth int) Valuer {
    36  	return func(ctx context.Context) interface{} {
    37  		_, file, line, _ := runtime.Caller(depth)
    38  		if strings.LastIndex(file, "gkit/log") > 0 {
    39  			_, file, line, _ = runtime.Caller(depth + 1)
    40  		}
    41  		idx := strings.LastIndexByte(file, '/')
    42  		return file[idx+1:] + ":" + strconv.Itoa(line)
    43  	}
    44  }
    45  
    46  // Timestamp 返回指定layout的时间戳 Valuer
    47  func Timestamp(layout string) Valuer {
    48  	return func(context.Context) interface{} {
    49  		return time.Now().Format(layout)
    50  	}
    51  }
    52  
    53  // TraceID 返回链路追踪使用的tranceID Valuer
    54  // TraceID 来将一个请求在各个服务器上的调用日志串联起来
    55  func TraceID() Valuer {
    56  	return func(ctx context.Context) interface{} {
    57  		if span := trace.SpanContextFromContext(ctx); span.HasTraceID() {
    58  			return span.TraceID().String()
    59  		}
    60  		return ""
    61  	}
    62  }
    63  
    64  // SpanID 返回链路定位的 SpanID Valuer
    65  // SpanID 代表本次调用在整个调用链路树中的位置
    66  func SpanID() Valuer {
    67  	return func(ctx context.Context) interface{} {
    68  		if span := trace.SpanContextFromContext(ctx); span.HasSpanID() {
    69  			return span.SpanID().String()
    70  		}
    71  		return ""
    72  	}
    73  }
    74  
    75  // bindValues 判断 kvs 的 v 是否是 Valuer对象 如果是的话将ctx传入保存
    76  func bindValues(ctx context.Context, kvs []interface{}) {
    77  	for i := 1; i < len(kvs); i += 2 {
    78  		if v, ok := kvs[i].(Valuer); ok {
    79  			kvs[i] = v(ctx)
    80  		}
    81  	}
    82  }
    83  
    84  // containsValuer 判断 kvs 中 v是否是 Valuer 如果有立即返回true
    85  func containsValuer(kvs []interface{}) bool {
    86  	for i := 1; i < len(kvs); i += 2 {
    87  		if _, ok := kvs[i].(Valuer); ok {
    88  			return true
    89  		}
    90  	}
    91  	return false
    92  }