Skip to content

Commit

Permalink
[exporter/awsxrayexporter]: Add support to string resource attributes (
Browse files Browse the repository at this point in the history
…#17503)

Allow string resource attributes to be used in some resource attributes of type slice in the awsxray exporter so that it is possible to set them using the OTEL_RESOURCE_ATTRIBUTES environment variable.

This is a major source of pain among users since it is not possible to set slice resource attributes using OTEL_RESOURCE_ATTRIBUTES open-telemetry/opentelemetry-specification#2857

Signed-off-by: Raphael Silva <rapphil@gmail.com>
Co-authored-by: William Armiros <54150514+willarmiros@users.noreply.github.com>
  • Loading branch information
rapphil and willarmiros authored Jan 12, 2023
1 parent 6367a68 commit 78bf8a0
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 3 deletions.
18 changes: 18 additions & 0 deletions .chloggen/awsxrayexporter-string-attrs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 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: >
Add support to string resource attributes of type slice so that it is possible to set those resource attributes using
the `OTEL_RESOURCE_ATTRIBUTES` environment variable. Strings are converted to string slices of size 1.
# One or more tracking issues related to the change
issues: [17503]

# (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:
18 changes: 17 additions & 1 deletion exporter/awsxrayexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,23 @@ comparable AWS X-Ray Daemon configuration values.
| `role_arn` | IAM role to upload segments to a different account. | |
| `indexed_attributes` | List of attribute names to be converted to X-Ray annotations. | |
| `index_all_attributes` | Enable or disable conversion of all OpenTelemetry attributes to X-Ray annotations. | false |
| `aws_log_groups` | List of log group names for cloud watch. | |
| `aws_log_groups` | List of log group names for CloudWatch. | [] |

## Traces and logs correlation

AWS X-Ray can be integrated with CloudWatch Logs to correlate traces with logs. For this integration to work, the X-Ray
segments must have the AWS Property `cloudwatch_logs` set. This property is set using the AWS X-Ray exporter with the
following values that are evaluated in this order:

1. `aws.log.group.arns` resource attribute.
2. `aws.log.group.names` resource attribute.
3. `aws_log_groups` configuration property.

In the case of multiple values are defined, the value with higher precedence will be used to set the `cloudwatch_logs` AWS Property.

`aws.log.group.arns` and `aws.log.group.names` are slice resource attributes that can be set programmatically.
Alternatively those resource attributes can be set using the [`OTEL_RESOURCE_ATTRIBUTES` environment variable](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable). In this case only a single log group/log group arn can
be provided as a string rather than a slice.

## AWS Credential Configuration

Expand Down
22 changes: 20 additions & 2 deletions exporter/awsxrayexporter/internal/translator/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ func makeAws(attributes map[string]pcommon.Value, resource pcommon.Resource, log
case conventions.AttributeAWSECSLaunchtype:
launchType = value.Str()
case conventions.AttributeAWSLogGroupNames:
logGroups = value.Slice()
logGroups = normalizeToSlice(value)
case conventions.AttributeAWSLogGroupARNs:
logGroupArns = value.Slice()
logGroupArns = normalizeToSlice(value)
}
return true
})
Expand Down Expand Up @@ -268,6 +268,24 @@ func makeAws(attributes map[string]pcommon.Value, resource pcommon.Resource, log
return filtered, awsData
}

// Normalize value to slice.
// 1. String values are converted to a slice of size 1 so that we can also handle resource
// attributes that are set using the OTEL_RESOURCE_ATTRIBUTES
// 2. Slices are kept as they are
// 3. Other types will result in a empty slice so that we avoid panic.
func normalizeToSlice(v pcommon.Value) pcommon.Slice {
switch v.Type() {
case pcommon.ValueTypeStr:
s := pcommon.NewSlice()
s.AppendEmpty().SetStr(v.Str())
return s
case pcommon.ValueTypeSlice:
return v.Slice()
default:
return pcommon.NewSlice()
}
}

// Given an array of log group ARNs, create a corresponding amount of LogGroupMetadata objects with log_group and arn
// populated, or given an array of just log group names, create the LogGroupMetadata objects with arn omitted
func getLogGroupMetadata(logGroups pcommon.Slice, isArn bool) []awsxray.LogGroupMetadata {
Expand Down
51 changes: 51 additions & 0 deletions exporter/awsxrayexporter/internal/translator/aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,57 @@ func TestLogGroupsFromArns(t *testing.T) {
assert.Contains(t, awsData.CWLogs, cwl2)
}

// Simulate Log groups being set using OTEL_RESOURCE_ATTRIBUTES
func TestLogGroupsFromStringResourceAttribute(t *testing.T) {
cwl1 := awsxray.LogGroupMetadata{
LogGroup: awsxray.String("group1"),
}

attributes := make(map[string]pcommon.Value)
resource := pcommon.NewResource()
resource.Attributes().PutStr(conventions.AttributeAWSLogGroupNames, "group1")

filtered, awsData := makeAws(attributes, resource, nil)

assert.NotNil(t, filtered)
assert.NotNil(t, awsData)
assert.Equal(t, 1, len(awsData.CWLogs))
assert.Contains(t, awsData.CWLogs, cwl1)
}

func TestLogGroupsInvalidType(t *testing.T) {
attributes := make(map[string]pcommon.Value)
resource := pcommon.NewResource()
resource.Attributes().PutInt(conventions.AttributeAWSLogGroupNames, 1)

filtered, awsData := makeAws(attributes, resource, nil)

assert.NotNil(t, filtered)
assert.NotNil(t, awsData)
assert.Equal(t, 0, len(awsData.CWLogs))
}

// Simulate Log groups arns being set using OTEL_RESOURCE_ATTRIBUTES
func TestLogGroupsArnsFromStringResourceAttributes(t *testing.T) {
group1 := "arn:aws:logs:us-east-1:123456789123:log-group:group1"

cwl1 := awsxray.LogGroupMetadata{
LogGroup: awsxray.String("group1"),
Arn: awsxray.String(group1),
}

attributes := make(map[string]pcommon.Value)
resource := pcommon.NewResource()
resource.Attributes().PutStr(conventions.AttributeAWSLogGroupARNs, group1)

filtered, awsData := makeAws(attributes, resource, nil)

assert.NotNil(t, filtered)
assert.NotNil(t, awsData)
assert.Equal(t, 1, len(awsData.CWLogs))
assert.Contains(t, awsData.CWLogs, cwl1)
}

func TestLogGroupsFromConfig(t *testing.T) {
cwl1 := awsxray.LogGroupMetadata{
LogGroup: awsxray.String("logGroup1"),
Expand Down

0 comments on commit 78bf8a0

Please sign in to comment.