From da405ec48fcde8610a68624da303bda4f0e88aa1 Mon Sep 17 00:00:00 2001 From: Jeffrey Chien Date: Tue, 9 Apr 2024 12:27:55 -0400 Subject: [PATCH] Set cloudwatch logs metadata in attributes. (#188) --- .../internal/translator/addtoattrs.go | 12 ++ .../internal/translator/aws.go | 10 +- .../internal/translator/aws_test.go | 119 ++++++++++++++++++ 3 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 receiver/awsxrayreceiver/internal/translator/aws_test.go diff --git a/receiver/awsxrayreceiver/internal/translator/addtoattrs.go b/receiver/awsxrayreceiver/internal/translator/addtoattrs.go index fd53a0bd74f8..c419f60a839a 100644 --- a/receiver/awsxrayreceiver/internal/translator/addtoattrs.go +++ b/receiver/awsxrayreceiver/internal/translator/addtoattrs.go @@ -22,3 +22,15 @@ func addInt64(val *int64, attrKey string, attrs pcommon.Map) { attrs.PutInt(attrKey, *val) } } + +func addStringSlice(val *string, attrKey string, attrs pcommon.Map) { + if val != nil { + var slice pcommon.Slice + if attrVal, ok := attrs.Get(attrKey); ok && attrVal.Type() == pcommon.ValueTypeSlice { + slice = attrVal.Slice() + } else { + slice = attrs.PutEmptySlice(attrKey) + } + slice.AppendEmpty().SetStr(*val) + } +} diff --git a/receiver/awsxrayreceiver/internal/translator/aws.go b/receiver/awsxrayreceiver/internal/translator/aws.go index 41ad8f1952dd..c7b65d765d6a 100644 --- a/receiver/awsxrayreceiver/internal/translator/aws.go +++ b/receiver/awsxrayreceiver/internal/translator/aws.go @@ -25,7 +25,14 @@ func addAWSToResource(aws *awsxray.AWSData, attrs pcommon.Map) { addString(aws.AccountID, conventions.AttributeCloudAccountID, attrs) // based on https://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html#api-segmentdocuments-aws - // it's possible to have all ec2, ecs and beanstalk fields at the same time. + // it's possible to have all cloudwatch_logs, ec2, ecs and beanstalk fields at the same time. + if cwl := aws.CWLogs; cwl != nil { + for _, logGroupMetaData := range cwl { + addStringSlice(logGroupMetaData.Arn, conventions.AttributeAWSLogGroupARNs, attrs) + addStringSlice(logGroupMetaData.LogGroup, conventions.AttributeAWSLogGroupNames, attrs) + } + } + if ec2 := aws.EC2; ec2 != nil { addString(ec2.AvailabilityZone, conventions.AttributeCloudAvailabilityZone, attrs) addString(ec2.InstanceID, conventions.AttributeHostID, attrs) @@ -51,7 +58,6 @@ func addAWSToResource(aws *awsxray.AWSData, attrs pcommon.Map) { addString(eks.ContainerID, conventions.AttributeContainerID, attrs) addString(eks.ClusterName, conventions.AttributeK8SClusterName, attrs) addString(eks.Pod, conventions.AttributeK8SPodName, attrs) - } } diff --git a/receiver/awsxrayreceiver/internal/translator/aws_test.go b/receiver/awsxrayreceiver/internal/translator/aws_test.go new file mode 100644 index 000000000000..f72b83012329 --- /dev/null +++ b/receiver/awsxrayreceiver/internal/translator/aws_test.go @@ -0,0 +1,119 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package translator + +import ( + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/pcommon" + conventions "go.opentelemetry.io/collector/semconv/v1.6.1" + + awsxray "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/xray" +) + +func TestAddAWSToResource(t *testing.T) { + testCases := map[string]struct { + input *awsxray.AWSData + want map[string]any + }{ + "WithNil": { + want: map[string]any{ + conventions.AttributeCloudProvider: "unknown", + }, + }, + "WithCloudWatchLogs": { + input: &awsxray.AWSData{ + CWLogs: []awsxray.LogGroupMetadata{ + { + LogGroup: aws.String(""), + Arn: aws.String("arn:aws:logs:::log-group::*"), + }, + { + LogGroup: aws.String(""), + Arn: aws.String("arn:aws:logs:::log-group::*"), + }, + }, + }, + want: map[string]any{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderAWS, + conventions.AttributeAWSLogGroupARNs: []any{ + "arn:aws:logs:::log-group::*", + "arn:aws:logs:::log-group::*", + }, + conventions.AttributeAWSLogGroupNames: []any{"", ""}, + }, + }, + "WithEC2": { + input: &awsxray.AWSData{ + EC2: &awsxray.EC2Metadata{ + InstanceID: aws.String(""), + AvailabilityZone: aws.String(""), + InstanceSize: aws.String(""), + AmiID: aws.String(""), + }, + }, + want: map[string]any{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderAWS, + conventions.AttributeCloudAvailabilityZone: "", + conventions.AttributeHostID: "", + conventions.AttributeHostType: "", + conventions.AttributeHostImageID: "", + }, + }, + "WithECS": { + input: &awsxray.AWSData{ + ECS: &awsxray.ECSMetadata{ + ContainerName: aws.String(""), + ContainerID: aws.String(""), + AvailabilityZone: aws.String(""), + }, + }, + want: map[string]any{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderAWS, + conventions.AttributeCloudAvailabilityZone: "", + conventions.AttributeContainerName: "", + conventions.AttributeContainerID: "", + }, + }, + "WithEKS": { + input: &awsxray.AWSData{ + EKS: &awsxray.EKSMetadata{ + ClusterName: aws.String(""), + Pod: aws.String(""), + ContainerID: aws.String(""), + }, + }, + want: map[string]any{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderAWS, + conventions.AttributeK8SPodName: "", + conventions.AttributeK8SClusterName: "", + conventions.AttributeContainerID: "", + }, + }, + "WithBeanstalk": { + input: &awsxray.AWSData{ + Beanstalk: &awsxray.BeanstalkMetadata{ + Environment: aws.String(""), + VersionLabel: aws.String(""), + DeploymentID: aws.Int64(1), + }, + }, + want: map[string]any{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderAWS, + conventions.AttributeServiceNamespace: "", + conventions.AttributeServiceInstanceID: "1", + conventions.AttributeServiceVersion: "", + }, + }, + } + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + attrs := pcommon.NewMap() + addAWSToResource(testCase.input, attrs) + assert.Equal(t, testCase.want, attrs.AsRaw()) + }) + } +}