Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add propagator interface and W3C propagator #85

Merged
merged 28 commits into from
Sep 23, 2019
Merged
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b4cf5f9
add propagation api.
rghetia Aug 9, 2019
067cb3f
add http propagator interface and w3c propagator implementation.
rghetia Aug 9, 2019
fdaf0f0
remove Extract api from trace.
rghetia Aug 9, 2019
7137e7b
remove Extract interface for tracer.
rghetia Aug 9, 2019
d9c6157
fix copyright.
rghetia Aug 9, 2019
1e2f4ea
fix variable names and comments.
rghetia Aug 9, 2019
8215b36
replace INVALID_SPAN_CONTEXT with EmptySpanContext function.
rghetia Aug 13, 2019
ae02d90
move inject/extract out of trace.
rghetia Aug 13, 2019
ddeb734
fix tag.Map.
rghetia Aug 23, 2019
ba6cda4
make carrier as interface instead of http.Request.
rghetia Aug 24, 2019
0c84304
rename structs and update doc comments..
rghetia Aug 26, 2019
034c2fc
add doc.go
rghetia Aug 26, 2019
2b279af
update doc.
rghetia Aug 27, 2019
8d3cced
add noop propagator.
rghetia Aug 27, 2019
a55726d
add new propagation api with Supplier interface.
rghetia Sep 3, 2019
8fe1085
remove old propagator.
rghetia Sep 4, 2019
db8f60b
rename propagator to TextFormatPropagator.
rghetia Sep 4, 2019
9c3ecb6
rename default tracer/span as pass_through tracer/span.
rghetia Sep 5, 2019
e5e1a93
add test for pass through tracer.
rghetia Sep 5, 2019
ecd6ba7
add missing interface to pass through tracer.
rghetia Sep 5, 2019
2a5fc9e
return SpanContext instead of contex.Context from Extract interface.
rghetia Sep 9, 2019
c8a05ec
fix review comments.
rghetia Sep 18, 2019
d759fec
add more test cases for traceContext extraction.
rghetia Sep 19, 2019
418b0f4
remove tidy temporarily from circle-ci target to avoid build failure.
rghetia Sep 20, 2019
f271dfc
allow header ending in dash '-'.
rghetia Sep 20, 2019
4ca80c3
add inject test for non-zero value other than 01 for traceoption
rghetia Sep 23, 2019
064af5e
add AddLink and Link interface to MockSpan
rghetia Sep 23, 2019
ed41e82
fix running go mod tidy on every build.
rghetia Sep 23, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
return SpanContext instead of contex.Context from Extract interface.
- also remove PassThroughTracer
rghetia committed Sep 23, 2019
commit 2a5fc9e2582c569c38120b9e023852cb47b958ae
6 changes: 4 additions & 2 deletions api/propagation/noop_propagator.go
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ package propagation

import (
"context"

"go.opentelemetry.io/api/core"
)

// NoopTextFormatPropagator implements TextFormatPropagator that does nothing.
@@ -28,8 +30,8 @@ func (np NoopTextFormatPropagator) Inject(ctx context.Context, supplier Supplier
}

// Extract does nothing.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And returns empty span context?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

func (np NoopTextFormatPropagator) Extract(ctx context.Context, supplier Supplier) context.Context {
return ctx
func (np NoopTextFormatPropagator) Extract(ctx context.Context, supplier Supplier) core.SpanContext {
return core.EmptySpanContext()
}

// GetAllKeys returns empty list of strings.
10 changes: 6 additions & 4 deletions api/propagation/propagator.go
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ package propagation

import (
"context"

"go.opentelemetry.io/api/core"
)

// TextFormatPropagator is an interface that specifies methods to inject and extract SpanContext
@@ -28,10 +30,10 @@ type TextFormatPropagator interface {
// associated with the supplier.
Inject(ctx context.Context, supplier Supplier)

// Extract method retrieves SpanContext using supplier from the associated carrier with
// the supplier. It decodes the SpanContext and it creates remote span using registered
// tracer.
Extract(ctx context.Context, supplier Supplier) context.Context
// Extract method retrieves encoded SpanContext using supplier from the associated carrier.
// It decodes the SpanContext and returns it. If no SpanContext was retrieved OR
// if the retrieved SpanContext is invalid then an empty SpanContext is returned.
Extract(ctx context.Context, supplier Supplier) core.SpanContext

// GetAllKeys returns all the keys that this propagator injects/extracts into/from a
// carrier. The use cases for this are
16 changes: 4 additions & 12 deletions api/trace/api.go
Original file line number Diff line number Diff line change
@@ -105,11 +105,10 @@ type SpanOption func(*SpanOptions)
// SpanOptions provides options to set properties of span at the time of starting
// a new span.
type SpanOptions struct {
Attributes []core.KeyValue
StartTime time.Time
Reference Reference
RecordEvent bool
RemoteSpanContext core.SpanContext
Attributes []core.KeyValue
StartTime time.Time
Reference Reference
RecordEvent bool
}

// Reference is used to establish relationship between newly created span and the
@@ -174,13 +173,6 @@ func WithRecordEvents() SpanOption {
}
}

// CopyOfRemote allows to create an inactive span mirroring remote span.
func CopyOfRemote(sc core.SpanContext) SpanOption {
return func(o *SpanOptions) {
o.RemoteSpanContext = sc
}
}

// ChildOf. TODO: do we need this?.
func ChildOf(sc core.SpanContext) SpanOption {
return func(o *SpanOptions) {
62 changes: 0 additions & 62 deletions api/trace/pass_through_tracer.go

This file was deleted.

57 changes: 0 additions & 57 deletions api/trace/pass_through_tracer_test.go

This file was deleted.

5 changes: 3 additions & 2 deletions example/http/server/server.go
Original file line number Diff line number Diff line change
@@ -35,16 +35,17 @@ var (

func main() {
helloHandler := func(w http.ResponseWriter, req *http.Request) {
attrs, tags, ctx := httptrace.Extract(req.Context(), req)
attrs, tags, spanCtx := httptrace.Extract(req.Context(), req)

req = req.WithContext(tag.WithMap(ctx, tag.NewMap(tag.MapUpdate{
req = req.WithContext(tag.WithMap(req.Context(), tag.NewMap(tag.MapUpdate{
MultiKV: tags,
})))

ctx, span := tracer.Start(
req.Context(),
"hello",
trace.WithAttributes(attrs...),
trace.ChildOf(spanCtx),
)
defer span.Finish()

40 changes: 21 additions & 19 deletions api/trace/pass_through_span.go → internal/trace/mock_span.go
Original file line number Diff line number Diff line change
@@ -21,64 +21,66 @@ import (

"go.opentelemetry.io/api/core"
"go.opentelemetry.io/api/tag"
apitrace "go.opentelemetry.io/api/trace"
)

type PassThroughSpan struct {
sc core.SpanContext
type MockSpan struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing doc string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.

sc core.SpanContext
tracer apitrace.Tracer
}

var _ Span = (*PassThroughSpan)(nil)
var _ apitrace.Span = (*MockSpan)(nil)

// SpancContext returns an invalid span context.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is false. Also s/SpancContext/SpanContext/.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

func (ds *PassThroughSpan) SpanContext() core.SpanContext {
if ds == nil {
func (ms *MockSpan) SpanContext() core.SpanContext {
if ms == nil {
core.EmptySpanContext()
}
return ds.sc
return ms.sc
}

// IsRecordingEvents always returns false for PassThroughSpan.
func (ds *PassThroughSpan) IsRecordingEvents() bool {
// IsRecordingEvents always returns false for MockSpan.
func (ms *MockSpan) IsRecordingEvents() bool {
return false
}

// SetStatus does nothing.
func (ds *PassThroughSpan) SetStatus(status codes.Code) {
func (ms *MockSpan) SetStatus(status codes.Code) {
}

// SetError does nothing.
func (ds *PassThroughSpan) SetError(v bool) {
func (ms *MockSpan) SetError(v bool) {
}

// SetAttribute does nothing.
func (ds *PassThroughSpan) SetAttribute(attribute core.KeyValue) {
func (ms *MockSpan) SetAttribute(attribute core.KeyValue) {
}

// SetAttributes does nothing.
func (ds *PassThroughSpan) SetAttributes(attributes ...core.KeyValue) {
func (ms *MockSpan) SetAttributes(attributes ...core.KeyValue) {
}

// ModifyAttribute does nothing.
func (ds *PassThroughSpan) ModifyAttribute(mutator tag.Mutator) {
func (ms *MockSpan) ModifyAttribute(mutator tag.Mutator) {
}

// ModifyAttributes does nothing.
func (ds *PassThroughSpan) ModifyAttributes(mutators ...tag.Mutator) {
func (ms *MockSpan) ModifyAttributes(mutators ...tag.Mutator) {
}

// Finish does nothing.
func (ds *PassThroughSpan) Finish(options ...FinishOption) {
func (ms *MockSpan) Finish(options ...apitrace.FinishOption) {
}

// SetName does nothing.
func (ds *PassThroughSpan) SetName(name string) {
func (ms *MockSpan) SetName(name string) {
}

// Tracer returns noop implementation of Tracer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should say that it returns a mock tracer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

func (ds *PassThroughSpan) Tracer() Tracer {
return PassThroughTracer{}
func (ms *MockSpan) Tracer() apitrace.Tracer {
return ms.tracer
}

// AddEvent does nothing.
func (ds *PassThroughSpan) AddEvent(ctx context.Context, msg string, attrs ...core.KeyValue) {
func (ms *MockSpan) AddEvent(ctx context.Context, msg string, attrs ...core.KeyValue) {
}
91 changes: 91 additions & 0 deletions internal/trace/mock_tracer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright 2019, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package trace

import (
"context"
"math/rand"
"sync/atomic"

"go.opentelemetry.io/api/core"
apitrace "go.opentelemetry.io/api/trace"
)

// MockTracer is a simple tracer used for testing purpose only.
// It only supports ChildOf option. SpanId is atomically increased every time a
// new span is created.
type MockTracer struct {
// Sampled specifies if the new span should be sampled or not.
Sampled bool

// StartSpanId is used to initialize spanId. It is incremented by one
// every time a new span is created.
StartSpanId *uint64
}

var _ apitrace.Tracer = (*MockTracer)(nil)

// WithResources does nothing and returns noop implementation of Tracer.
func (mt *MockTracer) WithResources(attributes ...core.KeyValue) apitrace.Tracer {
return mt
}

// WithComponent does nothing and returns noop implementation of Tracer.
func (mt *MockTracer) WithComponent(name string) apitrace.Tracer {
return mt
}

// WithService does nothing and returns noop implementation of Tracer.
func (mt *MockTracer) WithService(name string) apitrace.Tracer {
return mt
}

// WithSpan wraps around execution of func with noop span.
func (mt *MockTracer) WithSpan(ctx context.Context, name string, body func(context.Context) error) error {
return body(ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't that do span := mt.Start(ctx, name) and defer span.Finish() before using the body callback?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If needed for testing then yes. Otherwise it should be a noop.

}

// Start starts a MockSpan. It creates a new Span based on Reference SpanContext option.
// TracdID is used from Reference Span Context and SpanID is assigned.
// If Reference SpanContext option is not specified then random TraceID is used.
// No other options are supported.
func (mt *MockTracer) Start(ctx context.Context, name string, o ...apitrace.SpanOption) (context.Context, apitrace.Span) {
var opts apitrace.SpanOptions
for _, op := range o {
op(&opts)
}
var span *MockSpan
var sc core.SpanContext
if !opts.Reference.SpanContext.IsValid() {
sc = core.SpanContext{
TraceID: core.TraceID{
High: rand.Uint64(),
Low: rand.Uint64(),
},
}
if mt.Sampled {
sc.TraceOptions = core.TraceOptionSampled
}
} else {
sc = opts.Reference.SpanContext
}
sc.SpanID = atomic.AddUint64(mt.StartSpanId, 1)
span = &MockSpan{
sc: sc,
tracer: mt,
}

return apitrace.SetCurrentSpan(ctx, span), span
}
6 changes: 3 additions & 3 deletions plugin/httptrace/httptrace.go
Original file line number Diff line number Diff line change
@@ -41,15 +41,15 @@ var (
)

// Returns the Attributes, Context Tags, and SpanContext that were encoded by Inject.
func Extract(ctx context.Context, req *http.Request) ([]core.KeyValue, []core.KeyValue, context.Context) {
ctx = propagator.Extract(ctx, req.Header)
func Extract(ctx context.Context, req *http.Request) ([]core.KeyValue, []core.KeyValue, core.SpanContext) {
sc := propagator.Extract(ctx, req.Header)

attrs := []core.KeyValue{
URLKey.String(req.URL.String()),
// Etc.
}

return attrs, nil, ctx
return attrs, nil, sc
}

func Inject(ctx context.Context, req *http.Request) {
31 changes: 15 additions & 16 deletions propagation/http_trace_context_propagator.go
Original file line number Diff line number Diff line change
@@ -50,72 +50,71 @@ func (hp httpTraceContextPropagator) Inject(ctx context.Context, supplier apipro
}
}

func (hp httpTraceContextPropagator) Extract(ctx context.Context, supplier apipropagation.Supplier) context.Context {
func (hp httpTraceContextPropagator) Extract(ctx context.Context, supplier apipropagation.Supplier) core.SpanContext {
h := supplier.Get(traceparentHeader)
if h == "" {
return ctx
return core.EmptySpanContext()
}

sections := strings.Split(h, "-")
if len(sections) < 4 {
return ctx
return core.EmptySpanContext()
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we really check if all the characters in at least first four sections are either digits or lowercase letters from a to f? That's what the W3C trace context spec says in several places, like

HEXDIGLC = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ; lowercase hex character

or

Vendors MUST ignore the traceparent when the parent-id is invalid (for example, if it contains non-lowercase hex characters).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the check.

if len(sections[0]) != 2 {
return ctx
return core.EmptySpanContext()
}
ver, err := hex.DecodeString(sections[0])
if err != nil {
return ctx
return core.EmptySpanContext()
}
version := int(ver[0])
if version > maxVersion {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this check be version != supportedVersion for now? We support only one version at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the expectation here? will version 1 be compatible with version 0? If so then it should just check for invalid value of the version. If not then it should check for specific version.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through the spec and noticed this in 3.2.4 Versioning of traceparent:

This specification is opinionated about future versions of trace context. The current version of this specification assumes that future versions of the traceparent header will be additive to the current one.

So this needs to stay as is.

return ctx
return core.EmptySpanContext()
}

if version == 0 && len(sections) != 4 {
return ctx
return core.EmptySpanContext()
}

if len(sections[1]) != 32 {
return ctx
return core.EmptySpanContext()
}

result, err := strconv.ParseUint(sections[1][0:16], 16, 64)
if err != nil {
return ctx
return core.EmptySpanContext()
}
var sc core.SpanContext

sc.TraceID.High = result

result, err = strconv.ParseUint(sections[1][16:32], 16, 64)
if err != nil {
return ctx
return core.EmptySpanContext()
}
sc.TraceID.Low = result

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a check if sc.TraceID.Low == 0 && sc.TraceID.High == 0 { return core.EmptySpanContext() }? See first paragraph of 3.2.2.3 trace-id:

All bytes as zero (00000000000000000000000000000000) is considered an invalid value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind that - I see that we basically check it at the end of the function.

if len(sections[2]) != 16 {
return ctx
return core.EmptySpanContext()
}
result, err = strconv.ParseUint(sections[2][0:], 16, 64)
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be err != nil || result == 0? See first paragraph in 3.2.2.3.1 parent-id:

All bytes as zero (0000000000000000) is considered an invalid value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind that, I see that we check it at the end of the function.

return ctx
return core.EmptySpanContext()
}
sc.SpanID = result

opts, err := hex.DecodeString(sections[3])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check here if len(sections[3]) == 2. This is also in 3.2.4 Versioning of traceparent:

Parse the sampled bit of flags (2 characters from the third dash). Vendors MUST check that the 2 characters are either the end of the string or a dash.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I wonder if we should have a check like if version == 0 && opts[0] > 2 { return core.EmptySpanContext() } as the only specified flag currently is a "sampled" flag for which the first bit is reserved and all other bits should be zero. See 3.2.2.3.3 Other Flags:

The behavior of other flags, such as (00000100) is not defined and is reserved for future use. Vendors MUST set those to zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

if err != nil || len(opts) < 1 {
return ctx
return core.EmptySpanContext()
}
sc.TraceOptions = opts[0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be sc.TraceOptions = opts[0] &^ core.TraceOptionUnused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


if !sc.IsValid() {
return ctx
return core.EmptySpanContext()
}

ctx, _ = trace.GlobalTracer().Start(ctx, "remote", trace.CopyOfRemote(sc))
return ctx
return sc
}

func (hp httpTraceContextPropagator) GetAllKeys() []string {
21 changes: 13 additions & 8 deletions propagation/http_trace_context_propagator_test.go
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ import (
"github.com/google/go-cmp/cmp"

"go.opentelemetry.io/api/core"
mocktrace "go.opentelemetry.io/internal/trace"
"go.opentelemetry.io/propagation"
)

@@ -33,7 +34,7 @@ var (
)

func TestExtractTraceContextFromHTTPReq(t *testing.T) {
trace.SetGlobalTracer(trace.PassThroughTracer{})
trace.SetGlobalTracer(&mocktrace.MockTracer{})
propagator := propagation.HttpTraceContextPropagator()
tests := []struct {
name string
@@ -81,9 +82,7 @@ func TestExtractTraceContextFromHTTPReq(t *testing.T) {
req.Header.Set("traceparent", tt.header)

ctx := context.Background()
ctx = propagator.Extract(ctx, req.Header)
span := trace.CurrentSpan(ctx)
gotSc := span.SpanContext()
gotSc := propagator.Extract(ctx, req.Header)
if diff := cmp.Diff(gotSc, tt.wantSc); diff != "" {
t.Errorf("Extract Tracecontext: %s: -got +want %s", tt.name, diff)
}
@@ -92,7 +91,11 @@ func TestExtractTraceContextFromHTTPReq(t *testing.T) {
}

func TestInjectTraceContextToHTTPReq(t *testing.T) {
trace.SetGlobalTracer(trace.PassThroughTracer{})
var id uint64
trace.SetGlobalTracer(&mocktrace.MockTracer{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a point in installing the global tracer in the test? The test does not use any API that calls into the global tracer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had trace.GlobalTracer().Start() but I don't need that as I can use mockTracer.Start().
Removed installing global tracer.

Sampled: false,
StartSpanId: &id,
})
propagator := propagation.HttpTraceContextPropagator()
tests := []struct {
name string
@@ -106,15 +109,15 @@ func TestInjectTraceContextToHTTPReq(t *testing.T) {
SpanID: spanID,
TraceOptions: core.TraceOptionSampled,
},
wantHeader: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
wantHeader: "00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000000001-01",
},
{
name: "valid spancontext, not sampled",
sc: core.SpanContext{
TraceID: traceID,
SpanID: spanID,
},
wantHeader: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
wantHeader: "00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000000002-00",
},
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there should be a test case with a valid span context having options like 0xff, so the expected header should have 01 as options, not ff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with version '0' I added test to check that option should not be >2. For future version I added other values of option but expected value to be 01 or 00.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't see those tests anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for version 0, anything other than 01 should fail

		{
			name:   "trace-flag unused bits set",
			header: "00-ab000000000000000000000000000000-cd00000000000000-09",
		},

For future version accept 01 and 00

		{
			name:   "future options with sampled bit set",
			header: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-09",
			wantSc: core.SpanContext{
				TraceID:      traceID,
				SpanID:       spanID,
				TraceOptions: core.TraceOptionSampled,
			},
		},
		{
			name:   "future options with sampled bit cleared",
			header: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-08",
			wantSc: core.SpanContext{
				TraceID: traceID,
				SpanID:  spanID,
			},
		},

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I meant the test for the inject part, where as input you have a span context like:

core.SpanContext{
	TraceID:      core.TraceID{High: 0x4bf92f3577b34da6, Low: 0xa3ce929d0e0e4736},
	SpanID:       uint64(0x00f067aa0ba902b7),
	TraceOptions: 0xff,
}

and the expected generated "traceparent" HTTP header (for now) would be 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01 (not ff at the end).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.

name: "invalid spancontext",
@@ -126,7 +129,9 @@ func TestInjectTraceContextToHTTPReq(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
req, _ := http.NewRequest("GET", "http://example.com", nil)
ctx := context.Background()
ctx, _ = trace.GlobalTracer().Start(ctx, "inject", trace.CopyOfRemote(tt.sc))
if tt.sc.IsValid() {
ctx, _ = trace.GlobalTracer().Start(ctx, "inject", trace.ChildOf(tt.sc))
}
propagator.Inject(ctx, req.Header)

gotHeader := req.Header.Get("traceparent")
10 changes: 0 additions & 10 deletions sdk/trace/span.go
Original file line number Diff line number Diff line change
@@ -38,9 +38,6 @@ type span struct {
mu sync.Mutex // protects the contents of *data (but not the pointer value.)
spanContext core.SpanContext

// remote is true if span was created to mirror a remote span.
remote bool

// lruAttributes are capped at configured limit. When the capacity is reached an oldest entry
// is removed to create room for a new entry.
lruAttributes *lruMap
@@ -300,13 +297,6 @@ func (s *span) addChild() {
func startSpanInternal(name string, parent core.SpanContext, remoteParent bool, o apitrace.SpanOptions) *span {
var noParent bool
span := &span{}

if o.RemoteSpanContext.IsValid() {
span.remote = true
span.spanContext = o.RemoteSpanContext
return span
}

span.spanContext = parent

cfg := config.Load().(*Config)