forked from open-telemetry/opentelemetry-collector-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[exporter/awsxray] Add span links and messenger field translation to …
…x-ray exporter. (open-telemetry#20313) Add link span link support and support for the messaging field. We are conforming to the OTel spec: - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#specifying-links - https://github.com/open-telemetry/opentelemetry-specification/blob/main/semantic_conventions/trace/messaging.yaml#L110
- Loading branch information
Showing
6 changed files
with
309 additions
and
4 deletions.
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
.chloggen/awsxray-support-span-links-and-messaging-field.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' | ||
change_type: enhancement | ||
|
||
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) | ||
component: awsxrayexporter | ||
|
||
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). | ||
note: Adding translation support for span links for the aws x-ray exporter | ||
|
||
# One or more tracking issues related to the change | ||
issues: [20353] | ||
|
||
# (Optional) One or more lines of additional information to render under the primary note. | ||
# These lines will be padded with 2 spaces and then inserted directly into the document. | ||
# Use pipe (|) for multiline entries. | ||
subtext: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
local/ | ||
vendor/ | ||
|
||
# GoLand IDEA | ||
/.idea/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
exporter/awsxrayexporter/internal/translator/span_links.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package translator // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter/internal/translator" | ||
|
||
import ( | ||
"go.opentelemetry.io/collector/pdata/pcommon" | ||
"go.opentelemetry.io/collector/pdata/ptrace" | ||
|
||
awsxray "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/xray" | ||
) | ||
|
||
func makeSpanLinks(links ptrace.SpanLinkSlice) ([]awsxray.SpanLinkData, error) { | ||
var spanLinkDataArray []awsxray.SpanLinkData | ||
|
||
for i := 0; i < links.Len(); i++ { | ||
var spanLinkData awsxray.SpanLinkData | ||
var link = links.At(i) | ||
|
||
var spanID = link.SpanID().String() | ||
traceID, err := convertToAmazonTraceID(link.TraceID()) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
spanLinkData.SpanID = &spanID | ||
spanLinkData.TraceID = &traceID | ||
|
||
if link.Attributes().Len() > 0 { | ||
spanLinkData.Attributes = make(map[string]interface{}) | ||
|
||
link.Attributes().Range(func(k string, v pcommon.Value) bool { | ||
spanLinkData.Attributes[k] = v.AsRaw() | ||
return true | ||
}) | ||
} | ||
|
||
spanLinkDataArray = append(spanLinkDataArray, spanLinkData) | ||
} | ||
|
||
return spanLinkDataArray, nil | ||
} |
231 changes: 231 additions & 0 deletions
231
exporter/awsxrayexporter/internal/translator/span_links_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package translator // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter/internal/translator" | ||
|
||
import ( | ||
"encoding/binary" | ||
"strings" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"go.opentelemetry.io/collector/pdata/ptrace" | ||
) | ||
|
||
func TestSpanLinkSimple(t *testing.T) { | ||
spanName := "ProcessingMessage" | ||
parentSpanID := newSegmentID() | ||
attributes := make(map[string]interface{}) | ||
resource := constructDefaultResource() | ||
span := constructServerSpan(parentSpanID, spanName, ptrace.StatusCodeOk, "OK", attributes) | ||
|
||
var traceID = newTraceID() | ||
|
||
spanLink := span.Links().AppendEmpty() | ||
spanLink.SetTraceID(traceID) | ||
spanLink.SetSpanID(newSegmentID()) | ||
|
||
segment, _ := MakeSegment(span, resource, nil, false, nil) | ||
|
||
var convertedTraceID, _ = convertToAmazonTraceID(traceID) | ||
|
||
assert.Equal(t, 1, len(segment.Links)) | ||
assert.Equal(t, spanLink.SpanID().String(), *segment.Links[0].SpanID) | ||
assert.Equal(t, convertedTraceID, *segment.Links[0].TraceID) | ||
assert.Equal(t, 0, len(segment.Links[0].Attributes)) | ||
|
||
jsonStr, _ := MakeSegmentDocumentString(span, resource, nil, false, nil) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "links")) | ||
assert.False(t, strings.Contains(jsonStr, "attributes")) | ||
assert.True(t, strings.Contains(jsonStr, convertedTraceID)) | ||
assert.True(t, strings.Contains(jsonStr, spanLink.SpanID().String())) | ||
} | ||
|
||
func TestSpanLinkEmpty(t *testing.T) { | ||
spanName := "ProcessingMessage" | ||
parentSpanID := newSegmentID() | ||
attributes := make(map[string]interface{}) | ||
resource := constructDefaultResource() | ||
span := constructServerSpan(parentSpanID, spanName, ptrace.StatusCodeOk, "OK", attributes) | ||
|
||
segment, _ := MakeSegment(span, resource, nil, false, nil) | ||
|
||
assert.Equal(t, 0, len(segment.Links)) | ||
|
||
jsonStr, _ := MakeSegmentDocumentString(span, resource, nil, false, nil) | ||
|
||
assert.False(t, strings.Contains(jsonStr, "links")) | ||
} | ||
|
||
func TestOldSpanLinkError(t *testing.T) { | ||
spanName := "ProcessingMessage" | ||
parentSpanID := newSegmentID() | ||
attributes := make(map[string]interface{}) | ||
resource := constructDefaultResource() | ||
span := constructServerSpan(parentSpanID, spanName, ptrace.StatusCodeOk, "OK", attributes) | ||
|
||
const maxAge = 60 * 60 * 24 * 30 | ||
ExpiredEpoch := time.Now().Unix() - maxAge - 1 | ||
|
||
var traceID = newTraceID() | ||
binary.BigEndian.PutUint32(traceID[0:4], uint32(ExpiredEpoch)) | ||
|
||
spanLink := span.Links().AppendEmpty() | ||
spanLink.SetTraceID(traceID) | ||
spanLink.SetSpanID(newSegmentID()) | ||
|
||
_, error1 := MakeSegment(span, resource, nil, false, nil) | ||
|
||
assert.NotNil(t, error1) | ||
|
||
_, error2 := MakeSegmentDocumentString(span, resource, nil, false, nil) | ||
|
||
assert.NotNil(t, error2) | ||
} | ||
|
||
func TestTwoSpanLinks(t *testing.T) { | ||
spanName := "ProcessingMessage" | ||
parentSpanID := newSegmentID() | ||
attributes := make(map[string]interface{}) | ||
resource := constructDefaultResource() | ||
span := constructServerSpan(parentSpanID, spanName, ptrace.StatusCodeOk, "OK", attributes) | ||
|
||
var traceID1 = newTraceID() | ||
|
||
spanLink1 := span.Links().AppendEmpty() | ||
spanLink1.SetTraceID(traceID1) | ||
spanLink1.SetSpanID(newSegmentID()) | ||
spanLink1.Attributes().PutStr("myKey1", "ABC") | ||
|
||
var traceID2 = newTraceID() | ||
|
||
spanLink2 := span.Links().AppendEmpty() | ||
spanLink2.SetTraceID(traceID2) | ||
spanLink2.SetSpanID(newSegmentID()) | ||
spanLink2.Attributes().PutInt("myKey2", 1234) | ||
|
||
segment, _ := MakeSegment(span, resource, nil, false, nil) | ||
|
||
var convertedTraceID1, _ = convertToAmazonTraceID(traceID1) | ||
var convertedTraceID2, _ = convertToAmazonTraceID(traceID2) | ||
|
||
assert.Equal(t, 2, len(segment.Links)) | ||
assert.Equal(t, spanLink1.SpanID().String(), *segment.Links[0].SpanID) | ||
assert.Equal(t, convertedTraceID1, *segment.Links[0].TraceID) | ||
|
||
assert.Equal(t, 1, len(segment.Links[0].Attributes)) | ||
assert.Equal(t, "ABC", segment.Links[0].Attributes["myKey1"]) | ||
|
||
assert.Equal(t, spanLink2.SpanID().String(), *segment.Links[1].SpanID) | ||
assert.Equal(t, convertedTraceID2, *segment.Links[1].TraceID) | ||
assert.Equal(t, 1, len(segment.Links[0].Attributes)) | ||
assert.Equal(t, int64(1234), segment.Links[1].Attributes["myKey2"]) | ||
|
||
jsonStr, _ := MakeSegmentDocumentString(span, resource, nil, false, nil) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "attributes")) | ||
assert.True(t, strings.Contains(jsonStr, "links")) | ||
assert.True(t, strings.Contains(jsonStr, "myKey1")) | ||
assert.True(t, strings.Contains(jsonStr, "myKey2")) | ||
assert.True(t, strings.Contains(jsonStr, "ABC")) | ||
assert.True(t, strings.Contains(jsonStr, "1234")) | ||
assert.True(t, strings.Contains(jsonStr, convertedTraceID1)) | ||
assert.True(t, strings.Contains(jsonStr, convertedTraceID2)) | ||
} | ||
|
||
func TestSpanLinkComplexAttributes(t *testing.T) { | ||
spanName := "ProcessingMessage" | ||
parentSpanID := newSegmentID() | ||
attributes := make(map[string]interface{}) | ||
resource := constructDefaultResource() | ||
span := constructServerSpan(parentSpanID, spanName, ptrace.StatusCodeOk, "OK", attributes) | ||
|
||
spanLink := span.Links().AppendEmpty() | ||
spanLink.SetTraceID(newTraceID()) | ||
spanLink.SetSpanID(newSegmentID()) | ||
spanLink.Attributes().PutStr("myKey1", "myValue") | ||
spanLink.Attributes().PutBool("myKey2", true) | ||
spanLink.Attributes().PutInt("myKey3", 112233) | ||
spanLink.Attributes().PutDouble("myKey4", 3.1415) | ||
|
||
var slice1 = spanLink.Attributes().PutEmptySlice("myKey5") | ||
slice1.AppendEmpty().SetStr("apple") | ||
slice1.AppendEmpty().SetStr("pear") | ||
slice1.AppendEmpty().SetStr("banana") | ||
|
||
var slice2 = spanLink.Attributes().PutEmptySlice("myKey6") | ||
slice2.AppendEmpty().SetBool(true) | ||
slice2.AppendEmpty().SetBool(false) | ||
slice2.AppendEmpty().SetBool(false) | ||
slice2.AppendEmpty().SetBool(true) | ||
|
||
var slice3 = spanLink.Attributes().PutEmptySlice("myKey7") | ||
slice3.AppendEmpty().SetInt(1234) | ||
slice3.AppendEmpty().SetInt(5678) | ||
slice3.AppendEmpty().SetInt(9012) | ||
|
||
var slice4 = spanLink.Attributes().PutEmptySlice("myKey8") | ||
slice4.AppendEmpty().SetDouble(2.718) | ||
slice4.AppendEmpty().SetDouble(1.618) | ||
|
||
segment, _ := MakeSegment(span, resource, nil, false, nil) | ||
|
||
assert.Equal(t, 1, len(segment.Links)) | ||
assert.Equal(t, 8, len(segment.Links[0].Attributes)) | ||
|
||
assert.Equal(t, "myValue", segment.Links[0].Attributes["myKey1"]) | ||
assert.Equal(t, true, segment.Links[0].Attributes["myKey2"]) | ||
assert.Equal(t, int64(112233), segment.Links[0].Attributes["myKey3"]) | ||
assert.Equal(t, 3.1415, segment.Links[0].Attributes["myKey4"]) | ||
|
||
assert.Equal(t, "apple", segment.Links[0].Attributes["myKey5"].([]interface{})[0]) | ||
assert.Equal(t, "pear", segment.Links[0].Attributes["myKey5"].([]interface{})[1]) | ||
assert.Equal(t, "banana", segment.Links[0].Attributes["myKey5"].([]interface{})[2]) | ||
|
||
assert.Equal(t, true, segment.Links[0].Attributes["myKey6"].([]interface{})[0]) | ||
assert.Equal(t, false, segment.Links[0].Attributes["myKey6"].([]interface{})[1]) | ||
assert.Equal(t, false, segment.Links[0].Attributes["myKey6"].([]interface{})[2]) | ||
assert.Equal(t, true, segment.Links[0].Attributes["myKey6"].([]interface{})[0]) | ||
|
||
assert.Equal(t, int64(1234), segment.Links[0].Attributes["myKey7"].([]interface{})[0]) | ||
assert.Equal(t, int64(5678), segment.Links[0].Attributes["myKey7"].([]interface{})[1]) | ||
assert.Equal(t, int64(9012), segment.Links[0].Attributes["myKey7"].([]interface{})[2]) | ||
|
||
assert.Equal(t, 2.718, segment.Links[0].Attributes["myKey8"].([]interface{})[0]) | ||
assert.Equal(t, 1.618, segment.Links[0].Attributes["myKey8"].([]interface{})[1]) | ||
|
||
jsonStr, _ := MakeSegmentDocumentString(span, resource, nil, false, nil) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "links")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey1")) | ||
assert.True(t, strings.Contains(jsonStr, "myValue")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey2")) | ||
assert.True(t, strings.Contains(jsonStr, "true")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey3")) | ||
assert.True(t, strings.Contains(jsonStr, "112233")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey4")) | ||
assert.True(t, strings.Contains(jsonStr, "3.1415")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey5")) | ||
assert.True(t, strings.Contains(jsonStr, "apple")) | ||
assert.True(t, strings.Contains(jsonStr, "pear")) | ||
assert.True(t, strings.Contains(jsonStr, "banana")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey6")) | ||
assert.True(t, strings.Contains(jsonStr, "false")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey7")) | ||
assert.True(t, strings.Contains(jsonStr, "1234")) | ||
assert.True(t, strings.Contains(jsonStr, "5678")) | ||
assert.True(t, strings.Contains(jsonStr, "9012")) | ||
|
||
assert.True(t, strings.Contains(jsonStr, "myKey8")) | ||
assert.True(t, strings.Contains(jsonStr, "2.718")) | ||
assert.True(t, strings.Contains(jsonStr, "1.618")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters