Repository: open-telemetry/opentelemetry-go
Pull request #1874 (2021-05-02 21:10:01)

Add Status type to SDK
Instead of having two methods to return related information about the span status, use this new type to encapsulate the Span status similar to how the Event type encapsulates a Span event and the Link type encapsulates a span link.

Additionally, change the term status message to status description to match [the language in the specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.2.0/specification/trace/api.md#set-status).

Part of the clean up included in #1873 for #1380.

codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#1874](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (5327f76) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go/commit/f40cad5ee20175a946763ef79a32741069e4492a?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (f40cad5) will **decrease** coverage by `0.0%`.
> The diff coverage is `100.0%`.

[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874/graphs/tree.svg?width=650&height=150&src=pr&token=8efTmh4kvf&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #1874     +/-   ##
=======================================
- Coverage   78.7%   78.7%   -0.1%     
=======================================
  Files        137     137             
  Lines       7343    7339      -4     
=======================================
- Hits        5786    5782      -4     
  Misses      1316    1316             
  Partials     241     241             
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [trace/trace.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-dHJhY2UvdHJhY2UuZ28=) | `86.7% <ø> (ø)` | |
| [exporters/otlp/internal/otlptest/data.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-ZXhwb3J0ZXJzL290bHAvaW50ZXJuYWwvb3RscHRlc3QvZGF0YS5nbw==) | `87.7% <100.0%> (-0.3%)` | :arrow_down: |
| [exporters/otlp/internal/transform/span.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-ZXhwb3J0ZXJzL290bHAvaW50ZXJuYWwvdHJhbnNmb3JtL3NwYW4uZ28=) | `98.1% <100.0%> (ø)` | |
| [exporters/trace/jaeger/jaeger.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-ZXhwb3J0ZXJzL3RyYWNlL2phZWdlci9qYWVnZXIuZ28=) | `92.8% <100.0%> (ø)` | |
| [exporters/trace/zipkin/model.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-ZXhwb3J0ZXJzL3RyYWNlL3ppcGtpbi9tb2RlbC5nbw==) | `99.1% <100.0%> (ø)` | |
| [sdk/trace/span.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1874/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-c2RrL3RyYWNlL3NwYW4uZ28=) | `93.9% <100.0%> (-0.1%)` | :arrow_down: |


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d81a9cc..14aae8ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
       | 10 | Out of Range |
       | 14 | Unavailable |
       | 15 | Data Loss |
+- The `Status` type was added to the `go.opentelemetry.io/otel/sdk/trace` package to represent the status of a span. (#1874)
 
 ### Changed
 
@@ -31,6 +32,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
 - BatchSpanProcessor now report export failures when calling `ForceFlush()` method. (#1860)
 - `Set.Encoded(Encoder)` no longer caches the result of an encoding. (#1855)
 - Renamed `CloudZoneKey` to `CloudAvailabilityZoneKey` in Resource semantic conventions according to spec. (#1871)
+- The `StatusCode` and `StatusMessage` methods of the `ReadOnlySpan` interface and the `Span` produced by the `go.opentelemetry.io/otel/sdk/trace` package have been replaced with a single `Status` method.
+  This method returns the status of a span using the new `Status` type. (#1874)
 
 ### Deprecated
 
diff --git a/exporters/otlp/internal/transform/span.go b/exporters/otlp/internal/transform/span.go
index 342f349a..19801791 100644
--- a/exporters/otlp/internal/transform/span.go
+++ b/exporters/otlp/internal/transform/span.go
@@ -108,7 +108,7 @@ func span(sd *tracesdk.SpanSnapshot) *tracepb.Span {
 		TraceId:                tid[:],
 		SpanId:                 sid[:],
 		TraceState:             sd.SpanContext.TraceState().String(),
-		Status:                 status(sd.StatusCode, sd.StatusMessage),
+		Status:                 status(sd.Status.Code, sd.Status.Description),
 		StartTimeUnixNano:      uint64(sd.StartTime.UnixNano()),
 		EndTimeUnixNano:        uint64(sd.EndTime.UnixNano()),
 		Links:                  links(sd.Links),
diff --git a/exporters/trace/jaeger/jaeger.go b/exporters/trace/jaeger/jaeger.go
index d3f5f97f..c2926b61 100644
--- a/exporters/trace/jaeger/jaeger.go
+++ b/exporters/trace/jaeger/jaeger.go
@@ -170,13 +170,13 @@ func spanSnapshotToThrift(ss *sdktrace.SpanSnapshot) *gen.Span {
 		)
 	}
 
-	if ss.StatusCode != codes.Unset {
-		tags = append(tags, getInt64Tag(keyStatusCode, int64(ss.StatusCode)))
-		if ss.StatusMessage != "" {
-			tags = append(tags, getStringTag(keyStatusMessage, ss.StatusMessage))
+	if ss.Status.Code != codes.Unset {
+		tags = append(tags, getInt64Tag(keyStatusCode, int64(ss.Status.Code)))
+		if ss.Status.Description != "" {
+			tags = append(tags, getStringTag(keyStatusMessage, ss.Status.Description))
 		}
 
-		if ss.StatusCode == codes.Error {
+		if ss.Status.Code == codes.Error {
 			tags = append(tags, getBoolTag(keyError, true))
 		}
 	}
diff --git a/exporters/trace/zipkin/model.go b/exporters/trace/zipkin/model.go
index 74a3ffc7..51a8bc75 100644
--- a/exporters/trace/zipkin/model.go
+++ b/exporters/trace/zipkin/model.go
@@ -187,12 +187,12 @@ func toZipkinTags(data *tracesdk.SpanSnapshot) map[string]string {
 		}
 	}
 
-	if data.StatusCode != codes.Unset {
-		m["otel.status_code"] = data.StatusCode.String()
+	if data.Status.Code != codes.Unset {
+		m["otel.status_code"] = data.Status.Code.String()
 	}
 
-	if data.StatusCode == codes.Error {
-		m["error"] = data.StatusMessage
+	if data.Status.Code == codes.Error {
+		m["error"] = data.Status.Description
 	} else {
 		delete(m, "error")
 	}
diff --git a/sdk/trace/span.go b/sdk/trace/span.go
index b7f5296c..c69964da 100644
--- a/sdk/trace/span.go
+++ b/sdk/trace/span.go
@@ -46,8 +46,7 @@ type ReadOnlySpan interface {
 	Attributes() []attribute.KeyValue
 	Links() []trace.Link
 	Events() []Event
-	StatusCode() codes.Code
-	StatusMessage() string
+	Status() Status
 	Tracer() trace.Tracer
 	IsRecording() bool
 	InstrumentationLibrary() instrumentation.Library
@@ -92,11 +91,8 @@ type span struct {
 	// value of time.Time until the span is ended.
 	endTime time.Time
 
-	// statusCode represents the status of this span as a codes.Code value.
-	statusCode codes.Code
-
-	// statusMessage represents the status of this span as a string.
-	statusMessage string
+	// status is the status of this span.
+	status Status
 
 	// childSpanCount holds the number of child spans created for this span.
 	childSpanCount int
@@ -154,19 +150,22 @@ func (s *span) IsRecording() bool {
 	return !s.startTime.IsZero() && s.endTime.IsZero()
 }
 
-// SetStatus sets the status of this span in the form of a code and a
-// message. This overrides the existing value of this span's status if one
-// exists. Message will be set only if status is error. If this span is not being
-// recorded than this method does nothing.
-func (s *span) SetStatus(code codes.Code, msg string) {
+// SetStatus sets the status of the Span in the form of a code and a
+// description, overriding previous values set. The description is only
+// included in the set status when the code is for an error. If this span is
+// not being recorded than this method does nothing.
+func (s *span) SetStatus(code codes.Code, description string) {
 	if !s.IsRecording() {
 		return
 	}
-	s.mu.Lock()
-	s.statusCode = code
+
+	status := Status{Code: code}
 	if code == codes.Error {
-		s.statusMessage = msg
+		status.Description = description
 	}
+
+	s.mu.Lock()
+	s.status = status
 	s.mu.Unlock()
 }
 
@@ -381,18 +380,11 @@ func (s *span) Events() []Event {
 	return s.interfaceArrayToMessageEventArray()
 }
 
-// StatusCode returns the status code of this span.
-func (s *span) StatusCode() codes.Code {
+// Status returns the status of this span.
+func (s *span) Status() Status {
 	s.mu.Lock()
 	defer s.mu.Unlock()
-	return s.statusCode
-}
-
-// StatusMessage returns the status message of this span.
-func (s *span) StatusMessage() string {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	return s.statusMessage
+	return s.status
 }
 
 // InstrumentationLibrary returns the instrumentation.Library associated with
@@ -443,8 +435,7 @@ func (s *span) Snapshot() *SpanSnapshot {
 	sd.SpanContext = s.spanContext
 	sd.SpanKind = s.spanKind
 	sd.StartTime = s.startTime
-	sd.StatusCode = s.statusCode
-	sd.StatusMessage = s.statusMessage
+	sd.Status = s.status
 
 	if s.attributes.evictList.Len() > 0 {
 		sd.Attributes = s.attributes.toKeyValue()
@@ -580,6 +571,15 @@ func isSampled(s SamplingResult) bool {
 	return s.Decision == RecordAndSample
 }
 
+// Status is the classified state of a Span.
+type Status struct {
+	// Code is an identifier of a Span's state classification.
+	Code codes.Code
+	// Message is a user hint about why the status was set. It is only
+	// applicable when Code is Error.
+	Description string
+}
+
 // SpanSnapshot is a snapshot of a span which contains all the information
 // collected by the span. Its main purpose is exporting completed spans.
 // Although SpanSnapshot fields can be accessed and potentially modified,
@@ -597,8 +597,7 @@ type SpanSnapshot struct {
 	Attributes    []attribute.KeyValue
 	MessageEvents []Event
 	Links         []trace.Link
-	StatusCode    codes.Code
-	StatusMessage string
+	Status        Status
 
 	// DroppedAttributeCount contains dropped attributes for the span itself.
 	DroppedAttributeCount    int
diff --git a/trace/trace.go b/trace/trace.go
index af1d89e5..d1494100 100644
--- a/trace/trace.go
+++ b/trace/trace.go
@@ -525,9 +525,9 @@ type Span interface {
 	SpanContext() SpanContext
 
 	// SetStatus sets the status of the Span in the form of a code and a
-	// message. SetStatus overrides the value of previous calls to SetStatus
-	// on the Span.
-	SetStatus(code codes.Code, msg string)
+	// description, overriding previous values set. The description is only
+	// included in a status when the code is for an error.
+	SetStatus(code codes.Code, description string)
 
 	// SetName sets the Span name.
 	SetName(name string)


Test patch:
diff --git a/exporters/otlp/internal/otlptest/data.go b/exporters/otlp/internal/otlptest/data.go
index 0a61f101..adfdd6b5 100644
--- a/exporters/otlp/internal/otlptest/data.go
+++ b/exporters/otlp/internal/otlptest/data.go
@@ -99,8 +99,7 @@ func SingleSpanSnapshot() []*tracesdk.SpanSnapshot {
 		Attributes:               []attribute.KeyValue{},
 		MessageEvents:            []tracesdk.Event{},
 		Links:                    []trace.Link{},
-		StatusCode:               codes.Ok,
-		StatusMessage:            "",
+		Status:                   tracesdk.Status{Code: codes.Ok},
 		DroppedAttributeCount:    0,
 		DroppedMessageEventCount: 0,
 		DroppedLinkCount:         0,
diff --git a/exporters/otlp/internal/transform/span_test.go b/exporters/otlp/internal/transform/span_test.go
index 9d89a80b..eef72645 100644
--- a/exporters/otlp/internal/transform/span_test.go
+++ b/exporters/otlp/internal/transform/span_test.go
@@ -249,8 +249,10 @@ func TestSpanData(t *testing.T) {
 				},
 			},
 		},
-		StatusCode:    codes.Error,
-		StatusMessage: "utterly unrecognized",
+		Status: tracesdk.Status{
+			Code:        codes.Error,
+			Description: "utterly unrecognized",
+		},
 		Attributes: []attribute.KeyValue{
 			attribute.Int64("timeout_ns", 12e9),
 		},
@@ -276,7 +278,7 @@ func TestSpanData(t *testing.T) {
 		Kind:                   tracepb.Span_SPAN_KIND_SERVER,
 		StartTimeUnixNano:      uint64(startTime.UnixNano()),
 		EndTimeUnixNano:        uint64(endTime.UnixNano()),
-		Status:                 status(spanData.StatusCode, spanData.StatusMessage),
+		Status:                 status(spanData.Status.Code, spanData.Status.Description),
 		Events:                 spanEvents(spanData.MessageEvents),
 		Links:                  links(spanData.Links),
 		Attributes:             Attributes(spanData.Attributes),
diff --git a/exporters/otlp/otlp_span_test.go b/exporters/otlp/otlp_span_test.go
index 26931ca6..9764280e 100644
--- a/exporters/otlp/otlp_span_test.go
+++ b/exporters/otlp/otlp_span_test.go
@@ -68,9 +68,11 @@ func TestExportSpans(t *testing.T) {
 						attribute.String("user", "alice"),
 						attribute.Bool("authenticated", true),
 					},
-					StatusCode:    codes.Ok,
-					StatusMessage: "Ok",
-					Resource:      resource.NewWithAttributes(attribute.String("instance", "tester-a")),
+					Status: tracesdk.Status{
+						Code:        codes.Ok,
+						Description: "Ok",
+					},
+					Resource: resource.NewWithAttributes(attribute.String("instance", "tester-a")),
 					InstrumentationLibrary: instrumentation.Library{
 						Name:    "lib-a",
 						Version: "v0.1.0",
@@ -90,9 +92,11 @@ func TestExportSpans(t *testing.T) {
 						attribute.String("user", "alice"),
 						attribute.Bool("authenticated", true),
 					},
-					StatusCode:    codes.Ok,
-					StatusMessage: "Ok",
-					Resource:      resource.NewWithAttributes(attribute.String("instance", "tester-a")),
+					Status: tracesdk.Status{
+						Code:        codes.Ok,
+						Description: "Ok",
+					},
+					Resource: resource.NewWithAttributes(attribute.String("instance", "tester-a")),
 					InstrumentationLibrary: instrumentation.Library{
 						Name:    "lib-b",
 						Version: "v0.1.0",
@@ -117,9 +121,11 @@ func TestExportSpans(t *testing.T) {
 						attribute.String("user", "alice"),
 						attribute.Bool("authenticated", true),
 					},
-					StatusCode:    codes.Ok,
-					StatusMessage: "Ok",
-					Resource:      resource.NewWithAttributes(attribute.String("instance", "tester-a")),
+					Status: tracesdk.Status{
+						Code:        codes.Ok,
+						Description: "Ok",
+					},
+					Resource: resource.NewWithAttributes(attribute.String("instance", "tester-a")),
 					InstrumentationLibrary: instrumentation.Library{
 						Name:    "lib-a",
 						Version: "v0.1.0",
@@ -139,9 +145,11 @@ func TestExportSpans(t *testing.T) {
 						attribute.String("user", "bob"),
 						attribute.Bool("authenticated", false),
 					},
-					StatusCode:    codes.Error,
-					StatusMessage: "Unauthenticated",
-					Resource:      resource.NewWithAttributes(attribute.String("instance", "tester-b")),
+					Status: tracesdk.Status{
+						Code:        codes.Error,
+						Description: "Unauthenticated",
+					},
+					Resource: resource.NewWithAttributes(attribute.String("instance", "tester-b")),
 					InstrumentationLibrary: instrumentation.Library{
 						Name:    "lib-a",
 						Version: "v1.1.0",
diff --git a/exporters/stdout/trace_test.go b/exporters/stdout/trace_test.go
index 8fa64fef..6c2974a5 100644
--- a/exporters/stdout/trace_test.go
+++ b/exporters/stdout/trace_test.go
@@ -64,10 +64,12 @@ func TestExporter_ExportSpan(t *testing.T) {
 			{Name: "foo", Attributes: []attribute.KeyValue{attribute.String("key", keyValue)}, Time: now},
 			{Name: "bar", Attributes: []attribute.KeyValue{attribute.Float64("double", doubleValue)}, Time: now},
 		},
-		SpanKind:      trace.SpanKindInternal,
-		StatusCode:    codes.Error,
-		StatusMessage: "interesting",
-		Resource:      resource,
+		SpanKind: trace.SpanKindInternal,
+		Status: tracesdk.Status{
+			Code:        codes.Error,
+			Description: "interesting",
+		},
+		Resource: resource,
 	}
 	if err := ex.ExportSpans(context.Background(), []*tracesdk.SpanSnapshot{testSpan}); err != nil {
 		t.Fatal(err)
@@ -129,8 +131,7 @@ func TestExporter_ExportSpan(t *testing.T) {
 		`}` +
 		`],` +
 		`"Links":null,` +
-		`"StatusCode":"Error",` +
-		`"StatusMessage":"interesting",` +
+		`"Status":{"Code":"Error","Description":"interesting"},` +
 		`"DroppedAttributeCount":0,` +
 		`"DroppedMessageEventCount":0,` +
 		`"DroppedLinkCount":0,` +
diff --git a/exporters/trace/jaeger/jaeger_test.go b/exporters/trace/jaeger/jaeger_test.go
index cb9a4549..a503f323 100644
--- a/exporters/trace/jaeger/jaeger_test.go
+++ b/exporters/trace/jaeger/jaeger_test.go
@@ -229,11 +229,11 @@ func Test_spanSnapshotToThrift(t *testing.T) {
 					TraceID: traceID,
 					SpanID:  spanID,
 				}),
-				Name:       "/foo",
-				StartTime:  now,
-				EndTime:    now,
-				StatusCode: codes.Error,
-				SpanKind:   trace.SpanKindClient,
+				Name:      "/foo",
+				StartTime: now,
+				EndTime:   now,
+				Status:    sdktrace.Status{Code: codes.Error},
+				SpanKind:  trace.SpanKindClient,
 				InstrumentationLibrary: instrumentation.Library{
 					Name:    instrLibName,
 					Version: instrLibVersion,
@@ -287,9 +287,11 @@ func Test_spanSnapshotToThrift(t *testing.T) {
 						Time:                  now,
 					},
 				},
-				StatusCode:    codes.Error,
-				StatusMessage: statusMessage,
-				SpanKind:      trace.SpanKindClient,
+				Status: sdktrace.Status{
+					Code:        codes.Error,
+					Description: statusMessage,
+				},
+				SpanKind: trace.SpanKindClient,
 				InstrumentationLibrary: instrumentation.Library{
 					Name:    instrLibName,
 					Version: instrLibVersion,
@@ -370,9 +372,11 @@ func Test_spanSnapshotToThrift(t *testing.T) {
 				Attributes: []attribute.KeyValue{
 					attribute.Array("arr", []int{0, 1, 2, 3}),
 				},
-				StatusCode:    codes.Unset,
-				StatusMessage: statusMessage,
-				SpanKind:      trace.SpanKindInternal,
+				Status: sdktrace.Status{
+					Code:        codes.Unset,
+					Description: statusMessage,
+				},
+				SpanKind: trace.SpanKindInternal,
 				InstrumentationLibrary: instrumentation.Library{
 					Name:    instrLibName,
 					Version: instrLibVersion,
@@ -421,9 +425,11 @@ func Test_spanSnapshotToThrift(t *testing.T) {
 					attribute.Int64("rk2", rv2),
 					semconv.ServiceNameKey.String("service name"),
 				),
-				StatusCode:    codes.Unset,
-				StatusMessage: statusMessage,
-				SpanKind:      trace.SpanKindInternal,
+				Status: sdktrace.Status{
+					Code:        codes.Unset,
+					Description: statusMessage,
+				},
+				SpanKind: trace.SpanKindInternal,
 				InstrumentationLibrary: instrumentation.Library{
 					Name:    instrLibName,
 					Version: instrLibVersion,
diff --git a/exporters/trace/zipkin/model_test.go b/exporters/trace/zipkin/model_test.go
index ab0979a0..999ae4f7 100644
--- a/exporters/trace/zipkin/model_test.go
+++ b/exporters/trace/zipkin/model_test.go
@@ -74,9 +74,11 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data with no parent (same as typical, but has
 		// invalid parent)
@@ -107,9 +109,11 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data of unspecified kind
 		{
@@ -143,9 +147,11 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data of internal kind
 		{
@@ -179,9 +185,11 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data of client kind
 		{
@@ -218,9 +226,11 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data of producer kind
 		{
@@ -254,9 +264,11 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data of consumer kind
 		{
@@ -290,9 +302,11 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data with no events
 		{
@@ -313,9 +327,11 @@ func TestModelConversion(t *testing.T) {
 				attribute.String("attr2", "bar"),
 			},
 			MessageEvents: nil,
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: tracesdk.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// span data with an "error" attribute set to "false"
 		{
@@ -348,8 +364,7 @@ func TestModelConversion(t *testing.T) {
 					Attributes: nil,
 				},
 			},
-			StatusCode: codes.Unset,
-			Resource:   resource,
+			Resource: resource,
 		},
 	}
 
@@ -759,8 +774,10 @@ func TestTagsTransformation(t *testing.T) {
 					attribute.String("key", keyValue),
 					attribute.Bool("error", true),
 				},
-				StatusCode:    codes.Error,
-				StatusMessage: statusMessage,
+				Status: tracesdk.Status{
+					Code:        codes.Error,
+					Description: statusMessage,
+				},
 			},
 			want: map[string]string{
 				"error":            statusMessage,
diff --git a/exporters/trace/zipkin/zipkin_test.go b/exporters/trace/zipkin/zipkin_test.go
index 95b0b3d6..bd63f721 100644
--- a/exporters/trace/zipkin/zipkin_test.go
+++ b/exporters/trace/zipkin/zipkin_test.go
@@ -246,9 +246,11 @@ func TestExportSpans(t *testing.T) {
 			EndTime:       time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
 			Attributes:    nil,
 			MessageEvents: nil,
-			StatusCode:    codes.Error,
-			StatusMessage: "404, file not found",
-			Resource:      resource,
+			Status: sdktrace.Status{
+				Code:        codes.Error,
+				Description: "404, file not found",
+			},
+			Resource: resource,
 		},
 		// child
 		{
@@ -266,9 +268,11 @@ func TestExportSpans(t *testing.T) {
 			EndTime:       time.Date(2020, time.March, 11, 19, 24, 45, 0, time.UTC),
 			Attributes:    nil,
 			MessageEvents: nil,
-			StatusCode:    codes.Error,
-			StatusMessage: "403, forbidden",
-			Resource:      resource,
+			Status: sdktrace.Status{
+				Code:        codes.Error,
+				Description: "403, forbidden",
+			},
+			Resource: resource,
 		},
 	}
 	models := []zkmodel.SpanModel{
diff --git a/sdk/trace/trace_test.go b/sdk/trace/trace_test.go
index 6495215f..4789c20d 100644
--- a/sdk/trace/trace_test.go
+++ b/sdk/trace/trace_test.go
@@ -738,11 +738,13 @@ func TestSetSpanStatus(t *testing.T) {
 			TraceID:    tid,
 			TraceFlags: 0x1,
 		}),
-		Parent:                 sc.WithRemote(true),
-		Name:                   "span0",
-		SpanKind:               trace.SpanKindInternal,
-		StatusCode:             codes.Error,
-		StatusMessage:          "Error",
+		Parent:   sc.WithRemote(true),
+		Name:     "span0",
+		SpanKind: trace.SpanKindInternal,
+		Status: Status{
+			Code:        codes.Error,
+			Description: "Error",
+		},
 		InstrumentationLibrary: instrumentation.Library{Name: "SpanStatus"},
 	}
 	if diff := cmpDiff(got, want); diff != "" {
@@ -766,11 +768,13 @@ func TestSetSpanStatusWithoutMessageWhenStatusIsNotError(t *testing.T) {
 			TraceID:    tid,
 			TraceFlags: 0x1,
 		}),
-		Parent:                 sc.WithRemote(true),
-		Name:                   "span0",
-		SpanKind:               trace.SpanKindInternal,
-		StatusCode:             codes.Ok,
-		StatusMessage:          "",
+		Parent:   sc.WithRemote(true),
+		Name:     "span0",
+		SpanKind: trace.SpanKindInternal,
+		Status: Status{
+			Code:        codes.Ok,
+			Description: "",
+		},
 		InstrumentationLibrary: instrumentation.Library{Name: "SpanStatus"},
 	}
 	if diff := cmpDiff(got, want); diff != "" {
@@ -1115,10 +1119,10 @@ func TestRecordError(t *testing.T) {
 				TraceID:    tid,
 				TraceFlags: 0x1,
 			}),
-			Parent:     sc.WithRemote(true),
-			Name:       "span0",
-			StatusCode: codes.Unset,
-			SpanKind:   trace.SpanKindInternal,
+			Parent:   sc.WithRemote(true),
+			Name:     "span0",
+			Status:   Status{Code: codes.Unset},
+			SpanKind: trace.SpanKindInternal,
 			MessageEvents: []Event{
 				{
 					Name: semconv.ExceptionEventName,
@@ -1154,11 +1158,13 @@ func TestRecordErrorNil(t *testing.T) {
 			TraceID:    tid,
 			TraceFlags: 0x1,
 		}),
-		Parent:                 sc.WithRemote(true),
-		Name:                   "span0",
-		SpanKind:               trace.SpanKindInternal,
-		StatusCode:             codes.Unset,
-		StatusMessage:          "",
+		Parent:   sc.WithRemote(true),
+		Name:     "span0",
+		SpanKind: trace.SpanKindInternal,
+		Status: Status{
+			Code:        codes.Unset,
+			Description: "",
+		},
 		InstrumentationLibrary: instrumentation.Library{Name: "RecordErrorNil"},
 	}
 	if diff := cmpDiff(got, want); diff != "" {
@@ -1380,8 +1386,8 @@ func TestReadOnlySpan(t *testing.T) {
 	assert.Equal(t, linked, ro.Links()[0].SpanContext)
 	assert.Equal(t, kv.Key, ro.Events()[0].Attributes[0].Key)
 	assert.Equal(t, kv.Value, ro.Events()[0].Attributes[0].Value)
-	assert.Equal(t, codes.Ok, ro.StatusCode())
-	assert.Equal(t, "", ro.StatusMessage())
+	assert.Equal(t, codes.Ok, ro.Status().Code)
+	assert.Equal(t, "", ro.Status().Description)
 	assert.Equal(t, "ReadOnlySpan", ro.InstrumentationLibrary().Name)
 	assert.Equal(t, "3", ro.InstrumentationLibrary().Version)
 	assert.Equal(t, kv.Key, ro.Resource().Attributes()[0].Key)