Skip to content

Commit

Permalink
Update OTLP to 0.6.0 and use the new Span Status code
Browse files Browse the repository at this point in the history
Contributes to open-telemetry#1841

- Implemente the backward compatibility logic for sending and receiving
  side for DeprecatedCode and Code fields according to OTLP spec.

- Had to modify pdata generator to allow generating fields without setters.
  This is needed because the Status code field needs a custom setter logic
  that implements the DeprecatedCode vs Code handling.

- Added tests that verify OTLP receiver behavior for Status Code/DeprecatedCode.

- Added tests that verify sending/setting behavior for Status Code/DeprecatedCode
  for any component that uses pdata.Traces Status.SetCode().

- Modified all non-OTLP trace receivers and exporters (Jaeger, Zipkin, OpenCensus) to use
  the new Status code.

- Modified correctness tests to use the new status Code instead of DeprecatedCode.
  • Loading branch information
Tigran Najaryan committed Nov 3, 2020
1 parent 77c4d29 commit 0d2d8bb
Show file tree
Hide file tree
Showing 25 changed files with 780 additions and 413 deletions.
16 changes: 15 additions & 1 deletion cmd/pdatagen/internal/base_fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ func (ms ${structName}) Set${fieldName}(v ${returnType}) {
(*ms.orig).${originFieldName} = ${rawType}(v)
}`

const accessorsPrimitiveWithoutSetterTypedTemplate = `// ${fieldName} returns the ${lowerFieldName} associated with this ${structName}.
//
// Important: This causes a runtime error if IsNil() returns "true".
func (ms ${structName}) ${fieldName}() ${returnType} {
return ${returnType}((*ms.orig).${originFieldName})
}`

type baseField interface {
generateAccessors(ms *messageStruct, sb *strings.Builder)

Expand Down Expand Up @@ -265,10 +272,17 @@ type primitiveTypedField struct {
defaultVal string
testVal string
rawType string
manualSetter bool
}

func (ptf *primitiveTypedField) generateAccessors(ms *messageStruct, sb *strings.Builder) {
sb.WriteString(os.Expand(accessorsPrimitiveTypedTemplate, func(name string) string {
template := accessorsPrimitiveTypedTemplate
if ptf.manualSetter {
// Generate code without setter. Setter will be manually coded.
template = accessorsPrimitiveWithoutSetterTypedTemplate
}

sb.WriteString(os.Expand(template, func(name string) string {
switch name {
case "structName":
return ms.structName
Expand Down
12 changes: 12 additions & 0 deletions cmd/pdatagen/internal/trace_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,18 @@ var spanStatus = &messageStruct{
rawType: "otlptrace.Status_StatusCode",
defaultVal: "StatusCode(0)",
testVal: "StatusCode(1)",
// Generate code without setter. Setter will be manually coded since we
// need to also change DeprecatedCode when Code is changed according
// to OTLP spec https://github.com/open-telemetry/opentelemetry-proto/blob/59c488bfb8fb6d0458ad6425758b70259ff4a2bd/opentelemetry/proto/trace/v1/trace.proto#L231
manualSetter: true,
},
&primitiveTypedField{
fieldName: "DeprecatedCode",
originFieldName: "DeprecatedCode",
returnType: "DeprecatedStatusCode",
rawType: "otlptrace.Status_DeprecatedStatusCode",
defaultVal: "DeprecatedStatusCode(0)",
testVal: "DeprecatedStatusCode(1)",
},
&primitiveField{
fieldName: "Message",
Expand Down
14 changes: 11 additions & 3 deletions consumer/pdata/generated_trace.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions consumer/pdata/generated_trace_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 60 additions & 19 deletions consumer/pdata/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,29 +130,70 @@ const (
SpanKindCONSUMER = SpanKind(otlptrace.Span_SPAN_KIND_CONSUMER)
)

// DeprecatedStatusCode is the deprecated status code used previously.
// https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md#set-status
// Deprecated: use StatusCode instead.
type DeprecatedStatusCode otlptrace.Status_DeprecatedStatusCode

const (
DeprecatedStatusCodeOk = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_OK)
DeprecatedStatusCodeCancelled = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_CANCELLED)
DeprecatedStatusCodeUnknownError = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_UNKNOWN_ERROR)
DeprecatedStatusCodeInvalidArgument = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_INVALID_ARGUMENT)
DeprecatedStatusCodeDeadlineExceeded = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_DEADLINE_EXCEEDED)
DeprecatedStatusCodeNotFound = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_NOT_FOUND)
DeprecatedStatusCodeAlreadyExists = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_ALREADY_EXISTS)
DeprecatedStatusCodePermissionDenied = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_PERMISSION_DENIED)
DeprecatedStatusCodeResourceExhausted = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_RESOURCE_EXHAUSTED)
DeprecatedStatusCodeFailedPrecondition = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_FAILED_PRECONDITION)
DeprecatedStatusCodeAborted = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_ABORTED)
DeprecatedStatusCodeOutOfRange = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_OUT_OF_RANGE)
DeprecatedStatusCodeUnimplemented = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_UNIMPLEMENTED)
DeprecatedStatusCodeInternalError = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_INTERNAL_ERROR)
DeprecatedStatusCodeUnavailable = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_UNAVAILABLE)
DeprecatedStatusCodeDataLoss = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_DATA_LOSS)
DeprecatedStatusCodeUnauthenticated = DeprecatedStatusCode(otlptrace.Status_DEPRECATED_STATUS_CODE_UNAUTHENTICATED)
)

func (sc DeprecatedStatusCode) String() string {
return otlptrace.Status_DeprecatedStatusCode(sc).String()
}

// StatusCode mirrors the codes defined at
// https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-tracing.md#statuscanonicalcode
// and is numerically equal to Standard GRPC codes https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
// https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md#set-status
type StatusCode otlptrace.Status_StatusCode

const (
StatusCodeOk = StatusCode(otlptrace.Status_STATUS_CODE_OK)
StatusCodeCancelled = StatusCode(otlptrace.Status_STATUS_CODE_CANCELLED)
StatusCodeUnknownError = StatusCode(otlptrace.Status_STATUS_CODE_UNKNOWN_ERROR)
StatusCodeInvalidArgument = StatusCode(otlptrace.Status_STATUS_CODE_INVALID_ARGUMENT)
StatusCodeDeadlineExceeded = StatusCode(otlptrace.Status_STATUS_CODE_DEADLINE_EXCEEDED)
StatusCodeNotFound = StatusCode(otlptrace.Status_STATUS_CODE_NOT_FOUND)
StatusCodeAlreadyExists = StatusCode(otlptrace.Status_STATUS_CODE_ALREADY_EXISTS)
StatusCodePermissionDenied = StatusCode(otlptrace.Status_STATUS_CODE_PERMISSION_DENIED)
StatusCodeResourceExhausted = StatusCode(otlptrace.Status_STATUS_CODE_RESOURCE_EXHAUSTED)
StatusCodeFailedPrecondition = StatusCode(otlptrace.Status_STATUS_CODE_FAILED_PRECONDITION)
StatusCodeAborted = StatusCode(otlptrace.Status_STATUS_CODE_ABORTED)
StatusCodeOutOfRange = StatusCode(otlptrace.Status_STATUS_CODE_OUT_OF_RANGE)
StatusCodeUnimplemented = StatusCode(otlptrace.Status_STATUS_CODE_UNIMPLEMENTED)
StatusCodeInternalError = StatusCode(otlptrace.Status_STATUS_CODE_INTERNAL_ERROR)
StatusCodeUnavailable = StatusCode(otlptrace.Status_STATUS_CODE_UNAVAILABLE)
StatusCodeDataLoss = StatusCode(otlptrace.Status_STATUS_CODE_DATA_LOSS)
StatusCodeUnauthenticated = StatusCode(otlptrace.Status_STATUS_CODE_UNAUTHENTICATED)
StatusCodeUnset = StatusCode(otlptrace.Status_STATUS_CODE_UNSET)
StatusCodeOk = StatusCode(otlptrace.Status_STATUS_CODE_OK)
StatusCodeError = StatusCode(otlptrace.Status_STATUS_CODE_ERROR)
)

func (sc StatusCode) String() string { return otlptrace.Status_StatusCode(sc).String() }

// SetCode replaces the code associated with this SpanStatus.
//
// Important: This causes a runtime error if IsNil() returns "true".
func (ms SpanStatus) SetCode(v StatusCode) {
(*ms.orig).Code = otlptrace.Status_StatusCode(v)

// According to OTLP spec we also need to set the deprecated_code field.
// See https://github.com/open-telemetry/opentelemetry-proto/blob/59c488bfb8fb6d0458ad6425758b70259ff4a2bd/opentelemetry/proto/trace/v1/trace.proto#L231
//
// if code==STATUS_CODE_UNSET then `deprecated_code` MUST be
// set to DEPRECATED_STATUS_CODE_OK.
//
// if code==STATUS_CODE_OK then `deprecated_code` MUST be
// set to DEPRECATED_STATUS_CODE_OK.
//
// if code==STATUS_CODE_ERROR then `deprecated_code` MUST be
// set to DEPRECATED_STATUS_CODE_UNKNOWN_ERROR.
switch v {
case StatusCodeUnset:
fallthrough
case StatusCodeOk:
ms.SetDeprecatedCode(DeprecatedStatusCodeOk)
case StatusCodeError:
ms.SetDeprecatedCode(DeprecatedStatusCodeUnknownError)
}
}
37 changes: 37 additions & 0 deletions consumer/pdata/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,43 @@ func TestTraceID(t *testing.T) {
assert.EqualValues(t, [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1}, tid.Bytes())
}

func TestSpanStatusCode(t *testing.T) {
td := NewTraces()
rss := td.ResourceSpans()
rss.Resize(1)
rss.At(0).InstrumentationLibrarySpans().Resize(1)
rss.At(0).InstrumentationLibrarySpans().At(0).Spans().Resize(1)
status := rss.At(0).InstrumentationLibrarySpans().At(0).Spans().At(0).Status()
status.InitEmpty()

// Check handling of deprecated status code, see spec here:
// https://github.com/open-telemetry/opentelemetry-proto/blob/59c488bfb8fb6d0458ad6425758b70259ff4a2bd/opentelemetry/proto/trace/v1/trace.proto#L231
//
// 2. New senders, which are aware of the `code` field MUST set both the
// `deprecated_code` and `code` fields according to the following rules:
//
// if code==STATUS_CODE_UNSET then `deprecated_code` MUST be
// set to DEPRECATED_STATUS_CODE_OK.
status.SetDeprecatedCode(DeprecatedStatusCodeUnknownError)
assert.EqualValues(t, DeprecatedStatusCodeUnknownError, status.DeprecatedCode())
status.SetCode(StatusCodeUnset)
assert.EqualValues(t, DeprecatedStatusCodeOk, status.DeprecatedCode())

// if code==STATUS_CODE_OK then `deprecated_code` MUST be
// set to DEPRECATED_STATUS_CODE_OK.
status.SetDeprecatedCode(DeprecatedStatusCodeUnknownError)
assert.EqualValues(t, DeprecatedStatusCodeUnknownError, status.DeprecatedCode())
status.SetCode(StatusCodeOk)
assert.EqualValues(t, DeprecatedStatusCodeOk, status.DeprecatedCode())

// if code==STATUS_CODE_ERROR then `deprecated_code` MUST be
// set to DEPRECATED_STATUS_CODE_UNKNOWN_ERROR.
status.SetDeprecatedCode(DeprecatedStatusCodeOk)
assert.EqualValues(t, DeprecatedStatusCodeOk, status.DeprecatedCode())
status.SetCode(StatusCodeError)
assert.EqualValues(t, DeprecatedStatusCodeUnknownError, status.DeprecatedCode())
}

func TestToFromOtlp(t *testing.T) {
otlp := []*otlptrace.ResourceSpans(nil)
td := TracesFromOtlp(otlp)
Expand Down
Loading

0 comments on commit 0d2d8bb

Please sign in to comment.