github.com/replit/upm@v0.0.0-20240423230255-9ce4fc3ea24c/internal/trace/spancontext.go (about)

     1  /*
     2  This SpanContext implements
     3  [ddtrace.SpanContextW3C](https://github.com/DataDog/dd-trace-go/blob/49273dfcc871f3329614c40cd98116b6d44cdb12/ddtrace/ddtrace.go#L25)
     4  , implementation is mostly based on
     5  https://github.com/DataDog/dd-trace-go/blob/49273dfcc871f3329614c40cd98116b6d44cdb12/ddtrace/tracer/spancontext.go#L85
     6  
     7  We have our own version because that one was made private.
     8  */
     9  
    10  package trace
    11  
    12  import (
    13  	"encoding/binary"
    14  	"encoding/hex"
    15  	"errors"
    16  	"fmt"
    17  	"strconv"
    18  	"strings"
    19  
    20  	"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
    21  )
    22  
    23  type SpanContext struct {
    24  	traceID traceID
    25  	spanID  uint64
    26  }
    27  
    28  type traceID [16]byte // traceID in big endian, i.e. <upper><lower>
    29  
    30  var ErrSpanContextCorrupted = errors.New("span context corrupted")
    31  
    32  func (c *SpanContext) TraceID128() string {
    33  	return c.traceID.HexEncoded()
    34  }
    35  
    36  func (c *SpanContext) TraceID128Bytes() [16]byte {
    37  	return c.traceID
    38  }
    39  
    40  func (c *SpanContext) TraceID() uint64 {
    41  	return c.traceID.Lower()
    42  }
    43  
    44  func (c *SpanContext) SpanID() uint64 {
    45  	return c.spanID
    46  }
    47  
    48  func (c *SpanContext) ForeachBaggageItem(handler func(k, v string) bool) {
    49  }
    50  
    51  func GetHexSpanID(c ddtrace.SpanContextW3C) string {
    52  	return fmt.Sprintf("%016x", c.SpanID())
    53  }
    54  
    55  func GetHexTraceID(c ddtrace.SpanContextW3C) string {
    56  	return fmt.Sprintf("%032x", c.TraceID128Bytes())
    57  }
    58  
    59  func (c *SpanContext) ParseTraceID(v string) error {
    60  	if len(v) > 32 {
    61  		v = v[len(v)-32:]
    62  	}
    63  	v = strings.TrimLeft(v, "0")
    64  	var err error
    65  	if len(v) <= 16 { // 64-bit trace id
    66  		var tid uint64
    67  		tid, err = strconv.ParseUint(v, 16, 64)
    68  		c.traceID.SetLower(tid)
    69  	} else { // 128-bit trace id
    70  		idUpper := v[:len(v)-16]
    71  		//nolint:errcheck
    72  		c.traceID.SetUpperFromHex(idUpper)
    73  		var l uint64
    74  		l, err = strconv.ParseUint(v[len(idUpper):], 16, 64)
    75  		c.traceID.SetLower(l)
    76  	}
    77  	if err != nil {
    78  		return ErrSpanContextCorrupted
    79  	}
    80  	return nil
    81  }
    82  
    83  func (c *SpanContext) ParseSpanID(v string) error {
    84  	var err error
    85  	c.spanID, err = strconv.ParseUint(v, 16, 64)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	return nil
    90  }
    91  
    92  func (t *traceID) HexEncoded() string {
    93  	return hex.EncodeToString(t[:])
    94  }
    95  
    96  func (t *traceID) Lower() uint64 {
    97  	return binary.BigEndian.Uint64(t[8:])
    98  }
    99  
   100  func (t *traceID) Upper() uint64 {
   101  	return binary.BigEndian.Uint64(t[:8])
   102  }
   103  
   104  func (t *traceID) SetLower(i uint64) {
   105  	binary.BigEndian.PutUint64(t[8:], i)
   106  }
   107  
   108  func (t *traceID) SetUpper(i uint64) {
   109  	binary.BigEndian.PutUint64(t[:8], i)
   110  }
   111  
   112  func (t *traceID) SetUpperFromHex(s string) error {
   113  	u, err := strconv.ParseUint(s, 16, 64)
   114  	if err != nil {
   115  		return fmt.Errorf("malformed %q: %s", s, err)
   116  	}
   117  	t.SetUpper(u)
   118  	return nil
   119  }