Repository: open-telemetry/opentelemetry-go (go)

Issue:
SDK Span creation ignores the initial attributes list
The SDK doesn't sets the attributes that are passed via the `WithAttributes` option to the `Span` creation method.

see: https://github.com/open-telemetry/opentelemetry-go/pull/283/files#diff-ad5e6fa2f2080149c8a5aebd94ea03ddR64

Pull request:
set attributes in tracer.Start()
Fixes #284 cc @rghetia @paivagustavo 

Patch:
diff --git a/plugin/httptrace/clienttrace.go b/plugin/httptrace/clienttrace.go
index b1415c1f..a6a32bec 100644
--- a/plugin/httptrace/clienttrace.go
+++ b/plugin/httptrace/clienttrace.go
@@ -79,10 +79,6 @@ func NewClientTrace(ctx context.Context) *httptrace.ClientTrace {
 
 func (ct *clientTracer) start(hook, spanName string, attrs ...core.KeyValue) {
 	_, sp := ct.tr.Start(ct.Context, spanName, trace.WithAttributes(attrs...), trace.WithSpanKind(trace.SpanKindClient))
-	// TODO(paivagustavo): remove this for loop when `trace.WithAttributes(attrs...)` works.
-	for _, attr := range attrs {
-		sp.SetAttribute(attr)
-	}
 	ct.mtx.Lock()
 	defer ct.mtx.Unlock()
 	if ct.root == nil {
diff --git a/sdk/trace/tracer.go b/sdk/trace/tracer.go
index 03ceaf5d..539cc20c 100644
--- a/sdk/trace/tracer.go
+++ b/sdk/trace/tracer.go
@@ -63,6 +63,7 @@ func (tr *tracer) Start(ctx context.Context, name string, o ...apitrace.SpanOpti
 	for _, l := range opts.Links {
 		span.AddLink(l)
 	}
+	span.SetAttributes(opts.Attributes...)
 
 	span.tracer = tr
 


Test patch:
diff --git a/sdk/trace/trace_test.go b/sdk/trace/trace_test.go
index 916314dc..a66b6cf9 100644
--- a/sdk/trace/trace_test.go
+++ b/sdk/trace/trace_test.go
@@ -287,6 +287,33 @@ func TestStartSpanWithFollowsFrom(t *testing.T) {
 
 // TODO: [rghetia] Equivalent of SpanKind Test.
 
+func TestSetSpanAttributesOnStart(t *testing.T) {
+	te := &testExporter{}
+	tp, _ := NewProvider(WithSyncer(te))
+	span := startSpan(tp, "StartSpanAttribute", apitrace.WithAttributes(key.String("key1", "value1")))
+	got, err := endSpan(te, span)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	want := &export.SpanData{
+		SpanContext: core.SpanContext{
+			TraceID:    tid,
+			TraceFlags: 0x1,
+		},
+		ParentSpanID: sid,
+		Name:         "StartSpanAttribute/span0",
+		Attributes: []core.KeyValue{
+			key.String("key1", "value1"),
+		},
+		SpanKind:        "internal",
+		HasRemoteParent: true,
+	}
+	if diff := cmpDiff(got, want); diff != "" {
+		t.Errorf("SetSpanAttributesOnStart: -got +want %s", diff)
+	}
+}
+
 func TestSetSpanAttributes(t *testing.T) {
 	te := &testExporter{}
 	tp, _ := NewProvider(WithSyncer(te))
@@ -655,20 +682,20 @@ func checkChild(p core.SpanContext, apiSpan apitrace.Span) error {
 
 // startSpan starts a span with a name "span0". See startNamedSpan for
 // details.
-func startSpan(tp *Provider, trName string) apitrace.Span {
-	return startNamedSpan(tp, trName, "span0")
+func startSpan(tp *Provider, trName string, args ...apitrace.SpanOption) apitrace.Span {
+	return startNamedSpan(tp, trName, "span0", args...)
 }
 
 // startNamed Span is a test utility func that starts a span with a
 // passed name and with ChildOf option.  remote span context contains
 // TraceFlags with sampled bit set. This allows the span to be
 // automatically sampled.
-func startNamedSpan(tp *Provider, trName, name string) apitrace.Span {
+func startNamedSpan(tp *Provider, trName, name string, args ...apitrace.SpanOption) apitrace.Span {
+	args = append(args, apitrace.ChildOf(remoteSpanContext()), apitrace.WithRecord())
 	_, span := tp.GetTracer(trName).Start(
 		context.Background(),
 		name,
-		apitrace.ChildOf(remoteSpanContext()),
-		apitrace.WithRecord(),
+		args...,
 	)
 	return span
 }