context.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package trace
  2. import (
  3. "strconv"
  4. "strings"
  5. "github.com/pkg/errors"
  6. )
  7. const (
  8. flagSampled = 0x01
  9. flagDebug = 0x02
  10. )
  11. var (
  12. errEmptyTracerString = errors.New("trace: cannot convert empty string to spancontext")
  13. errInvalidTracerString = errors.New("trace: string does not match spancontext string format")
  14. )
  15. // SpanContext implements opentracing.SpanContext
  16. type spanContext struct {
  17. // traceID represents globally unique ID of the trace.
  18. // Usually generated as a random number.
  19. traceID uint64
  20. // spanID represents span ID that must be unique within its trace,
  21. // but does not have to be globally unique.
  22. spanID uint64
  23. // parentID refers to the ID of the parent span.
  24. // Should be 0 if the current span is a root span.
  25. parentID uint64
  26. // flags is a bitmap containing such bits as 'sampled' and 'debug'.
  27. flags byte
  28. // probability
  29. probability float32
  30. // current level
  31. level int
  32. }
  33. func (c spanContext) isSampled() bool {
  34. return (c.flags & flagSampled) == flagSampled
  35. }
  36. func (c spanContext) isDebug() bool {
  37. return (c.flags & flagDebug) == flagDebug
  38. }
  39. // IsValid check spanContext valid
  40. func (c spanContext) IsValid() bool {
  41. return c.traceID != 0 && c.spanID != 0
  42. }
  43. // emptyContext emptyContext
  44. var emptyContext = spanContext{}
  45. // String convert spanContext to String
  46. // {TraceID}:{SpanID}:{ParentID}:{flags}:[extend...]
  47. // TraceID: uint64 base16
  48. // SpanID: uint64 base16
  49. // ParentID: uint64 base16
  50. // flags:
  51. // - :0 sampled flag
  52. // - :1 debug flag
  53. // extend:
  54. // sample-rate: s-{base16(BigEndian(float32))}
  55. func (c spanContext) String() string {
  56. base := make([]string, 4)
  57. base[0] = strconv.FormatUint(uint64(c.traceID), 16)
  58. base[1] = strconv.FormatUint(uint64(c.spanID), 16)
  59. base[2] = strconv.FormatUint(uint64(c.parentID), 16)
  60. base[3] = strconv.FormatUint(uint64(c.flags), 16)
  61. return strings.Join(base, ":")
  62. }
  63. // ContextFromString parse spanContext form string
  64. func contextFromString(value string) (spanContext, error) {
  65. if value == "" {
  66. return emptyContext, errEmptyTracerString
  67. }
  68. items := strings.Split(value, ":")
  69. if len(items) < 4 {
  70. return emptyContext, errInvalidTracerString
  71. }
  72. parseHexUint64 := func(hexs []string) ([]uint64, error) {
  73. rets := make([]uint64, len(hexs))
  74. var err error
  75. for i, hex := range hexs {
  76. rets[i], err = strconv.ParseUint(hex, 16, 64)
  77. if err != nil {
  78. break
  79. }
  80. }
  81. return rets, err
  82. }
  83. rets, err := parseHexUint64(items[0:4])
  84. if err != nil {
  85. return emptyContext, errInvalidTracerString
  86. }
  87. sctx := spanContext{
  88. traceID: rets[0],
  89. spanID: rets[1],
  90. parentID: rets[2],
  91. flags: byte(rets[3]),
  92. }
  93. return sctx, nil
  94. }