diff --git a/.chloggen/xray-exporter-dynamodb-translation-fix.yaml b/.chloggen/xray-exporter-dynamodb-translation-fix.yaml new file mode 100644 index 000000000000..4c9631b73431 --- /dev/null +++ b/.chloggen/xray-exporter-dynamodb-translation-fix.yaml @@ -0,0 +1,16 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: 'bug_fix' + +# 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: "Fixed DynamoDB table name from being set as an empty string when reading from attributes" + +# One or more tracking issues related to the change +issues: [19204] + +# (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: diff --git a/exporter/awsxrayexporter/internal/translator/aws.go b/exporter/awsxrayexporter/internal/translator/aws.go index 4946805f3765..6fd38dfc356f 100644 --- a/exporter/awsxrayexporter/internal/translator/aws.go +++ b/exporter/awsxrayexporter/internal/translator/aws.go @@ -43,6 +43,7 @@ func makeAws(attributes map[string]pcommon.Value, resource pcommon.Resource, log requestID string queueURL string tableName string + tableNames []string sdk string sdkName string sdkLanguage string @@ -167,7 +168,15 @@ func makeAws(attributes map[string]pcommon.Value, resource pcommon.Resource, log queueURL = value.Str() } if value, ok := attributes[conventions.AttributeAWSDynamoDBTableNames]; ok { - tableName = value.Str() + if value.Slice().Len() == 1 { + tableName = value.Slice().At(0).Str() + } else if value.Slice().Len() > 1 { + tableName = "" + tableNames = []string{} + for i := 0; i < value.Slice().Len(); i++ { + tableNames = append(tableNames, value.Slice().At(i).Str()) + } + } } // EC2 - add ec2 metadata to xray request if @@ -264,6 +273,7 @@ func makeAws(attributes map[string]pcommon.Value, resource pcommon.Resource, log RequestID: awsxray.String(requestID), QueueURL: awsxray.String(queueURL), TableName: awsxray.String(tableName), + TableNames: tableNames, } return filtered, awsData } diff --git a/exporter/awsxrayexporter/internal/translator/aws_test.go b/exporter/awsxrayexporter/internal/translator/aws_test.go index 34f3d2e46c46..26555d83baed 100644 --- a/exporter/awsxrayexporter/internal/translator/aws_test.go +++ b/exporter/awsxrayexporter/internal/translator/aws_test.go @@ -305,7 +305,8 @@ func TestAwsWithDynamoDbAlternateAttribute(t *testing.T) { func TestAwsWithDynamoDbSemConvAttributes(t *testing.T) { tableName := "MyTable" attributes := make(map[string]pcommon.Value) - attributes[conventions.AttributeAWSDynamoDBTableNames] = pcommon.NewValueStr(tableName) + attributes[conventions.AttributeAWSDynamoDBTableNames] = pcommon.NewValueSlice() + attributes[conventions.AttributeAWSDynamoDBTableNames].Slice().AppendEmpty().SetStr(tableName) filtered, awsData := makeAws(attributes, pcommon.NewResource(), nil) diff --git a/exporter/awsxrayexporter/internal/translator/segment_test.go b/exporter/awsxrayexporter/internal/translator/segment_test.go index 4afd7586c92f..178d456a3126 100644 --- a/exporter/awsxrayexporter/internal/translator/segment_test.go +++ b/exporter/awsxrayexporter/internal/translator/segment_test.go @@ -830,6 +830,38 @@ func TestFilteredAttributesMetadata(t *testing.T) { }, segment.Metadata["default"]["map_value"]) } +func TestSpanWithSingleDynamoDBTableHasTableName(t *testing.T) { + spanName := "/api/locations" + parentSpanID := newSegmentID() + attributes := make(map[string]interface{}) + attributes[conventions.AttributeAWSDynamoDBTableNames] = []string{"table1"} + resource := constructDefaultResource() + span := constructServerSpan(parentSpanID, spanName, ptrace.StatusCodeError, "OK", attributes) + + segment, _ := MakeSegment(span, resource, nil, false, nil) + + assert.NotNil(t, segment) + assert.Equal(t, "table1", *segment.AWS.TableName) + assert.Nil(t, segment.AWS.TableNames) + assert.Equal(t, []interface{}{"table1"}, segment.Metadata["default"][conventions.AttributeAWSDynamoDBTableNames]) +} + +func TestSpanWithMultipleDynamoDBTablesHasTableNames(t *testing.T) { + spanName := "/api/locations" + parentSpanID := newSegmentID() + attributes := make(map[string]interface{}) + attributes[conventions.AttributeAWSDynamoDBTableNames] = []string{"table1", "table2"} + resource := constructDefaultResource() + span := constructServerSpan(parentSpanID, spanName, ptrace.StatusCodeError, "OK", attributes) + + segment, _ := MakeSegment(span, resource, nil, false, nil) + + assert.NotNil(t, segment) + assert.Nil(t, segment.AWS.TableName) + assert.Equal(t, []string{"table1", "table2"}, segment.AWS.TableNames) + assert.Equal(t, []interface{}{"table1", "table2"}, segment.Metadata["default"][conventions.AttributeAWSDynamoDBTableNames]) +} + func TestSegmentWithLogGroupsFromConfig(t *testing.T) { spanName := "/api/locations" parentSpanID := newSegmentID() diff --git a/internal/aws/xray/tracesegment.go b/internal/aws/xray/tracesegment.go index ebfd8c8c6865..fc98ce3c5ce1 100644 --- a/internal/aws/xray/tracesegment.go +++ b/internal/aws/xray/tracesegment.go @@ -111,13 +111,14 @@ type AWSData struct { XRay *XRayMetaData `json:"xray,omitempty"` // For both segment and subsegments - AccountID *string `json:"account_id,omitempty"` - Operation *string `json:"operation,omitempty"` - RemoteRegion *string `json:"region,omitempty"` - RequestID *string `json:"request_id,omitempty"` - QueueURL *string `json:"queue_url,omitempty"` - TableName *string `json:"table_name,omitempty"` - Retries *int64 `json:"retries,omitempty"` + AccountID *string `json:"account_id,omitempty"` + Operation *string `json:"operation,omitempty"` + RemoteRegion *string `json:"region,omitempty"` + RequestID *string `json:"request_id,omitempty"` + QueueURL *string `json:"queue_url,omitempty"` + TableName *string `json:"table_name,omitempty"` + TableNames []string `json:"table_names,omitempty"` + Retries *int64 `json:"retries,omitempty"` } // EC2Metadata represents the EC2 metadata field