diff --git a/trace/trace.go b/trace/trace.go index 3f8977b41..eb3aea7ea 100644 --- a/trace/trace.go +++ b/trace/trace.go @@ -141,6 +141,10 @@ type StartOptions struct { // SpanKind represents the kind of a span. If none is set, // SpanKindUnspecified is used. SpanKind int + + // StartTime is used as the start time of the span if provided. Else it will + // use time.Now(). + StartTime time.Time } // StartOption apply changes to StartOptions. @@ -161,6 +165,13 @@ func WithSampler(sampler Sampler) StartOption { } } +// WithStartTime sets the span start time. +func WithStartTime(t time.Time) StartOption { + return func(o *StartOptions) { + o.StartTime = t + } +} + // StartSpan starts a new child span of the current span in the context. If // there is no span in the context, creates a new trace and span. // @@ -236,7 +247,7 @@ func startSpanInternal(name string, hasParent bool, parent SpanContext, remotePa span.data = &SpanData{ SpanContext: span.spanContext, - StartTime: time.Now(), + StartTime: o.StartTime, SpanKind: o.SpanKind, Name: name, HasRemoteParent: remoteParent, @@ -246,6 +257,9 @@ func startSpanInternal(name string, hasParent bool, parent SpanContext, remotePa span.messageEvents = newEvictedQueue(cfg.MaxMessageEventsPerSpan) span.links = newEvictedQueue(cfg.MaxLinksPerSpan) + if span.data.StartTime.IsZero() { + span.data.StartTime = time.Now() + } if hasParent { span.data.ParentSpanID = parent.SpanID } diff --git a/trace/trace_test.go b/trace/trace_test.go index c2151367f..70df907d1 100644 --- a/trace/trace_test.go +++ b/trace/trace_test.go @@ -230,6 +230,20 @@ func TestStartSpanWithRemoteParent(t *testing.T) { } } +func TestStartSpanWithStartTime(t *testing.T) { + start := time.Now() + + ctx, span := StartSpan(context.Background(), "parent", WithSampler(AlwaysSample()), WithStartTime(start)) + if !span.data.StartTime.Equal(start) { + t.Errorf("expected start time=%s was=%s", start, span.data.StartTime) + } + + _, span = StartSpan(ctx, "child") + if !span.data.StartTime.After(start) { + t.Error("expected child's start time to be after parent's") + } +} + // startSpan returns a context with a new Span that is recording events and will be exported. func startSpan(o StartOptions) *Span { _, span := StartSpanWithRemoteParent(context.Background(), "span0",