diff --git a/context.go b/context.go index c73a2bd..5b6f55b 100644 --- a/context.go +++ b/context.go @@ -25,7 +25,7 @@ type spanContext struct { // Shared trace context traceContext *traceContext - spanID uint32 + spanID uint64 } func newSpanContext(ctx context.Context, tracingCtx *traceContext) *spanContext { @@ -106,7 +106,7 @@ func (tc *traceContext) pushSpan(span *Span) (ok bool) { return true } -func (tc *traceContext) collect() (spans []Span, attachment interface{}) { +func (tc *traceContext) collect() (trace Trace, attachment interface{}) { tc.mu.Lock() defer tc.mu.Unlock() @@ -115,7 +115,8 @@ func (tc *traceContext) collect() (spans []Span, attachment interface{}) { } tc.collected = true - spans = tc.collectedSpans + trace.Spans = tc.collectedSpans + trace.TraceID = tc.traceID attachment = tc.attachment tc.collectedSpans = nil diff --git a/datadog/datadog.go b/datadog/datadog.go index af7a80c..8cd4808 100644 --- a/datadog/datadog.go +++ b/datadog/datadog.go @@ -62,19 +62,12 @@ func MessagePackEncode(buf io.Writer, spanList SpanList) error { func MiniSpansToDatadogSpanList( serviceName string, - traceID uint64, - spanIDPrefix uint32, - rootParentSpanID uint64, - spans []minitrace.Span, + trace minitrace.Trace, ) SpanList { + spans := trace.Spans ddSpans := make([]*Span, 0, len(spans)) for _, span := range spans { - parentID := uint64(spanIDPrefix)<<32 | uint64(span.ParentID) - if span.ParentID == 0 { - parentID = rootParentSpanID - } - meta := make(map[string]string) for _, property := range span.Properties { meta[property.Key] = property.Value @@ -85,9 +78,9 @@ func MiniSpansToDatadogSpanList( Start: int64(span.BeginUnixTimeNs), Duration: int64(span.DurationNs), Meta: meta, - SpanID: uint64(spanIDPrefix)<<32 | uint64(span.ID), - TraceID: traceID, - ParentID: parentID, + SpanID: span.ID, + TraceID: trace.TraceID, + ParentID: span.ParentID, } ddSpans = append(ddSpans, ddSpan) } diff --git a/datadog/datadog_test.go b/datadog/datadog_test.go index 9b4fa6f..5e8ddd6 100644 --- a/datadog/datadog_test.go +++ b/datadog/datadog_test.go @@ -26,7 +26,7 @@ import ( ) func TestDatadog(t *testing.T) { - ctx, handle := minitrace.StartRootSpan(context.Background(), "root", 10010, nil) + ctx, handle := minitrace.StartRootSpan(context.Background(), "root", 10010, 0,nil) handle.AddProperty("event1", "root") handle.AddProperty("event2", "root") var wg sync.WaitGroup @@ -58,12 +58,12 @@ func TestDatadog(t *testing.T) { } wg.Wait() - spans, _ := handle.Collect() + trace, _ := handle.Collect() rand.Seed(time.Now().UnixNano()) buf := bytes.NewBuffer([]byte{}) - spanList := MiniSpansToDatadogSpanList("datadog-test", rand.Uint64(), 0, 0, spans) + spanList := MiniSpansToDatadogSpanList("datadog-test", trace) if err := MessagePackEncode(buf, spanList); err == nil { _ = Send(buf, "127.0.0.1:8126") } else { diff --git a/jaeger/jaeger.go b/jaeger/jaeger.go index 8ed60b8..9b32509 100644 --- a/jaeger/jaeger.go +++ b/jaeger/jaeger.go @@ -33,19 +33,12 @@ func Send(buf []byte, agent string) error { func MiniSpansToJaegerTrace( serviceName string, - traceID int64, - spanIDPrefix uint32, - rootParentSpanID int64, - spans []minitrace.Span, + trace minitrace.Trace, ) Trace { + spans := trace.Spans retSpans := make([]Span, 0, len(spans)) for _, span := range spans { - parentID := int64(spanIDPrefix)<<32 | int64(span.ParentID) - if span.ParentID == 0 { - parentID = rootParentSpanID - } - var tags []struct { Key string Value string @@ -62,8 +55,8 @@ func MiniSpansToJaegerTrace( } retSpans = append(retSpans, Span{ - SpanID: int64(spanIDPrefix)<<32 | int64(span.ID), - ParentID: parentID, + SpanID: int64(span.ID), + ParentID: int64(span.ParentID), StartUnixTimeUs: int64(span.BeginUnixTimeNs / 1000), DurationUs: int64(span.DurationNs / 1000), OperationName: span.Event, @@ -72,7 +65,7 @@ func MiniSpansToJaegerTrace( } return Trace{ - TraceIDLow: traceID, + TraceIDLow: int64(trace.TraceID), ServiceName: serviceName, Spans: retSpans, } diff --git a/jaeger/jaeger_test.go b/jaeger/jaeger_test.go index f73191b..09db91a 100644 --- a/jaeger/jaeger_test.go +++ b/jaeger/jaeger_test.go @@ -26,7 +26,7 @@ import ( ) func TestJaeger(t *testing.T) { - ctx, handle := minitrace.StartRootSpan(context.Background(), "root", 10010, nil) + ctx, handle := minitrace.StartRootSpan(context.Background(), "root", 10010, 0, nil) handle.AddProperty("event1", "root") handle.AddProperty("event2", "root") var wg sync.WaitGroup @@ -58,12 +58,12 @@ func TestJaeger(t *testing.T) { } wg.Wait() - spans, _ := handle.Collect() + mtrace, _ := handle.Collect() buf := bytes.NewBuffer(make([]uint8, 0, 4096)) rand.Seed(time.Now().UnixNano()) - trace := MiniSpansToJaegerTrace("minitrace-test", rand.Int63(), 0, 0, spans) + trace := MiniSpansToJaegerTrace("minitrace-test", mtrace) if err := ThriftCompactEncode(buf, trace); err == nil { _ = Send(buf.Bytes(), "127.0.0.1:6831") } diff --git a/span.go b/span.go index 7cefa40..2b31125 100644 --- a/span.go +++ b/span.go @@ -14,15 +14,15 @@ package minitrace type Span struct { - ID uint32 - ParentID uint32 // 0 means Root + ID uint64 + ParentID uint64 // 0 means Root BeginUnixTimeNs uint64 DurationNs uint64 Event string Properties []Property } -func (s *Span) beginWith(parentID uint32, event string) { +func (s *Span) beginWith(parentID uint64, event string) { s.ID = nextID() s.ParentID = parentID diff --git a/trace.go b/trace.go index b4a0691..5fb0aa3 100644 --- a/trace.go +++ b/trace.go @@ -15,25 +15,23 @@ package minitrace import ( "context" - "sync/atomic" + "math/rand" ) -// The id 0 have a special semantic. So id should begin from 1. -var idGen uint32 = 1 +type Trace struct { + TraceID uint64 + Spans []Span +} -// Returns incremental uint32 unique ID. -func nextID() uint32 { - return atomic.AddUint32(&idGen, 1) +// Returns random uint64 ID. +func nextID() uint64 { + return rand.Uint64() } -func StartRootSpan(ctx context.Context, event string, traceID uint64, attachment interface{}) (context.Context, TraceHandle) { +func StartRootSpan(ctx context.Context, event string, traceID uint64, parentSpanID uint64, attachment interface{}) (context.Context, TraceHandle) { traceCtx := newTraceContext(traceID, attachment) spanCtx := newSpanContext(ctx, traceCtx) - - // Root span doesn't have a parent. Its parent span id is set to 0. - const ParentID = 0 - spanHandle := newSpanHandle(spanCtx, ParentID, event) - + spanHandle := newSpanHandle(spanCtx, parentSpanID, event) return spanCtx, TraceHandle{spanHandle} } @@ -66,7 +64,7 @@ func StartSpan(ctx context.Context, event string) (handle SpanHandle) { return newSpanHandle(spanCtx, parentSpanCtx.spanID, event) } -func CurrentID(ctx context.Context) (spanID uint32, traceID uint64, ok bool) { +func CurrentID(ctx context.Context) (spanID uint64, traceID uint64, ok bool) { if s, ok := ctx.Value(activeTraceKey).(*spanContext); ok { return s.spanID, s.traceContext.traceID, ok } @@ -88,7 +86,7 @@ type SpanHandle struct { finished bool } -func newSpanHandle(spanCtx *spanContext, parentSpanID uint32, event string) (sh SpanHandle) { +func newSpanHandle(spanCtx *spanContext, parentSpanID uint64, event string) (sh SpanHandle) { sh.spanContext = spanCtx sh.span.beginWith(parentSpanID, event) sh.finished = false @@ -129,7 +127,7 @@ type TraceHandle struct { SpanHandle } -func (th *TraceHandle) Collect() (spans []Span, attachment interface{}) { +func (th *TraceHandle) Collect() (trace Trace, attachment interface{}) { th.SpanHandle.Finish() return th.spanContext.traceContext.collect() } diff --git a/trace_test.go b/trace_test.go index d9600f7..4f00bcf 100644 --- a/trace_test.go +++ b/trace_test.go @@ -29,16 +29,16 @@ func BenchmarkMiniTrace(b *testing.B) { for i := 100; i < 10001; i *= 10 { b.Run(fmt.Sprintf(" %d", i), func(b *testing.B) { for j := 0; j < b.N; j++ { - ctx, handle := StartRootSpan(context.Background(), "root", 10086, nil) + ctx, handle := StartRootSpan(context.Background(), "root", 10086, 0, nil) for k := 1; k < i; k++ { _, handle := StartSpanWithContext(ctx, strconv.Itoa(k)) handle.Finish() } - spans, _ := handle.Collect() - if i != len(spans) { - b.Fatalf("expected length %d, got %d", i, len(spans)) + trace, _ := handle.Collect() + if i != len(trace.Spans) { + b.Fatalf("expected length %d, got %d", i, len(trace.Spans)) } } }) @@ -82,7 +82,7 @@ func BenchmarkAppdashTrace(b *testing.B) { func TestMiniTrace(t *testing.T) { var traceID uint64 = 9527 - ctx, handle := StartRootSpan(context.Background(), "root", traceID, nil) + ctx, handle := StartRootSpan(context.Background(), "root", traceID, 0, nil) var wg sync.WaitGroup if spanID1, traceID1, ok := CurrentID(ctx); ok { @@ -130,8 +130,8 @@ func TestMiniTrace(t *testing.T) { } wg.Wait() - spans, _ := handle.Collect() - if len(spans) != 29 { - t.Fatalf("length of spanSets expected %d, but got %d", 25, len(spans)) + trace, _ := handle.Collect() + if len(trace.Spans) != 29 { + t.Fatalf("length of spanSets expected %d, but got %d", 29, len(trace.Spans)) } }