123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- package lib
- import (
- "bytes"
- "encoding/binary"
- "encoding/hex"
- "errors"
- "fmt"
- "github.com/gin-gonic/gin"
- "golang.org/x/net/context"
- "math/rand"
- "net"
- "os"
- "time"
- )
- var LocalIP = net.ParseIP("127.0.0.1")
- type Trace struct {
- TraceId string
- SpanId string
- Caller string
- SrcMethod string
- HintCode int64
- HintContent string
- }
- type TraceContext struct {
- Trace
- CSpanId string
- }
- func NewTrace() *TraceContext {
- trace := &TraceContext{}
- trace.TraceId = GetTraceId()
- trace.SpanId = NewSpanId()
- return trace
- }
- func NewSpanId() string {
- timestamp := uint32(time.Now().Unix())
- ipToLong := binary.BigEndian.Uint32(LocalIP.To4())
- b := bytes.Buffer{}
- b.WriteString(fmt.Sprintf("%08x", ipToLong^timestamp))
- b.WriteString(fmt.Sprintf("%08x", rand.Int31()))
- return b.String()
- }
- func GetTraceId() (traceId string) {
- return calcTraceId(LocalIP.String())
- }
- func calcTraceId(ip string) (traceId string) {
- now := time.Now()
- timestamp := uint32(now.Unix())
- timeNano := now.UnixNano()
- pid := os.Getpid()
- b := bytes.Buffer{}
- netIP := net.ParseIP(ip)
- if netIP == nil {
- b.WriteString("00000000")
- } else {
- b.WriteString(hex.EncodeToString(netIP.To4()))
- }
- b.WriteString(fmt.Sprintf("%08x", timestamp&0xffffffff))
- b.WriteString(fmt.Sprintf("%04x", timeNano&0xffff))
- b.WriteString(fmt.Sprintf("%04x", pid&0xffff))
- b.WriteString(fmt.Sprintf("%06x", rand.Int31n(1<<24)))
- b.WriteString("b0") // 末两位标记来源,b0为go
- return b.String()
- }
- func GetLocalIPs() (ips []net.IP) {
- interfaceAddr, err := net.InterfaceAddrs()
- if err != nil {
- return nil
- }
- for _, address := range interfaceAddr {
- ipNet, isValidIpNet := address.(*net.IPNet)
- if isValidIpNet && !ipNet.IP.IsLoopback() {
- if ipNet.IP.To4() != nil {
- ips = append(ips, ipNet.IP)
- }
- }
- }
- return ips
- }
- func SetGinTraceContext(c *gin.Context, trace *TraceContext) error {
- if trace == nil || c == nil {
- return errors.New("context is nil")
- }
- c.Set("trace", trace)
- return nil
- }
- func SetTraceContext(ctx context.Context, trace *TraceContext) context.Context {
- if trace == nil {
- return ctx
- }
- return context.WithValue(ctx, "trace", trace)
- }
- func GetTraceContext(ctx context.Context) *TraceContext {
- if ginCtx, ok := ctx.(*gin.Context); ok {
- traceIntraceContext, exists := ginCtx.Get("trace")
- if !exists {
- return NewTrace()
- }
- traceContext, ok := traceIntraceContext.(*TraceContext)
- if ok {
- return traceContext
- }
- return NewTrace()
- }
- if contextInterface, ok := ctx.(context.Context); ok {
- traceContext, ok := contextInterface.Value("trace").(*TraceContext)
- if ok {
- return traceContext
- }
- return NewTrace()
- }
- return NewTrace()
- }
|