1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-03-07 15:10:43 +02:00

api(trace): change trace id to byte array. ()

* api(trace): change trace id to byte array.

* fix lint errors

* add helper to create trace id from hex and improve stdout exporter.

* remove comma.

* fix lint

* change TraceIDFromHex to be compliant with w3 trace-context

* revert remove of hex16 regex because its used to parse SpanID

* lint

* fix typo
This commit is contained in:
Gustavo Silva Paiva 2019-10-23 03:01:33 -03:00 committed by rghetia
parent cf62d12648
commit a6e139e1d4
21 changed files with 209 additions and 150 deletions

@ -15,14 +15,13 @@
package core
import (
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
)
type TraceID struct {
High uint64
Low uint64
}
const (
traceFlagsBitMaskSampled = byte(0x01)
traceFlagsBitMaskUnused = byte(0xFE)
@ -33,23 +32,81 @@ const (
TraceFlagsUnused = traceFlagsBitMaskUnused
)
type TraceID [16]byte
var nilTraceID TraceID
func (t TraceID) isValid() bool {
return !bytes.Equal(t[:], nilTraceID[:])
}
// TraceIDFromHex returns a TraceID from a hex string if it is compliant
// with the w3c trace-context specification.
// See more at https://www.w3.org/TR/trace-context/#trace-id
func TraceIDFromHex(h string) (TraceID, error) {
t := TraceID{}
if len(h) != 32 {
return t, errors.New("hex encoded trace-id must have length equals to 32")
}
for _, r := range h {
switch {
case 'a' <= r && r <= 'f':
continue
case '0' <= r && r <= '9':
continue
default:
return t, errors.New("trace-id can only contain [0-9a-f] characters, all lowercase")
}
}
b, err := hex.DecodeString(h)
if err != nil {
return t, err
}
copy(t[:], b)
if !t.isValid() {
return t, errors.New("trace-id can't be all zero")
}
return t, nil
}
type SpanContext struct {
TraceID TraceID
SpanID uint64
TraceFlags byte
}
var _ json.Marshaler = (*SpanContext)(nil)
// EmptySpanContext is meant for internal use to return invalid span context during error conditions.
func EmptySpanContext() SpanContext {
return SpanContext{}
}
// MarshalJSON implements a custom marshal function to encode SpanContext
// in a human readable format with hex encoded TraceID and SpanID.
func (sc SpanContext) MarshalJSON() ([]byte, error) {
type JSONSpanContext struct {
TraceID string
SpanID string
TraceFlags byte
}
return json.Marshal(JSONSpanContext{
TraceID: sc.TraceIDString(),
SpanID: sc.SpanIDString(),
TraceFlags: sc.TraceFlags,
})
}
func (sc SpanContext) IsValid() bool {
return sc.HasTraceID() && sc.HasSpanID()
}
func (sc SpanContext) HasTraceID() bool {
return sc.TraceID.High != 0 || sc.TraceID.Low != 0
return sc.TraceID.isValid()
}
func (sc SpanContext) HasSpanID() bool {
@ -61,9 +118,7 @@ func (sc SpanContext) SpanIDString() string {
}
func (sc SpanContext) TraceIDString() string {
p1 := fmt.Sprintf("%.16x", sc.TraceID.High)
p2 := fmt.Sprintf("%.16x", sc.TraceID.Low)
return p1 + p2
return hex.EncodeToString(sc.TraceID[:])
}
func (sc SpanContext) IsSampled() bool {

@ -29,22 +29,22 @@ func TestIsValid(t *testing.T) {
}{
{
name: "SpanContext.IsValid() returns true if sc has both an Trace ID and Span ID",
tid: core.TraceID{High: uint64(42)},
tid: core.TraceID([16]byte{1}),
sid: uint64(42),
want: true,
}, {
name: "SpanContext.IsValid() returns false if sc has neither an Trace ID nor Span ID",
tid: core.TraceID{High: uint64(0)},
tid: core.TraceID([16]byte{}),
sid: uint64(0),
want: false,
}, {
name: "SpanContext.IsValid() returns false if sc has a Span ID but not a Trace ID",
tid: core.TraceID{High: uint64(0)},
tid: core.TraceID([16]byte{}),
sid: uint64(42),
want: false,
}, {
name: "SpanContext.IsValid() returns false if sc has a Trace ID but not a Span ID",
tid: core.TraceID{High: uint64(42)},
tid: core.TraceID([16]byte{1}),
sid: uint64(0),
want: false,
},
@ -62,6 +62,50 @@ func TestIsValid(t *testing.T) {
}
}
func TestIsValidFromHex(t *testing.T) {
for _, testcase := range []struct {
name string
hex string
tid core.TraceID
valid bool
}{
{
name: "Valid TraceID",
tid: core.TraceID([16]byte{128, 241, 152, 238, 86, 52, 59, 168, 100, 254, 139, 42, 87, 211, 239, 247}),
hex: "80f198ee56343ba864fe8b2a57d3eff7",
valid: true,
}, {
name: "Invalid TraceID with invalid length",
hex: "80f198ee56343ba864fe8b2a57d3eff",
valid: false,
}, {
name: "Invalid TraceID with invalid char",
hex: "80f198ee56343ba864fe8b2a57d3efg7",
valid: false,
}, {
name: "Invalid TraceID with uppercase",
hex: "80f198ee56343ba864fe8b2a57d3efF7",
valid: false,
},
} {
t.Run(testcase.name, func(t *testing.T) {
tid, err := core.TraceIDFromHex(testcase.hex)
if testcase.valid && err != nil {
t.Errorf("Expected TraceID %s to be valid but end with error %s", testcase.hex, err.Error())
}
if !testcase.valid && err == nil {
t.Errorf("Expected TraceID %s to be invalid but end no error", testcase.hex)
}
if tid != testcase.tid {
t.Errorf("Want: %v, but have: %v", testcase.tid, tid)
}
})
}
}
func TestHasTraceID(t *testing.T) {
for _, testcase := range []struct {
name string
@ -70,20 +114,12 @@ func TestHasTraceID(t *testing.T) {
}{
{
name: "SpanContext.HasTraceID() returns true if both Low and High are nonzero",
tid: core.TraceID{High: uint64(42), Low: uint64(42)},
tid: core.TraceID([16]byte{1}),
want: true,
}, {
name: "SpanContext.HasTraceID() returns false if neither Low nor High are nonzero",
tid: core.TraceID{},
want: false,
}, {
name: "SpanContext.HasTraceID() returns true if High != 0",
tid: core.TraceID{High: uint64(42)},
want: true,
}, {
name: "SpanContext.HasTraceID() returns true if Low != 0",
tid: core.TraceID{Low: uint64(42)},
want: true,
},
} {
t.Run(testcase.name, func(t *testing.T) {
@ -158,12 +194,9 @@ func TestTraceIDString(t *testing.T) {
{
name: "SpanContext.TraceIDString returns string representation of self.TraceID values > 0",
sc: core.SpanContext{
TraceID: core.TraceID{
High: uint64(42),
Low: uint64(42),
},
TraceID: core.TraceID([16]byte{255}),
},
want: `000000000000002a000000000000002a`,
want: `ff000000000000000000000000000000`,
}, {
name: "SpanContext.TraceIDString returns string representation of self.TraceID values == 0",
sc: core.SpanContext{TraceID: core.TraceID{}},
@ -189,20 +222,14 @@ func TestSpanContextIsSampled(t *testing.T) {
{
name: "sampled",
sc: core.SpanContext{
TraceID: core.TraceID{
High: uint64(42),
Low: uint64(42),
},
TraceID: core.TraceID([16]byte{1}),
TraceFlags: core.TraceFlagsSampled,
},
want: true,
}, {
name: "sampled plus unused",
sc: core.SpanContext{
TraceID: core.TraceID{
High: uint64(42),
Low: uint64(42),
},
TraceID: core.TraceID([16]byte{1}),
TraceFlags: core.TraceFlagsSampled | core.TraceFlagsUnused,
},
want: true,

@ -31,7 +31,7 @@ import (
otelcore "go.opentelemetry.io/api/core"
oteltrace "go.opentelemetry.io/api/trace"
migration "go.opentelemetry.io/experimental/bridge/opentracing/migration"
"go.opentelemetry.io/experimental/bridge/opentracing/migration"
)
type bridgeSpanContext struct {
@ -512,7 +512,7 @@ func (t *BridgeTracer) Inject(sm ot.SpanContext, format interface{}, carrier int
if !ok {
return ot.ErrInvalidCarrier
}
hhcarrier.Set(traceIDHeader, traceIDString(bridgeSC.otelSpanContext.TraceID))
hhcarrier.Set(traceIDHeader, bridgeSC.otelSpanContext.TraceIDString())
hhcarrier.Set(spanIDHeader, spanIDToString(bridgeSC.otelSpanContext.SpanID))
hhcarrier.Set(traceFlagsHeader, traceFlagsToString(bridgeSC.otelSpanContext.TraceFlags))
bridgeSC.ForeachBaggageItem(func(k, v string) bool {
@ -523,12 +523,6 @@ func (t *BridgeTracer) Inject(sm ot.SpanContext, format interface{}, carrier int
return nil
}
// mostly copied from core/span_context.go, but I prefer not to rely
// on some impl details
func traceIDString(traceID otelcore.TraceID) string {
return fmt.Sprintf("%.16x%.16x", traceID.High, traceID.Low)
}
func spanIDToString(spanID uint64) string {
return fmt.Sprintf("%.16x", spanID)
}
@ -558,7 +552,7 @@ func (t *BridgeTracer) Extract(format interface{}, carrier interface{}) (ot.Span
ck := http.CanonicalHeaderKey(k)
switch ck {
case traceIDHeader:
traceID, err := traceIDFromString(v)
traceID, err := otelcore.TraceIDFromHex(v)
if err != nil {
return err
}
@ -588,23 +582,6 @@ func (t *BridgeTracer) Extract(format interface{}, carrier interface{}) (ot.Span
return bridgeSC, nil
}
func traceIDFromString(s string) (otelcore.TraceID, error) {
traceID := otelcore.TraceID{}
if len(s) != 32 {
return traceID, fmt.Errorf("invalid trace ID")
}
high, err := strconv.ParseUint(s[0:16], 16, 64)
if err != nil {
return traceID, err
}
low, err := strconv.ParseUint(s[16:32], 16, 64)
if err != nil {
return traceID, err
}
traceID.High, traceID.Low = high, low
return traceID, nil
}
func spanIDFromString(s string) (uint64, error) {
if len(s) != 16 {
return 0, fmt.Errorf("invalid span ID")

@ -145,11 +145,7 @@ func (t *MockTracer) getTraceID(ctx context.Context, spanOpts *oteltrace.SpanOpt
}
return traceID
}
uints := t.getNRandUint64(2)
return otelcore.TraceID{
High: uints[0],
Low: uints[1],
}
return t.getRandTraceID()
}
func (t *MockTracer) getParentSpanID(ctx context.Context, spanOpts *oteltrace.SpanOptions) uint64 {
@ -183,17 +179,19 @@ func (t *MockTracer) getSpanID() uint64 {
}
func (t *MockTracer) getRandUint64() uint64 {
return t.getNRandUint64(1)[0]
}
func (t *MockTracer) getNRandUint64(n int) []uint64 {
uints := make([]uint64, n)
t.randLock.Lock()
defer t.randLock.Unlock()
for i := 0; i < n; i++ {
uints[i] = t.rand.Uint64()
}
return uints
return t.rand.Uint64()
}
func (t *MockTracer) getRandTraceID() otelcore.TraceID {
t.randLock.Lock()
defer t.randLock.Unlock()
tid := otelcore.TraceID{}
t.rand.Read(tid[:])
return tid
}
func (t *MockTracer) DeferredContextSetupHook(ctx context.Context, span oteltrace.Span) context.Context {

@ -504,10 +504,7 @@ func reverse(length int, swap func(i, j int)) {
}
func simpleTraceID() otelcore.TraceID {
return otelcore.TraceID{
High: 1357,
Low: 2468,
}
return [16]byte{123, 42}
}
func simpleSpanIDs(count int) []uint64 {

@ -16,6 +16,7 @@ package jaeger
import (
"context"
"encoding/binary"
"log"
"sync"
@ -196,8 +197,8 @@ func spanDataToThrift(data *export.SpanData) *gen.Span {
var refs []*gen.SpanRef
for _, link := range data.Links {
refs = append(refs, &gen.SpanRef{
TraceIdHigh: int64(link.TraceID.High),
TraceIdLow: int64(link.TraceID.Low),
TraceIdHigh: int64(binary.BigEndian.Uint64(link.TraceID[0:8])),
TraceIdLow: int64(binary.BigEndian.Uint64(link.TraceID[8:16])),
SpanId: int64(link.SpanID),
// TODO(paivagustavo): properly set the reference type when specs are defined
// see https://github.com/open-telemetry/opentelemetry-specification/issues/65
@ -206,8 +207,8 @@ func spanDataToThrift(data *export.SpanData) *gen.Span {
}
return &gen.Span{
TraceIdHigh: int64(data.SpanContext.TraceID.High),
TraceIdLow: int64(data.SpanContext.TraceID.Low),
TraceIdHigh: int64(binary.BigEndian.Uint64(data.SpanContext.TraceID[0:8])),
TraceIdLow: int64(binary.BigEndian.Uint64(data.SpanContext.TraceID[8:16])),
SpanId: int64(data.SpanContext.SpanID),
ParentSpanId: int64(data.ParentSpanID),
OperationName: data.Name, // TODO: if span kind is added then add prefix "Sent"/"Recv"

@ -15,6 +15,7 @@
package jaeger
import (
"encoding/binary"
"sort"
"testing"
"time"
@ -35,10 +36,10 @@ import (
func Test_spanDataToThrift(t *testing.T) {
now := time.Now()
traceID := core.TraceID{High: 0x0102030405060708, Low: 0x090a0b0c0d0e0f10}
traceID, _ := core.TraceIDFromHex("0102030405060708090a0b0c0d0e0f10")
spanID := uint64(0x0102030405060708)
linkTraceID := core.TraceID{High: 0x0102030405060709, Low: 0x090a0b0c0d0e0f11}
linkTraceID, _ := core.TraceIDFromHex("0102030405060709090a0b0c0d0e0f11")
linkSpanID := uint64(0x0102030405060709)
keyValue := "value"
@ -99,8 +100,8 @@ func Test_spanDataToThrift(t *testing.T) {
References: []*gen.SpanRef{
{
RefType: gen.SpanRefType_CHILD_OF,
TraceIdLow: int64(linkTraceID.Low),
TraceIdHigh: int64(linkTraceID.High),
TraceIdHigh: int64(binary.BigEndian.Uint64(linkTraceID[0:8])),
TraceIdLow: int64(binary.BigEndian.Uint64(linkTraceID[8:16])),
SpanId: int64(linkSpanID),
},
},

@ -39,7 +39,7 @@ func TestExporter_ExportSpan(t *testing.T) {
// setup test span
now := time.Now()
traceID := core.TraceID{High: 0x0102030405060708, Low: 0x090a0b0c0d0e0f10}
traceID, _ := core.TraceIDFromHex("0102030405060708090a0b0c0d0e0f10")
spanID := uint64(0x0102030405060708)
keyValue := "value"
doubleValue := float64(123.456)
@ -70,8 +70,8 @@ func TestExporter_ExportSpan(t *testing.T) {
got := b.String()
expectedOutput := `{"SpanContext":{` +
`"TraceID":{"High":72623859790382856,"Low":651345242494996240},` +
`"SpanID":72623859790382856,"TraceFlags":0},` +
`"TraceID":"0102030405060708090a0b0c0d0e0f10",` +
`"SpanID":"0102030405060708","TraceFlags":0},` +
`"ParentSpanID":0,` +
`"SpanKind":0,` +
`"Name":"/foo",` +

@ -16,7 +16,7 @@ package trace
import (
"context"
"math/rand"
"crypto/rand"
"sync/atomic"
"go.opentelemetry.io/api/core"
@ -69,12 +69,8 @@ func (mt *MockTracer) Start(ctx context.Context, name string, o ...apitrace.Span
var span *MockSpan
var sc core.SpanContext
if !opts.Relation.SpanContext.IsValid() {
sc = core.SpanContext{
TraceID: core.TraceID{
High: rand.Uint64(),
Low: rand.Uint64(),
},
}
sc = core.SpanContext{}
_, _ = rand.Read(sc.TraceID[:])
if mt.Sampled {
sc.TraceFlags = core.TraceFlagsSampled
}

@ -38,8 +38,7 @@ func (bp binaryPropagator) ToBytes(sc core.SpanContext) []byte {
return nil
}
var b [29]byte
binary.BigEndian.PutUint64(b[2:10], sc.TraceID.High)
binary.BigEndian.PutUint64(b[10:18], sc.TraceID.Low)
copy(b[2:18], sc.TraceID[:])
b[18] = 1
binary.BigEndian.PutUint64(b[19:27], sc.SpanID)
b[27] = 2
@ -55,8 +54,7 @@ func (bp binaryPropagator) FromBytes(b []byte) (sc core.SpanContext) {
}
b = b[1:]
if len(b) >= 17 && b[0] == 0 {
sc.TraceID.High = binary.BigEndian.Uint64(b[1:9])
sc.TraceID.Low = binary.BigEndian.Uint64(b[9:17])
copy(sc.TraceID[:], b[1:17])
b = b[17:]
} else {
return core.EmptySpanContext()

@ -15,6 +15,7 @@
package propagation_test
import (
"encoding/hex"
"testing"
"github.com/google/go-cmp/cmp"
@ -24,7 +25,10 @@ import (
)
func TestExtractSpanContextFromBytes(t *testing.T) {
traceID := core.TraceID{High: 0x4bf92f3577b34da6, Low: 0xa3ce929d0e0e4736}
bTraceID, _ := hex.DecodeString("4bf92f3577b34da6a3ce929d0e0e4736")
traceID := core.TraceID{}
copy(traceID[:], bTraceID)
spanID := uint64(0x00f067aa0ba902b7)
propagator := propagation.BinaryPropagator()
tests := []struct {
@ -119,7 +123,10 @@ func TestExtractSpanContextFromBytes(t *testing.T) {
}
func TestConvertSpanContextToBytes(t *testing.T) {
traceID := core.TraceID{High: 0x4bf92f3577b34da6, Low: 0xa3ce929d0e0e4736}
bTraceID, _ := hex.DecodeString("4bf92f3577b34da6a3ce929d0e0e4736")
traceID := core.TraceID{}
copy(traceID[:], bTraceID)
spanID := uint64(0x00f067aa0ba902b7)
propagator := propagation.BinaryPropagator()
tests := []struct {

@ -57,7 +57,6 @@ type HTTPB3Propagator struct {
var _ apipropagation.TextFormatPropagator = HTTPB3Propagator{}
var hexStr32ByteRegex = regexp.MustCompile("^[a-f0-9]{32}$")
var hexStr16ByteRegex = regexp.MustCompile("^[a-f0-9]{16}$")
func (b3 HTTPB3Propagator) Inject(ctx context.Context, supplier apipropagation.Supplier) {
@ -66,10 +65,9 @@ func (b3 HTTPB3Propagator) Inject(ctx context.Context, supplier apipropagation.S
if b3.SingleHeader {
sampled := sc.TraceFlags & core.TraceFlagsSampled
supplier.Set(B3SingleHeader,
fmt.Sprintf("%.16x%.16x-%.16x-%.1d", sc.TraceID.High, sc.TraceID.Low, sc.SpanID, sampled))
fmt.Sprintf("%s-%.16x-%.1d", sc.TraceIDString(), sc.SpanID, sampled))
} else {
supplier.Set(B3TraceIDHeader,
fmt.Sprintf("%.16x%.16x", sc.TraceID.High, sc.TraceID.Low))
supplier.Set(B3TraceIDHeader, sc.TraceIDString())
supplier.Set(B3SpanIDHeader,
fmt.Sprintf("%.16x", sc.SpanID))
@ -183,15 +181,8 @@ func (b3 HTTPB3Propagator) extractSingleHeader(supplier apipropagation.Supplier)
// extractTraceID parses the value of the X-B3-TraceId b3Header.
func (b3 HTTPB3Propagator) extractTraceID(tid string) (traceID core.TraceID, ok bool) {
if hexStr32ByteRegex.MatchString(tid) {
traceID.High, _ = strconv.ParseUint(tid[0:(16)], 16, 64)
traceID.Low, _ = strconv.ParseUint(tid[(16):32], 16, 64)
ok = true
} else if b3.SingleHeader && hexStr16ByteRegex.MatchString(tid) {
traceID.Low, _ = strconv.ParseUint(tid[:16], 16, 64)
ok = true
}
return traceID, ok
traceID, err := core.TraceIDFromHex(tid)
return traceID, err == nil
}
// extractSpanID parses the value of the X-B3-SpanId or X-B3-ParentSpanId headers.

@ -46,10 +46,9 @@ var traceCtxRegExp = regexp.MustCompile("^[0-9a-f]{2}-[a-f0-9]{32}-[a-f0-9]{16}-
func (hp HTTPTraceContextPropagator) Inject(ctx context.Context, supplier apipropagation.Supplier) {
sc := trace.CurrentSpan(ctx).SpanContext()
if sc.IsValid() {
h := fmt.Sprintf("%.2x-%.16x%.16x-%.16x-%.2x",
h := fmt.Sprintf("%.2x-%s-%.16x-%.2x",
supportedVersion,
sc.TraceID.High,
sc.TraceID.Low,
sc.TraceIDString(),
sc.SpanID,
sc.TraceFlags&core.TraceFlagsSampled)
supplier.Set(TraceparentHeader, h)
@ -118,24 +117,17 @@ func (hp HTTPTraceContextPropagator) extractSpanContext(
return core.EmptySpanContext()
}
result, err := strconv.ParseUint(sections[1][0:16], 16, 64)
if err != nil {
return core.EmptySpanContext()
}
var sc core.SpanContext
sc.TraceID.High = result
result, err = strconv.ParseUint(sections[1][16:32], 16, 64)
_, err = hex.Decode(sc.TraceID[0:16], []byte(sections[1][0:32]))
if err != nil {
return core.EmptySpanContext()
}
sc.TraceID.Low = result
if len(sections[2]) != 16 {
return core.EmptySpanContext()
}
result, err = strconv.ParseUint(sections[2][0:], 16, 64)
result, err := strconv.ParseUint(sections[2][0:], 16, 64)
if err != nil {
return core.EmptySpanContext()
}

@ -2,6 +2,7 @@ package propagation
import (
"context"
"encoding/hex"
"net/http"
"testing"
@ -27,8 +28,11 @@ func injectSubBenchmarks(b *testing.B, fn func(context.Context, *testing.B)) {
var (
id uint64
spanID = uint64(0x00f067aa0ba902b7)
traceID = core.TraceID{High: 0x4bf92f3577b34da6, Low: 0xa3ce929d0e0e4736}
traceID = core.TraceID{}
)
bt, _ := hex.DecodeString("4bf92f3577b34da6a3ce929d0e0e4736")
copy(traceID[:], bt)
mockTracer := &mocktrace.MockTracer{
Sampled: false,
StartSpanID: &id,

@ -31,10 +31,15 @@ import (
)
var (
traceID = core.TraceID{High: 0x4bf92f3577b34da6, Low: 0xa3ce929d0e0e4736}
traceID = mustTraceIDFromHex("4bf92f3577b34da6a3ce929d0e0e4736")
spanID = uint64(0x00f067aa0ba902b7)
)
func mustTraceIDFromHex(s string) (t core.TraceID) {
t, _ = core.TraceIDFromHex(s)
return
}
func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
var propagator propagation.HTTPTraceContextPropagator
tests := []struct {

@ -16,6 +16,7 @@ package trace_test
import (
"context"
"encoding/binary"
"sync"
"testing"
"time"
@ -164,7 +165,7 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
// Check first Span is reported. Most recent one is dropped.
sc := getSpanContext()
wantTraceID := sc.TraceID
wantTraceID.High = 1
binary.BigEndian.PutUint64(wantTraceID[0:8], uint64(1))
gotTraceID := te.get(0).SpanContext.TraceID
if wantTraceID != gotTraceID {
t.Errorf("%s: first exported span: got %+v, want %+v\n", option.name, gotTraceID, wantTraceID)
@ -185,14 +186,14 @@ func generateSpan(t *testing.T, tr apitrace.Tracer, option testOption) {
sc := getSpanContext()
for i := 0; i < option.genNumSpans; i++ {
sc.TraceID.High = uint64(i + 1)
binary.BigEndian.PutUint64(sc.TraceID[0:8], uint64(i+1))
_, span := tr.Start(context.Background(), option.name, apitrace.ChildOf(sc))
span.End()
}
}
func getSpanContext() core.SpanContext {
tid := core.TraceID{High: 0x0102030405060708, Low: 0x0102040810203040}
tid, _ := core.TraceIDFromHex("01020304050607080102040810203040")
sid := uint64(0x0102040810203040)
return core.SpanContext{
TraceID: tid,

@ -147,7 +147,8 @@ func BenchmarkSpanWithAttributes_all_2x(b *testing.B) {
func BenchmarkTraceID_DotString(b *testing.B) {
traceBenchmark(b, func(b *testing.B) {
sc := core.SpanContext{TraceID: core.TraceID{High: 1, Low: 0x2a}}
t, _ := core.TraceIDFromHex("0000000000000001000000000000002a")
sc := core.SpanContext{TraceID: t}
want := "0000000000000001000000000000002a"
for i := 0; i < b.N; i++ {

@ -59,9 +59,7 @@ func (gen *defaultIDGenerator) NewTraceID() core.TraceID {
defer gen.Unlock()
// Construct the trace ID from two outputs of traceIDRand, with a constant
// added to each half for additional entropy.
tid := core.TraceID{
High: gen.traceIDRand.Uint64() + gen.traceIDAdd[0],
Low: gen.traceIDRand.Uint64() + gen.traceIDAdd[1],
}
tid := core.TraceID{}
gen.traceIDRand.Read(tid[:])
return tid
}

@ -15,6 +15,8 @@
package trace
import (
"encoding/binary"
"go.opentelemetry.io/api/core"
)
@ -52,7 +54,7 @@ func ProbabilitySampler(fraction float64) Sampler {
if p.ParentContext.IsSampled() {
return SamplingDecision{Sample: true}
}
x := p.TraceID.High >> 1
x := binary.BigEndian.Uint64(p.TraceID[0:8]) >> 1
return SamplingDecision{Sample: x < traceIDUpperBound}
})
}

@ -55,9 +55,10 @@ func TestSimpleSpanProcessorOnEnd(t *testing.T) {
if ssp == nil {
t.Errorf("Error creating new instance of SimpleSpanProcessor with nil Exporter\n")
}
tp.RegisterSpanProcessor(ssp)
tr := tp.GetTracer("SimpleSpanProcessor")
tid := core.TraceID{High: 0x0102030405060708, Low: 0x0102040810203040}
tid, _ := core.TraceIDFromHex("01020304050607080102040810203040")
sid := uint64(0x0102040810203040)
sc := core.SpanContext{
TraceID: tid,

@ -34,10 +34,14 @@ import (
)
var (
tid = core.TraceID{High: 0x0102030405060708, Low: 0x0102040810203040}
tid core.TraceID
sid = uint64(0x0102040810203040)
)
func init() {
tid, _ = core.TraceIDFromHex("01020304050607080102040810203040")
}
func TestTracerFollowsExpectedAPIBehaviour(t *testing.T) {
tp, err := NewProvider(WithConfig(Config{DefaultSampler: ProbabilitySampler(0)}))
if err != nil {
@ -386,8 +390,8 @@ func TestAddLinks(t *testing.T) {
k1v1 := key.New("key1").String("value1")
k2v2 := key.New("key2").String("value2")
sc1 := core.SpanContext{TraceID: core.TraceID{High: 0x1, Low: 0x1}, SpanID: 0x3}
sc2 := core.SpanContext{TraceID: core.TraceID{High: 0x1, Low: 0x2}, SpanID: 0x3}
sc1 := core.SpanContext{TraceID: core.TraceID([16]byte{1, 1}), SpanID: 0x3}
sc2 := core.SpanContext{TraceID: core.TraceID([16]byte{1, 1}), SpanID: 0x3}
link1 := apitrace.Link{SpanContext: sc1, Attributes: []core.KeyValue{k1v1}}
link2 := apitrace.Link{SpanContext: sc2, Attributes: []core.KeyValue{k2v2}}
@ -426,8 +430,8 @@ func TestLinks(t *testing.T) {
k2v2 := key.New("key2").String("value2")
k3v3 := key.New("key3").String("value3")
sc1 := core.SpanContext{TraceID: core.TraceID{High: 0x1, Low: 0x1}, SpanID: 0x3}
sc2 := core.SpanContext{TraceID: core.TraceID{High: 0x1, Low: 0x2}, SpanID: 0x3}
sc1 := core.SpanContext{TraceID: core.TraceID([16]byte{1, 1}), SpanID: 0x3}
sc2 := core.SpanContext{TraceID: core.TraceID([16]byte{1, 1}), SpanID: 0x3}
span.Link(sc1, key.New("key1").String("value1"))
span.Link(sc2,
@ -460,12 +464,13 @@ func TestLinks(t *testing.T) {
func TestLinksOverLimit(t *testing.T) {
te := &testExporter{}
cfg := Config{MaxLinksPerSpan: 2}
tp, _ := NewProvider(WithConfig(cfg), WithSyncer(te))
sc1 := core.SpanContext{TraceID: core.TraceID([16]byte{1, 1}), SpanID: 0x3}
sc2 := core.SpanContext{TraceID: core.TraceID([16]byte{1, 1}), SpanID: 0x3}
sc3 := core.SpanContext{TraceID: core.TraceID([16]byte{1, 1}), SpanID: 0x3}
tp, _ := NewProvider(WithConfig(cfg), WithSyncer(te))
span := startSpan(tp, "LinksOverLimit")
sc1 := core.SpanContext{TraceID: core.TraceID{High: 0x1, Low: 0x1}, SpanID: 0x3}
sc2 := core.SpanContext{TraceID: core.TraceID{High: 0x1, Low: 0x2}, SpanID: 0x3}
sc3 := core.SpanContext{TraceID: core.TraceID{High: 0x1, Low: 0x3}, SpanID: 0x3}
k2v2 := key.New("key2").String("value2")
k3v3 := key.New("key3").String("value3")
@ -741,12 +746,14 @@ func TestExecutionTracerTaskEnd(t *testing.T) {
s.executionTracerTaskEnd = executionTracerTaskEnd
spans = append(spans, s) // never sample
tID, _ := core.TraceIDFromHex("0102030405060708090a0b0c0d0e0f")
_, apiSpan = tr.Start(
context.Background(),
"foo",
apitrace.ChildOf(
core.SpanContext{
TraceID: core.TraceID{High: 0x0102030405060708, Low: 0x090a0b0c0d0e0f},
TraceID: tID,
SpanID: uint64(0x0001020304050607),
TraceFlags: 0,
},