From 78bf8a04e8707adcd5da3e03cd0dad575c339c59 Mon Sep 17 00:00:00 2001 From: Raphael Philipe Mendes da Silva Date: Thu, 12 Jan 2023 14:07:39 -0800 Subject: [PATCH] [exporter/awsxrayexporter]: Add support to string resource attributes (#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 Co-authored-by: William Armiros <54150514+willarmiros@users.noreply.github.com> --- .chloggen/awsxrayexporter-string-attrs.yaml | 18 +++++++ exporter/awsxrayexporter/README.md | 18 ++++++- .../internal/translator/aws.go | 22 +++++++- .../internal/translator/aws_test.go | 51 +++++++++++++++++++ 4 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 .chloggen/awsxrayexporter-string-attrs.yaml diff --git a/.chloggen/awsxrayexporter-string-attrs.yaml b/.chloggen/awsxrayexporter-string-attrs.yaml new file mode 100644 index 000000000000..e31309b53a1f --- /dev/null +++ b/.chloggen/awsxrayexporter-string-attrs.yaml @@ -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: diff --git a/exporter/awsxrayexporter/README.md b/exporter/awsxrayexporter/README.md index d75c02fc055d..c53b403f9a10 100644 --- a/exporter/awsxrayexporter/README.md +++ b/exporter/awsxrayexporter/README.md @@ -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 diff --git a/exporter/awsxrayexporter/internal/translator/aws.go b/exporter/awsxrayexporter/internal/translator/aws.go index a4f82c82c6e3..4946805f3765 100644 --- a/exporter/awsxrayexporter/internal/translator/aws.go +++ b/exporter/awsxrayexporter/internal/translator/aws.go @@ -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 }) @@ -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 { diff --git a/exporter/awsxrayexporter/internal/translator/aws_test.go b/exporter/awsxrayexporter/internal/translator/aws_test.go index 5e2bb22af9b3..34f3d2e46c46 100644 --- a/exporter/awsxrayexporter/internal/translator/aws_test.go +++ b/exporter/awsxrayexporter/internal/translator/aws_test.go @@ -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"),