diff --git a/.chloggen/resource-detection-processor.yaml b/.chloggen/resource-detection-processor.yaml new file mode 100644 index 000000000000..0bc1d9d7e98e --- /dev/null +++ b/.chloggen/resource-detection-processor.yaml @@ -0,0 +1,48 @@ +# Use this changelog template to create an entry for release notes. +# If your change doesn't affect end users, such as a test fix or a tooling change, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. + +# 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: resourcedetectionprocessor + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Adds a way to configure the list of added resource attributes by the processor + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [21482] + +# (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: | + Users can now configure what resource attributes are gathered by specific detectors. + Example configuration: + + ``` + resourcedetection: + detectors: [system, ec2] + system: + resource_attributes: + host.name: + enabled: true + host.id: + enabled: false + ec2: + resource_attributes: + host.name: + enabled: false + host.id: + enabled: true + ``` + + For example, this config makes `host.name` being set by `system` detector, and `host.id` by `ec2` detector. + Moreover: + - Existing behavior remains unaffected as all attributes are currently enabled by default. + - The default attributes 'enabled' values are defined in `metadata.yaml`. + - Future releases will introduce changes to resource_attributes `enabled` values. + - Users can tailor resource detection process to their needs and environment. + + diff --git a/processor/resourcedetectionprocessor/README.md b/processor/resourcedetectionprocessor/README.md index 2d0379092390..5f7eafbc86e2 100644 --- a/processor/resourcedetectionprocessor/README.md +++ b/processor/resourcedetectionprocessor/README.md @@ -454,10 +454,57 @@ See: [TLS Configuration Settings](https://github.com/open-telemetry/opentelemetr detectors: [ ] # determines if existing resource attributes should be overridden or preserved, defaults to true override: -# When included, only attributes in the list will be appened. Applies to all detectors. +# [DEPRECATED] When included, only attributes in the list will be appended. Applies to all detectors. attributes: [ ] ``` +Moreover, you have the ability to specify which detector should collect each attribute with `resource_attributes` option. An example of such a configuration is: + +```yaml +resourcedetection: + detectors: [system, ec2] + system: + resource_attributes: + host.name: + enabled: true + host.id: + enabled: false + ec2: + resource_attributes: + host.name: + enabled: false + host.id: + enabled: true +``` + +### Migration from attributes to resource_attributes + +The `attributes` option is deprecated and will be removed soon, from now on you should enable/disable attributes through `resource_attributes`. +For example, this config: + +```yaml +resourcedetection: + detectors: [system] + attributes: ['host.name', 'host.id'] +``` + +can be replaced with: + +```yaml +resourcedetection: + detectors: [system] + system: + resource_attributes: + host.name: + enabled: true + host.id: + enabled: true + os.type: + enabled: false +``` + +NOTE: Currently all attributes are enabled by default for backwards compatibility purposes, but it will change in the future. + ## Ordering Note that if multiple detectors are inserting the same attribute name, the first detector to insert wins. For example if you had `detectors: [eks, ec2]` then `cloud.platform` will be `aws_eks` instead of `ec2`. The below ordering is recommended. diff --git a/processor/resourcedetectionprocessor/config.go b/processor/resourcedetectionprocessor/config.go index 95af2d696f1d..6d667edeb455 100644 --- a/processor/resourcedetectionprocessor/config.go +++ b/processor/resourcedetectionprocessor/config.go @@ -8,7 +8,16 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ec2" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ecs" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/eks" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/aks" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/consul" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/docker" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openshift" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system" ) @@ -28,7 +37,8 @@ type Config struct { // Timeout default is 5s confighttp.HTTPClientSettings `mapstructure:",squash"` // Attributes is an allowlist of attributes to add. - // If a supplied attribute is not a valid atrtibute of a supplied detector it will be ignored. + // If a supplied attribute is not a valid attribute of a supplied detector it will be ignored. + // Deprecated: Please use detector's resource_attributes config instead Attributes []string `mapstructure:"attributes"` } @@ -37,9 +47,36 @@ type DetectorConfig struct { // EC2Config contains user-specified configurations for the EC2 detector EC2Config ec2.Config `mapstructure:"ec2"` + // ECSConfig contains user-specified configurations for the ECS detector + ECSConfig ecs.Config `mapstructure:"ecs"` + + // EKSConfig contains user-specified configurations for the EKS detector + EKSConfig eks.Config `mapstructure:"eks"` + + // Elasticbeanstalk contains user-specified configurations for the elasticbeanstalk detector + ElasticbeanstalkConfig elasticbeanstalk.Config `mapstructure:"elasticbeanstalk"` + + // Lambda contains user-specified configurations for the lambda detector + LambdaConfig lambda.Config `mapstructure:"lambda"` + + // Azure contains user-specified configurations for the azure detector + AzureConfig azure.Config `mapstructure:"azure"` + + // Aks contains user-specified configurations for the aks detector + AksConfig aks.Config `mapstructure:"aks"` + // ConsulConfig contains user-specified configurations for the Consul detector ConsulConfig consul.Config `mapstructure:"consul"` + // DockerConfig contains user-specified configurations for the docker detector + DockerConfig docker.Config `mapstructure:"docker"` + + // GcpConfig contains user-specified configurations for the gcp detector + GcpConfig gcp.Config `mapstructure:"gcp"` + + // HerokuConfig contains user-specified configurations for the heroku detector + HerokuConfig heroku.Config `mapstructure:"heroku"` + // SystemConfig contains user-specified configurations for the System detector SystemConfig system.Config `mapstructure:"system"` @@ -47,12 +84,46 @@ type DetectorConfig struct { OpenShiftConfig openshift.Config `mapstructure:"openshift"` } +func detectorCreateDefaultConfig() DetectorConfig { + return DetectorConfig{ + EC2Config: ec2.CreateDefaultConfig(), + ECSConfig: ecs.CreateDefaultConfig(), + EKSConfig: eks.CreateDefaultConfig(), + ElasticbeanstalkConfig: elasticbeanstalk.CreateDefaultConfig(), + LambdaConfig: lambda.CreateDefaultConfig(), + AzureConfig: azure.CreateDefaultConfig(), + AksConfig: aks.CreateDefaultConfig(), + ConsulConfig: consul.CreateDefaultConfig(), + DockerConfig: docker.CreateDefaultConfig(), + GcpConfig: gcp.CreateDefaultConfig(), + HerokuConfig: heroku.CreateDefaultConfig(), + SystemConfig: system.CreateDefaultConfig(), + OpenShiftConfig: openshift.CreateDefaultConfig(), + } +} + func (d *DetectorConfig) GetConfigFromType(detectorType internal.DetectorType) internal.DetectorConfig { switch detectorType { case ec2.TypeStr: return d.EC2Config + case ecs.TypeStr: + return d.ECSConfig + case eks.TypeStr: + return d.EKSConfig + case elasticbeanstalk.TypeStr: + return d.ElasticbeanstalkConfig + case lambda.TypeStr: + return d.LambdaConfig + case azure.TypeStr: + return d.AzureConfig case consul.TypeStr: return d.ConsulConfig + case docker.TypeStr: + return d.DockerConfig + case gcp.TypeStr: + return d.GcpConfig + case heroku.TypeStr: + return d.HerokuConfig case system.TypeStr: return d.SystemConfig case openshift.TypeStr: diff --git a/processor/resourcedetectionprocessor/config_test.go b/processor/resourcedetectionprocessor/config_test.go index 2a52d6042439..b1b8c97e2bcb 100644 --- a/processor/resourcedetectionprocessor/config_test.go +++ b/processor/resourcedetectionprocessor/config_test.go @@ -29,6 +29,37 @@ func TestLoadConfig(t *testing.T) { cfg := confighttp.NewDefaultHTTPClientSettings() cfg.Timeout = 2 * time.Second + openshiftConfig := detectorCreateDefaultConfig() + openshiftConfig.OpenShiftConfig = openshift.Config{ + Address: "127.0.0.1:4444", + Token: "some_token", + TLSSettings: configtls.TLSClientSetting{ + Insecure: true, + }, + ResourceAttributes: openshift.CreateDefaultConfig().ResourceAttributes, + } + + ec2Config := detectorCreateDefaultConfig() + ec2Config.EC2Config = ec2.Config{ + Tags: []string{"^tag1$", "^tag2$"}, + ResourceAttributes: ec2.CreateDefaultConfig().ResourceAttributes, + } + + systemConfig := detectorCreateDefaultConfig() + systemConfig.SystemConfig = system.Config{ + HostnameSources: []string{"os"}, + ResourceAttributes: system.CreateDefaultConfig().ResourceAttributes, + } + + resourceAttributesConfig := detectorCreateDefaultConfig() + ec2ResourceAttributesConfig := ec2.CreateDefaultConfig() + ec2ResourceAttributesConfig.ResourceAttributes.HostName.Enabled = false + ec2ResourceAttributesConfig.ResourceAttributes.HostID.Enabled = false + ec2ResourceAttributesConfig.ResourceAttributes.HostType.Enabled = false + systemResourceAttributesConfig := system.CreateDefaultConfig() + systemResourceAttributesConfig.ResourceAttributes.OsType.Enabled = false + resourceAttributesConfig.EC2Config = ec2ResourceAttributesConfig + resourceAttributesConfig.SystemConfig = systemResourceAttributesConfig tests := []struct { id component.ID @@ -38,16 +69,8 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "openshift"), expected: &Config{ - Detectors: []string{"openshift"}, - DetectorConfig: DetectorConfig{ - OpenShiftConfig: openshift.Config{ - Address: "127.0.0.1:4444", - Token: "some_token", - TLSSettings: configtls.TLSClientSetting{ - Insecure: true, - }, - }, - }, + Detectors: []string{"openshift"}, + DetectorConfig: openshiftConfig, HTTPClientSettings: cfg, Override: false, }, @@ -58,17 +81,14 @@ func TestLoadConfig(t *testing.T) { Detectors: []string{"env", "gcp"}, HTTPClientSettings: cfg, Override: false, + DetectorConfig: detectorCreateDefaultConfig(), }, }, { id: component.NewIDWithName(metadata.Type, "ec2"), expected: &Config{ - Detectors: []string{"env", "ec2"}, - DetectorConfig: DetectorConfig{ - EC2Config: ec2.Config{ - Tags: []string{"^tag1$", "^tag2$"}, - }, - }, + Detectors: []string{"env", "ec2"}, + DetectorConfig: ec2Config, HTTPClientSettings: cfg, Override: false, }, @@ -76,12 +96,8 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "system"), expected: &Config{ - Detectors: []string{"env", "system"}, - DetectorConfig: DetectorConfig{ - SystemConfig: system.Config{ - HostnameSources: []string{"os"}, - }, - }, + Detectors: []string{"env", "system"}, + DetectorConfig: systemConfig, HTTPClientSettings: cfg, Override: false, Attributes: []string{"a", "b"}, @@ -93,6 +109,7 @@ func TestLoadConfig(t *testing.T) { Detectors: []string{"env", "heroku"}, HTTPClientSettings: cfg, Override: false, + DetectorConfig: detectorCreateDefaultConfig(), }, }, { @@ -101,6 +118,16 @@ func TestLoadConfig(t *testing.T) { Detectors: []string{"env", "lambda"}, HTTPClientSettings: cfg, Override: false, + DetectorConfig: detectorCreateDefaultConfig(), + }, + }, + { + id: component.NewIDWithName(metadata.Type, "resourceattributes"), + expected: &Config{ + Detectors: []string{"system", "ec2"}, + HTTPClientSettings: cfg, + Override: false, + DetectorConfig: resourceAttributesConfig, }, }, { @@ -131,6 +158,13 @@ func TestLoadConfig(t *testing.T) { } func TestGetConfigFromType(t *testing.T) { + herokuDetectorConfig := DetectorConfig{HerokuConfig: heroku.CreateDefaultConfig()} + lambdaDetectorConfig := DetectorConfig{LambdaConfig: lambda.CreateDefaultConfig()} + ec2DetectorConfig := DetectorConfig{ + EC2Config: ec2.Config{ + Tags: []string{"tag1", "tag2"}, + }, + } tests := []struct { name string detectorType internal.DetectorType @@ -138,26 +172,16 @@ func TestGetConfigFromType(t *testing.T) { expectedConfig internal.DetectorConfig }{ { - name: "Get EC2 Config", - detectorType: ec2.TypeStr, - inputDetectorConfig: DetectorConfig{ - EC2Config: ec2.Config{ - Tags: []string{"tag1", "tag2"}, - }, - }, - expectedConfig: ec2.Config{ - Tags: []string{"tag1", "tag2"}, - }, + name: "Get EC2 Config", + detectorType: ec2.TypeStr, + inputDetectorConfig: ec2DetectorConfig, + expectedConfig: ec2DetectorConfig.EC2Config, }, { - name: "Get Nil Config", - detectorType: internal.DetectorType("invalid input"), - inputDetectorConfig: DetectorConfig{ - EC2Config: ec2.Config{ - Tags: []string{"tag1", "tag2"}, - }, - }, - expectedConfig: nil, + name: "Get Nil Config", + detectorType: internal.DetectorType("invalid input"), + inputDetectorConfig: ec2DetectorConfig, + expectedConfig: nil, }, { name: "Get System Config", @@ -174,14 +198,14 @@ func TestGetConfigFromType(t *testing.T) { { name: "Get Heroku Config", detectorType: heroku.TypeStr, - inputDetectorConfig: DetectorConfig{}, - expectedConfig: nil, + inputDetectorConfig: herokuDetectorConfig, + expectedConfig: herokuDetectorConfig.HerokuConfig, }, { name: "Get AWS Lambda Config", detectorType: lambda.TypeStr, - inputDetectorConfig: DetectorConfig{}, - expectedConfig: nil, + inputDetectorConfig: lambdaDetectorConfig, + expectedConfig: lambdaDetectorConfig.LambdaConfig, }, } diff --git a/processor/resourcedetectionprocessor/doc.go b/processor/resourcedetectionprocessor/doc.go index c87c57465857..b720c6a38ab3 100644 --- a/processor/resourcedetectionprocessor/doc.go +++ b/processor/resourcedetectionprocessor/doc.go @@ -2,6 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 //go:generate mdatagen metadata.yaml +//go:generate mdatagen internal/aws/ec2/metadata.yaml +//go:generate mdatagen internal/aws/ecs/metadata.yaml +//go:generate mdatagen internal/aws/eks/metadata.yaml +//go:generate mdatagen internal/aws/elasticbeanstalk/metadata.yaml +//go:generate mdatagen internal/aws/lambda/metadata.yaml +//go:generate mdatagen internal/azure/aks/metadata.yaml +//go:generate mdatagen internal/azure/metadata.yaml +//go:generate mdatagen internal/consul/metadata.yaml +//go:generate mdatagen internal/docker/metadata.yaml +//go:generate mdatagen internal/gcp/metadata.yaml +//go:generate mdatagen internal/heroku/metadata.yaml +//go:generate mdatagen internal/openshift/metadata.yaml +//go:generate mdatagen internal/system/metadata.yaml // package resourcedetectionprocessor implements a processor // which can be used to detect resource information from the host, diff --git a/processor/resourcedetectionprocessor/factory.go b/processor/resourcedetectionprocessor/factory.go index a27f26d9f4fd..df6d809e186b 100644 --- a/processor/resourcedetectionprocessor/factory.go +++ b/processor/resourcedetectionprocessor/factory.go @@ -87,6 +87,7 @@ func createDefaultConfig() component.Config { HTTPClientSettings: defaultHTTPClientSettings(), Override: true, Attributes: nil, + DetectorConfig: detectorCreateDefaultConfig(), // TODO: Once issue(https://github.com/open-telemetry/opentelemetry-collector/issues/4001) gets resolved, // Set the default value of 'hostname_source' here instead of 'system' detector } @@ -166,7 +167,9 @@ func (f *factory) getResourceDetectionProcessor( cfg component.Config, ) (*resourceDetectionProcessor, error) { oCfg := cfg.(*Config) - + if oCfg.Attributes != nil { + params.Logger.Warn("You are using deprecated `attributes` option that will be removed soon; use `resource_attributes` instead, details on configuration: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/resourcedetectionprocessor#migration-from-attributes-to-resource_attributes") + } provider, err := f.getResourceProvider(params, oCfg.HTTPClientSettings.Timeout, oCfg.Detectors, oCfg.DetectorConfig, oCfg.Attributes) if err != nil { return nil, err diff --git a/processor/resourcedetectionprocessor/go.mod b/processor/resourcedetectionprocessor/go.mod index 9603f393bda0..02af9173187c 100644 --- a/processor/resourcedetectionprocessor/go.mod +++ b/processor/resourcedetectionprocessor/go.mod @@ -6,6 +6,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.15.0 github.com/aws/aws-sdk-go v1.44.287 + github.com/google/go-cmp v0.5.9 github.com/hashicorp/consul/api v1.21.0 github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/ecsutil v0.80.0 github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders v0.80.0 @@ -50,7 +51,6 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/config.go b/processor/resourcedetectionprocessor/internal/aws/ec2/config.go index 74190c5ff458..16c7c06ddb9f 100644 --- a/processor/resourcedetectionprocessor/internal/aws/ec2/config.go +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/config.go @@ -3,9 +3,21 @@ package ec2 // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ec2" +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata" +) + // Config defines user-specified configurations unique to the EC2 detector type Config struct { // Tags is a list of regex's to match ec2 instance tag keys that users want // to add as resource attributes to processed data - Tags []string `mapstructure:"tags"` + Tags []string `mapstructure:"tags"` + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + Tags: []string{}, + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } } diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go index af4b56bff489..c3dc2c454bb0 100644 --- a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go @@ -20,6 +20,7 @@ import ( ec2provider "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/aws/ec2" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata" ) const ( @@ -31,9 +32,10 @@ const ( var _ internal.Detector = (*Detector)(nil) type Detector struct { - metadataProvider ec2provider.Provider - tagKeyRegexes []*regexp.Regexp - logger *zap.Logger + metadataProvider ec2provider.Provider + tagKeyRegexes []*regexp.Regexp + logger *zap.Logger + resourceAttributes metadata.ResourceAttributesConfig } func NewDetector(set processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { @@ -46,10 +48,12 @@ func NewDetector(set processor.CreateSettings, dcfg internal.DetectorConfig) (in if err != nil { return nil, err } + return &Detector{ - metadataProvider: ec2provider.NewProvider(sess), - tagKeyRegexes: tagKeyRegexes, - logger: set.Logger, + metadataProvider: ec2provider.NewProvider(sess), + tagKeyRegexes: tagKeyRegexes, + logger: set.Logger, + resourceAttributes: cfg.ResourceAttributes, }, nil } @@ -71,15 +75,33 @@ func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schem } attr := res.Attributes() - attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) - attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSEC2) - attr.PutStr(conventions.AttributeCloudRegion, meta.Region) - attr.PutStr(conventions.AttributeCloudAccountID, meta.AccountID) - attr.PutStr(conventions.AttributeCloudAvailabilityZone, meta.AvailabilityZone) - attr.PutStr(conventions.AttributeHostID, meta.InstanceID) - attr.PutStr(conventions.AttributeHostImageID, meta.ImageID) - attr.PutStr(conventions.AttributeHostType, meta.InstanceType) - attr.PutStr(conventions.AttributeHostName, hostname) + if d.resourceAttributes.CloudProvider.Enabled { + attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) + } + if d.resourceAttributes.CloudPlatform.Enabled { + attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSEC2) + } + if d.resourceAttributes.CloudRegion.Enabled { + attr.PutStr(conventions.AttributeCloudRegion, meta.Region) + } + if d.resourceAttributes.CloudAccountID.Enabled { + attr.PutStr(conventions.AttributeCloudAccountID, meta.AccountID) + } + if d.resourceAttributes.CloudAvailabilityZone.Enabled { + attr.PutStr(conventions.AttributeCloudAvailabilityZone, meta.AvailabilityZone) + } + if d.resourceAttributes.HostID.Enabled { + attr.PutStr(conventions.AttributeHostID, meta.InstanceID) + } + if d.resourceAttributes.HostImageID.Enabled { + attr.PutStr(conventions.AttributeHostImageID, meta.ImageID) + } + if d.resourceAttributes.HostType.Enabled { + attr.PutStr(conventions.AttributeHostType, meta.InstanceType) + } + if d.resourceAttributes.HostName.Enabled { + attr.PutStr(conventions.AttributeHostName, hostname) + } if len(d.tagKeyRegexes) != 0 { client := getHTTPClientSettings(ctx, d.logger) diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go index 82d4dada5a80..a857b11213c6 100644 --- a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go @@ -172,9 +172,11 @@ func TestDetector_Detect(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + resourceAttributes := CreateDefaultConfig().ResourceAttributes d := &Detector{ - metadataProvider: tt.fields.metadataProvider, - logger: zap.NewNop(), + metadataProvider: tt.fields.metadataProvider, + logger: zap.NewNop(), + resourceAttributes: resourceAttributes, } got, _, err := d.Detect(tt.args.ctx) diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/generated_config.go new file mode 100644 index 000000000000..64115c49f2ad --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/generated_config.go @@ -0,0 +1,53 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/ec2 resource attributes. +type ResourceAttributesConfig struct { + CloudAccountID ResourceAttributeConfig `mapstructure:"cloud.account.id"` + CloudAvailabilityZone ResourceAttributeConfig `mapstructure:"cloud.availability_zone"` + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` + HostID ResourceAttributeConfig `mapstructure:"host.id"` + HostImageID ResourceAttributeConfig `mapstructure:"host.image.id"` + HostName ResourceAttributeConfig `mapstructure:"host.name"` + HostType ResourceAttributeConfig `mapstructure:"host.type"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + CloudAccountID: ResourceAttributeConfig{ + Enabled: true, + }, + CloudAvailabilityZone: ResourceAttributeConfig{ + Enabled: true, + }, + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + HostID: ResourceAttributeConfig{ + Enabled: true, + }, + HostImageID: ResourceAttributeConfig{ + Enabled: true, + }, + HostName: ResourceAttributeConfig{ + Enabled: true, + }, + HostType: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..fb420f866679 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/generated_config_test.go @@ -0,0 +1,70 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + CloudAccountID: ResourceAttributeConfig{Enabled: true}, + CloudAvailabilityZone: ResourceAttributeConfig{Enabled: true}, + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + CloudRegion: ResourceAttributeConfig{Enabled: true}, + HostID: ResourceAttributeConfig{Enabled: true}, + HostImageID: ResourceAttributeConfig{Enabled: true}, + HostName: ResourceAttributeConfig{Enabled: true}, + HostType: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + CloudAccountID: ResourceAttributeConfig{Enabled: false}, + CloudAvailabilityZone: ResourceAttributeConfig{Enabled: false}, + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + CloudRegion: ResourceAttributeConfig{Enabled: false}, + HostID: ResourceAttributeConfig{Enabled: false}, + HostImageID: ResourceAttributeConfig{Enabled: false}, + HostName: ResourceAttributeConfig{Enabled: false}, + HostType: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..0a6c359bf20b --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/internal/metadata/testdata/config.yaml @@ -0,0 +1,41 @@ +default: +all_set: + resource_attributes: + cloud.account.id: + enabled: true + cloud.availability_zone: + enabled: true + cloud.platform: + enabled: true + cloud.provider: + enabled: true + cloud.region: + enabled: true + host.id: + enabled: true + host.image.id: + enabled: true + host.name: + enabled: true + host.type: + enabled: true +none_set: + resource_attributes: + cloud.account.id: + enabled: false + cloud.availability_zone: + enabled: false + cloud.platform: + enabled: false + cloud.provider: + enabled: false + cloud.region: + enabled: false + host.id: + enabled: false + host.image.id: + enabled: false + host.name: + enabled: false + host.type: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/metadata.yaml b/processor/resourcedetectionprocessor/internal/aws/ec2/metadata.yaml new file mode 100644 index 000000000000..85bfa338b07f --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/metadata.yaml @@ -0,0 +1,39 @@ +type: resourcedetectionprocessor/ec2 + +resource_attributes: + host.name: + description: The hostname + type: string + enabled: true + host.id: + description: The host.id + type: string + enabled: true + cloud.provider: + description: The cloud provider + type: string + enabled: true + cloud.account.id: + description: The cloud account id + type: string + enabled: true + cloud.platform: + description: The cloud platform + type: string + enabled: true + cloud.region: + description: The cloud region + type: string + enabled: true + cloud.availability_zone: + description: The cloud availability zone + type: string + enabled: true + host.image.id: + description: The host image id + type: string + enabled: true + host.type: + description: The host id + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/aws/ecs/config.go b/processor/resourcedetectionprocessor/internal/aws/ecs/config.go new file mode 100644 index 000000000000..2db7453b9f15 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ecs/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package ecs // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ecs" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/ecs/ecs.go b/processor/resourcedetectionprocessor/internal/aws/ecs/ecs.go index 5f779e796cda..9ac534bcd6d9 100644 --- a/processor/resourcedetectionprocessor/internal/aws/ecs/ecs.go +++ b/processor/resourcedetectionprocessor/internal/aws/ecs/ecs.go @@ -17,6 +17,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/ecsutil" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/ecsutil/endpoints" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata" ) const ( @@ -27,10 +28,12 @@ const ( var _ internal.Detector = (*Detector)(nil) type Detector struct { - provider ecsutil.MetadataProvider + provider ecsutil.MetadataProvider + resourceAttributes metadata.ResourceAttributesConfig } -func NewDetector(params processor.CreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { +func NewDetector(params processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) provider, err := ecsutil.NewDetectedTaskMetadataProvider(params.TelemetrySettings) if err != nil { // Allow metadata provider to be created in incompatible environments and just have a noop Detect() @@ -40,7 +43,7 @@ func NewDetector(params processor.CreateSettings, _ internal.DetectorConfig) (in } return nil, fmt.Errorf("unable to create task metadata provider: %w", err) } - return &Detector{provider: provider}, nil + return &Detector{provider: provider, resourceAttributes: cfg.ResourceAttributes}, nil } // Detect records metadata retrieved from the ECS Task Metadata Endpoint (TMDE) as resource attributes @@ -60,36 +63,49 @@ func (d *Detector) Detect(context.Context) (resource pcommon.Resource, schemaURL } attr := res.Attributes() - attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) - attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSECS) - attr.PutStr(conventions.AttributeAWSECSTaskARN, tmdeResp.TaskARN) - attr.PutStr(conventions.AttributeAWSECSTaskFamily, tmdeResp.Family) - attr.PutStr(conventions.AttributeAWSECSTaskRevision, tmdeResp.Revision) + + if d.resourceAttributes.CloudProvider.Enabled { + attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) + } + if d.resourceAttributes.CloudPlatform.Enabled { + attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSECS) + } + if d.resourceAttributes.AwsEcsTaskArn.Enabled { + attr.PutStr(conventions.AttributeAWSECSTaskARN, tmdeResp.TaskARN) + } + if d.resourceAttributes.AwsEcsTaskFamily.Enabled { + attr.PutStr(conventions.AttributeAWSECSTaskFamily, tmdeResp.Family) + } + if d.resourceAttributes.AwsEcsTaskRevision.Enabled { + attr.PutStr(conventions.AttributeAWSECSTaskRevision, tmdeResp.Revision) + } region, account := parseRegionAndAccount(tmdeResp.TaskARN) - if account != "" { + if account != "" && d.resourceAttributes.CloudAccountID.Enabled { attr.PutStr(conventions.AttributeCloudAccountID, account) } - if region != "" { + if region != "" && d.resourceAttributes.CloudRegion.Enabled { attr.PutStr(conventions.AttributeCloudRegion, region) } - // TMDE returns the cluster short name or ARN, so we need to construct the ARN if necessary - attr.PutStr(conventions.AttributeAWSECSClusterARN, constructClusterArn(tmdeResp.Cluster, region, account)) + if d.resourceAttributes.AwsEcsClusterArn.Enabled { + // TMDE returns the cluster short name or ARN, so we need to construct the ARN if necessary + attr.PutStr(conventions.AttributeAWSECSClusterARN, constructClusterArn(tmdeResp.Cluster, region, account)) + } - // The Availability Zone is not available in all Fargate runtimes - if tmdeResp.AvailabilityZone != "" { + if tmdeResp.AvailabilityZone != "" && d.resourceAttributes.CloudAvailabilityZone.Enabled { attr.PutStr(conventions.AttributeCloudAvailabilityZone, tmdeResp.AvailabilityZone) } - // The launch type and log data attributes are only available in TMDE v4 - switch lt := strings.ToLower(tmdeResp.LaunchType); lt { - case "ec2": - attr.PutStr(conventions.AttributeAWSECSLaunchtype, "ec2") - - case "fargate": - attr.PutStr(conventions.AttributeAWSECSLaunchtype, "fargate") + if d.resourceAttributes.AwsEcsLaunchtype.Enabled { + // The launch type and log data attributes are only available in TMDE v4 + switch lt := strings.ToLower(tmdeResp.LaunchType); lt { + case "ec2": + attr.PutStr(conventions.AttributeAWSECSLaunchtype, "ec2") + case "fargate": + attr.PutStr(conventions.AttributeAWSECSLaunchtype, "fargate") + } } selfMetaData, err := d.provider.FetchContainerMetadata() @@ -98,7 +114,7 @@ func (d *Detector) Detect(context.Context) (resource pcommon.Resource, schemaURL return res, "", err } - addValidLogData(tmdeResp.Containers, selfMetaData, account, attr) + addValidLogData(tmdeResp.Containers, selfMetaData, account, attr, d.resourceAttributes) return res, conventions.SchemaURL, nil } @@ -127,7 +143,7 @@ func parseRegionAndAccount(taskARN string) (region string, account string) { // "init" containers which only run at startup then shutdown (as indicated by the "KnownStatus" attribute), // containers not using AWS Logs, and those without log group metadata to get the final lists of valid log data // See: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint-v4.html#task-metadata-endpoint-v4-response -func addValidLogData(containers []ecsutil.ContainerMetadata, self *ecsutil.ContainerMetadata, account string, dest pcommon.Map) { +func addValidLogData(containers []ecsutil.ContainerMetadata, self *ecsutil.ContainerMetadata, account string, dest pcommon.Map, resourceAttributes metadata.ResourceAttributesConfig) { initialized := false var logGroupNames pcommon.Slice var logGroupArns pcommon.Slice @@ -142,16 +158,32 @@ func addValidLogData(containers []ecsutil.ContainerMetadata, self *ecsutil.Conta self.DockerID != container.DockerID && logData != (ecsutil.LogOptions{}) { if !initialized { - logGroupNames = dest.PutEmptySlice(conventions.AttributeAWSLogGroupNames) - logGroupArns = dest.PutEmptySlice(conventions.AttributeAWSLogGroupARNs) - logStreamNames = dest.PutEmptySlice(conventions.AttributeAWSLogStreamNames) - logStreamArns = dest.PutEmptySlice(conventions.AttributeAWSLogStreamARNs) + if resourceAttributes.AwsLogGroupNames.Enabled { + logGroupNames = dest.PutEmptySlice(conventions.AttributeAWSLogGroupNames) + } + if resourceAttributes.AwsEcsTaskArn.Enabled { + logGroupArns = dest.PutEmptySlice(conventions.AttributeAWSLogGroupARNs) + } + if resourceAttributes.AwsLogStreamNames.Enabled { + logStreamNames = dest.PutEmptySlice(conventions.AttributeAWSLogStreamNames) + } + if resourceAttributes.AwsLogStreamArns.Enabled { + logStreamArns = dest.PutEmptySlice(conventions.AttributeAWSLogStreamARNs) + } initialized = true } - logGroupNames.AppendEmpty().SetStr(logData.LogGroup) - logGroupArns.AppendEmpty().SetStr(constructLogGroupArn(logData.Region, account, logData.LogGroup)) - logStreamNames.AppendEmpty().SetStr(logData.Stream) - logStreamArns.AppendEmpty().SetStr(constructLogStreamArn(logData.Region, account, logData.LogGroup, logData.Stream)) + if resourceAttributes.AwsLogGroupNames.Enabled { + logGroupNames.AppendEmpty().SetStr(logData.LogGroup) + } + if resourceAttributes.AwsEcsTaskArn.Enabled { + logGroupArns.AppendEmpty().SetStr(constructLogGroupArn(logData.Region, account, logData.LogGroup)) + } + if resourceAttributes.AwsLogStreamNames.Enabled { + logStreamNames.AppendEmpty().SetStr(logData.Stream) + } + if resourceAttributes.AwsLogStreamArns.Enabled { + logStreamArns.AppendEmpty().SetStr(constructLogStreamArn(logData.Region, account, logData.LogGroup, logData.Stream)) + } } } } diff --git a/processor/resourcedetectionprocessor/internal/aws/ecs/ecs_test.go b/processor/resourcedetectionprocessor/internal/aws/ecs/ecs_test.go index 4ae0dab9b412..0384f46bf582 100644 --- a/processor/resourcedetectionprocessor/internal/aws/ecs/ecs_test.go +++ b/processor/resourcedetectionprocessor/internal/aws/ecs/ecs_test.go @@ -13,6 +13,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/ecsutil" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/ecsutil/endpoints" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata" ) type mockMetaDataProvider struct { @@ -48,14 +49,14 @@ func (md *mockMetaDataProvider) FetchContainerMetadata() (*ecsutil.ContainerMeta func Test_ecsNewDetector(t *testing.T) { t.Setenv(endpoints.TaskMetadataEndpointV4EnvVar, "endpoint") - d, err := NewDetector(processortest.NewNopCreateSettings(), nil) + d, err := NewDetector(processortest.NewNopCreateSettings(), CreateDefaultConfig()) assert.NoError(t, err) assert.NotNil(t, d) } func Test_detectorReturnsIfNoEnvVars(t *testing.T) { - d, _ := NewDetector(processortest.NewNopCreateSettings(), nil) + d, _ := NewDetector(processortest.NewNopCreateSettings(), CreateDefaultConfig()) res, _, err := d.Detect(context.TODO()) assert.Nil(t, err) @@ -80,7 +81,23 @@ func Test_ecsFiltersInvalidContainers(t *testing.T) { containers := []ecsutil.ContainerMetadata{c1, c2, c3, c4} dest := pcommon.NewMap() - addValidLogData(containers, &c4, "123", dest) + resourceAttributes := metadata.ResourceAttributesConfig{ + AwsEcsClusterArn: metadata.ResourceAttributeConfig{Enabled: true}, + AwsEcsLaunchtype: metadata.ResourceAttributeConfig{Enabled: true}, + AwsEcsTaskArn: metadata.ResourceAttributeConfig{Enabled: true}, + AwsEcsTaskFamily: metadata.ResourceAttributeConfig{Enabled: true}, + AwsEcsTaskRevision: metadata.ResourceAttributeConfig{Enabled: true}, + AwsLogGroupArns: metadata.ResourceAttributeConfig{Enabled: true}, + AwsLogGroupNames: metadata.ResourceAttributeConfig{Enabled: true}, + AwsLogStreamArns: metadata.ResourceAttributeConfig{Enabled: true}, + AwsLogStreamNames: metadata.ResourceAttributeConfig{Enabled: true}, + CloudAccountID: metadata.ResourceAttributeConfig{Enabled: true}, + CloudAvailabilityZone: metadata.ResourceAttributeConfig{Enabled: true}, + CloudPlatform: metadata.ResourceAttributeConfig{Enabled: true}, + CloudProvider: metadata.ResourceAttributeConfig{Enabled: true}, + CloudRegion: metadata.ResourceAttributeConfig{Enabled: true}, + } + addValidLogData(containers, &c4, "123", dest, resourceAttributes) assert.Equal(t, 0, dest.Len()) } @@ -104,7 +121,8 @@ func Test_ecsDetectV4(t *testing.T) { attr.PutEmptySlice("aws.log.stream.names").AppendEmpty().SetStr("stream") attr.PutEmptySlice("aws.log.stream.arns").AppendEmpty().SetStr("arn:aws:logs:us-east-1:123456789123:log-group:group:log-stream:stream") - d := Detector{provider: &mockMetaDataProvider{isV4: true}} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + d := Detector{provider: &mockMetaDataProvider{isV4: true}, resourceAttributes: resourceAttributes} got, _, err := d.Detect(context.TODO()) assert.Nil(t, err) @@ -127,7 +145,8 @@ func Test_ecsDetectV3(t *testing.T) { attr.PutStr("cloud.availability_zone", "us-west-2a") attr.PutStr("cloud.account.id", "123456789123") - d := Detector{provider: &mockMetaDataProvider{isV4: false}} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + d := Detector{provider: &mockMetaDataProvider{isV4: false}, resourceAttributes: resourceAttributes} got, _, err := d.Detect(context.TODO()) assert.Nil(t, err) diff --git a/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/generated_config.go new file mode 100644 index 000000000000..dcf69faf3e3e --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/generated_config.go @@ -0,0 +1,73 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/ecs resource attributes. +type ResourceAttributesConfig struct { + AwsEcsClusterArn ResourceAttributeConfig `mapstructure:"aws.ecs.cluster.arn"` + AwsEcsLaunchtype ResourceAttributeConfig `mapstructure:"aws.ecs.launchtype"` + AwsEcsTaskArn ResourceAttributeConfig `mapstructure:"aws.ecs.task.arn"` + AwsEcsTaskFamily ResourceAttributeConfig `mapstructure:"aws.ecs.task.family"` + AwsEcsTaskRevision ResourceAttributeConfig `mapstructure:"aws.ecs.task.revision"` + AwsLogGroupArns ResourceAttributeConfig `mapstructure:"aws.log.group.arns"` + AwsLogGroupNames ResourceAttributeConfig `mapstructure:"aws.log.group.names"` + AwsLogStreamArns ResourceAttributeConfig `mapstructure:"aws.log.stream.arns"` + AwsLogStreamNames ResourceAttributeConfig `mapstructure:"aws.log.stream.names"` + CloudAccountID ResourceAttributeConfig `mapstructure:"cloud.account.id"` + CloudAvailabilityZone ResourceAttributeConfig `mapstructure:"cloud.availability_zone"` + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + AwsEcsClusterArn: ResourceAttributeConfig{ + Enabled: true, + }, + AwsEcsLaunchtype: ResourceAttributeConfig{ + Enabled: true, + }, + AwsEcsTaskArn: ResourceAttributeConfig{ + Enabled: true, + }, + AwsEcsTaskFamily: ResourceAttributeConfig{ + Enabled: true, + }, + AwsEcsTaskRevision: ResourceAttributeConfig{ + Enabled: true, + }, + AwsLogGroupArns: ResourceAttributeConfig{ + Enabled: true, + }, + AwsLogGroupNames: ResourceAttributeConfig{ + Enabled: true, + }, + AwsLogStreamArns: ResourceAttributeConfig{ + Enabled: true, + }, + AwsLogStreamNames: ResourceAttributeConfig{ + Enabled: true, + }, + CloudAccountID: ResourceAttributeConfig{ + Enabled: true, + }, + CloudAvailabilityZone: ResourceAttributeConfig{ + Enabled: true, + }, + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..fc734b19464b --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/generated_config_test.go @@ -0,0 +1,80 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + AwsEcsClusterArn: ResourceAttributeConfig{Enabled: true}, + AwsEcsLaunchtype: ResourceAttributeConfig{Enabled: true}, + AwsEcsTaskArn: ResourceAttributeConfig{Enabled: true}, + AwsEcsTaskFamily: ResourceAttributeConfig{Enabled: true}, + AwsEcsTaskRevision: ResourceAttributeConfig{Enabled: true}, + AwsLogGroupArns: ResourceAttributeConfig{Enabled: true}, + AwsLogGroupNames: ResourceAttributeConfig{Enabled: true}, + AwsLogStreamArns: ResourceAttributeConfig{Enabled: true}, + AwsLogStreamNames: ResourceAttributeConfig{Enabled: true}, + CloudAccountID: ResourceAttributeConfig{Enabled: true}, + CloudAvailabilityZone: ResourceAttributeConfig{Enabled: true}, + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + CloudRegion: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + AwsEcsClusterArn: ResourceAttributeConfig{Enabled: false}, + AwsEcsLaunchtype: ResourceAttributeConfig{Enabled: false}, + AwsEcsTaskArn: ResourceAttributeConfig{Enabled: false}, + AwsEcsTaskFamily: ResourceAttributeConfig{Enabled: false}, + AwsEcsTaskRevision: ResourceAttributeConfig{Enabled: false}, + AwsLogGroupArns: ResourceAttributeConfig{Enabled: false}, + AwsLogGroupNames: ResourceAttributeConfig{Enabled: false}, + AwsLogStreamArns: ResourceAttributeConfig{Enabled: false}, + AwsLogStreamNames: ResourceAttributeConfig{Enabled: false}, + CloudAccountID: ResourceAttributeConfig{Enabled: false}, + CloudAvailabilityZone: ResourceAttributeConfig{Enabled: false}, + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + CloudRegion: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..af6581590f21 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ecs/internal/metadata/testdata/config.yaml @@ -0,0 +1,61 @@ +default: +all_set: + resource_attributes: + aws.ecs.cluster.arn: + enabled: true + aws.ecs.launchtype: + enabled: true + aws.ecs.task.arn: + enabled: true + aws.ecs.task.family: + enabled: true + aws.ecs.task.revision: + enabled: true + aws.log.group.arns: + enabled: true + aws.log.group.names: + enabled: true + aws.log.stream.arns: + enabled: true + aws.log.stream.names: + enabled: true + cloud.account.id: + enabled: true + cloud.availability_zone: + enabled: true + cloud.platform: + enabled: true + cloud.provider: + enabled: true + cloud.region: + enabled: true +none_set: + resource_attributes: + aws.ecs.cluster.arn: + enabled: false + aws.ecs.launchtype: + enabled: false + aws.ecs.task.arn: + enabled: false + aws.ecs.task.family: + enabled: false + aws.ecs.task.revision: + enabled: false + aws.log.group.arns: + enabled: false + aws.log.group.names: + enabled: false + aws.log.stream.arns: + enabled: false + aws.log.stream.names: + enabled: false + cloud.account.id: + enabled: false + cloud.availability_zone: + enabled: false + cloud.platform: + enabled: false + cloud.provider: + enabled: false + cloud.region: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/aws/ecs/metadata.yaml b/processor/resourcedetectionprocessor/internal/aws/ecs/metadata.yaml new file mode 100644 index 000000000000..08238bb0a0b7 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/ecs/metadata.yaml @@ -0,0 +1,59 @@ +type: resourcedetectionprocessor/ecs + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true + cloud.account.id: + description: The cloud.account.id + type: string + enabled: true + cloud.region: + description: The cloud.region + type: string + enabled: true + cloud.availability_zone: + description: The cloud.availability_zone + type: string + enabled: true + aws.ecs.cluster.arn: + description: The aws.ecs.cluster.arn + type: string + enabled: true + aws.ecs.task.arn: + description: The aws.ecs.task.arn + type: string + enabled: true + aws.ecs.task.family: + description: The aws.ecs.task.family + type: string + enabled: true + aws.ecs.task.revision: + description: The aws.ecs.task.revision + type: string + enabled: true + aws.ecs.launchtype: + description: The aws.ecs.launchtype + type: string + enabled: true + aws.log.group.names: + description: The aws.log.group.names + type: string + enabled: true + aws.log.group.arns: + description: The aws.log.group.arns + type: string + enabled: true + aws.log.stream.names: + description: The aws.log.stream.names + type: string + enabled: true + aws.log.stream.arns: + description: The aws.log.stream.arns + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/aws/eks/config.go b/processor/resourcedetectionprocessor/internal/aws/eks/config.go new file mode 100644 index 000000000000..0221b8e1274e --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/eks/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package eks // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/eks" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/eks/detector.go b/processor/resourcedetectionprocessor/internal/aws/eks/detector.go index bb73608f7682..f8dced97d3be 100644 --- a/processor/resourcedetectionprocessor/internal/aws/eks/detector.go +++ b/processor/resourcedetectionprocessor/internal/aws/eks/detector.go @@ -17,6 +17,7 @@ import ( "k8s.io/client-go/rest" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata" ) const ( @@ -39,9 +40,10 @@ type eksDetectorUtils struct { // detector for EKS type detector struct { - utils detectorUtils - logger *zap.Logger - err error + utils detectorUtils + logger *zap.Logger + err error + resourceAttributes metadata.ResourceAttributesConfig } var _ internal.Detector = (*detector)(nil) @@ -49,9 +51,10 @@ var _ internal.Detector = (*detector)(nil) var _ detectorUtils = (*eksDetectorUtils)(nil) // NewDetector returns a resource detector that will detect AWS EKS resources. -func NewDetector(set processor.CreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { +func NewDetector(set processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) utils, err := newK8sDetectorUtils() - return &detector{utils: utils, logger: set.Logger, err: err}, nil + return &detector{utils: utils, logger: set.Logger, err: err, resourceAttributes: cfg.ResourceAttributes}, nil } // Detect returns a Resource describing the Amazon EKS environment being run in. @@ -66,8 +69,12 @@ func (detector *detector) Detect(ctx context.Context) (resource pcommon.Resource } attr := res.Attributes() - attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) - attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSEKS) + if detector.resourceAttributes.CloudProvider.Enabled { + attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) + } + if detector.resourceAttributes.CloudPlatform.Enabled { + attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSEKS) + } return res, conventions.SchemaURL, nil } diff --git a/processor/resourcedetectionprocessor/internal/aws/eks/detector_test.go b/processor/resourcedetectionprocessor/internal/aws/eks/detector_test.go index 33137666f1c4..a4ea414ad2d5 100644 --- a/processor/resourcedetectionprocessor/internal/aws/eks/detector_test.go +++ b/processor/resourcedetectionprocessor/internal/aws/eks/detector_test.go @@ -24,7 +24,8 @@ func (detectorUtils *MockDetectorUtils) getConfigMap(_ context.Context, namespac } func TestNewDetector(t *testing.T) { - detector, err := NewDetector(processortest.NewNopCreateSettings(), nil) + dcfg := CreateDefaultConfig() + detector, err := NewDetector(processortest.NewNopCreateSettings(), dcfg) assert.NoError(t, err) assert.NotNil(t, detector) } @@ -37,7 +38,8 @@ func TestEKS(t *testing.T) { t.Setenv("KUBERNETES_SERVICE_HOST", "localhost") detectorUtils.On("getConfigMap", authConfigmapNS, authConfigmapName).Return(map[string]string{"cluster.name": "my-cluster"}, nil) // Call EKS Resource detector to detect resources - eksResourceDetector := &detector{utils: detectorUtils, err: nil} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + eksResourceDetector := &detector{utils: detectorUtils, err: nil, resourceAttributes: resourceAttributes} res, _, err := eksResourceDetector.Detect(ctx) require.NoError(t, err) diff --git a/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/generated_config.go new file mode 100644 index 000000000000..3cc9b61f02b7 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/generated_config.go @@ -0,0 +1,25 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/eks resource attributes. +type ResourceAttributesConfig struct { + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..ddd1c9b4717a --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/generated_config_test.go @@ -0,0 +1,56 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..d00b63470c51 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/eks/internal/metadata/testdata/config.yaml @@ -0,0 +1,13 @@ +default: +all_set: + resource_attributes: + cloud.platform: + enabled: true + cloud.provider: + enabled: true +none_set: + resource_attributes: + cloud.platform: + enabled: false + cloud.provider: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/aws/eks/metadata.yaml b/processor/resourcedetectionprocessor/internal/aws/eks/metadata.yaml new file mode 100644 index 000000000000..b5c003beb079 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/eks/metadata.yaml @@ -0,0 +1,11 @@ +type: resourcedetectionprocessor/eks + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/config.go b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/config.go new file mode 100644 index 000000000000..2f4d87fdb12a --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package elasticbeanstalk // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk.go b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk.go index 44932c058bac..a3d2340af857 100644 --- a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk.go +++ b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk.go @@ -14,6 +14,7 @@ import ( conventions "go.opentelemetry.io/collector/semconv/v1.6.1" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata" ) const ( @@ -27,7 +28,8 @@ const ( var _ internal.Detector = (*Detector)(nil) type Detector struct { - fs fileSystem + fs fileSystem + resourceAttributes metadata.ResourceAttributesConfig } type EbMetaData struct { @@ -36,8 +38,9 @@ type EbMetaData struct { VersionLabel string `json:"version_label"` } -func NewDetector(processor.CreateSettings, internal.DetectorConfig) (internal.Detector, error) { - return &Detector{fs: &ebFileSystem{}}, nil +func NewDetector(_ processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) + return &Detector{fs: &ebFileSystem{}, resourceAttributes: cfg.ResourceAttributes}, nil } func (d Detector) Detect(context.Context) (resource pcommon.Resource, schemaURL string, err error) { @@ -66,10 +69,20 @@ func (d Detector) Detect(context.Context) (resource pcommon.Resource, schemaURL } attr := res.Attributes() - attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) - attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSElasticBeanstalk) - attr.PutStr(conventions.AttributeServiceInstanceID, strconv.Itoa(ebmd.DeploymentID)) - attr.PutStr(conventions.AttributeDeploymentEnvironment, ebmd.EnvironmentName) - attr.PutStr(conventions.AttributeServiceVersion, ebmd.VersionLabel) + if d.resourceAttributes.CloudProvider.Enabled { + attr.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) + } + if d.resourceAttributes.CloudPlatform.Enabled { + attr.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSElasticBeanstalk) + } + if d.resourceAttributes.ServiceInstanceID.Enabled { + attr.PutStr(conventions.AttributeServiceInstanceID, strconv.Itoa(ebmd.DeploymentID)) + } + if d.resourceAttributes.DeploymentEnvironment.Enabled { + attr.PutStr(conventions.AttributeDeploymentEnvironment, ebmd.EnvironmentName) + } + if d.resourceAttributes.ServiceVersion.Enabled { + attr.PutStr(conventions.AttributeServiceVersion, ebmd.VersionLabel) + } return res, conventions.SchemaURL, nil } diff --git a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk_test.go b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk_test.go index 46e800968bc0..06588f15c339 100644 --- a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk_test.go +++ b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/elasticbeanstalk_test.go @@ -38,7 +38,8 @@ func (mfs *mockFileSystem) IsWindows() bool { } func Test_newDetector(t *testing.T) { - d, err := NewDetector(processortest.NewNopCreateSettings(), nil) + dcfg := CreateDefaultConfig() + d, err := NewDetector(processortest.NewNopCreateSettings(), dcfg) assert.Nil(t, err) assert.NotNil(t, d) @@ -79,7 +80,8 @@ func Test_fileMalformed(t *testing.T) { func Test_AttributesDetectedSuccessfully(t *testing.T) { mfs := &mockFileSystem{exists: true, contents: xrayConf} - d := Detector{fs: mfs} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + d := Detector{fs: mfs, resourceAttributes: resourceAttributes} want := pcommon.NewResource() attr := want.Attributes() diff --git a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/generated_config.go new file mode 100644 index 000000000000..f8dbd4bc88fa --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/generated_config.go @@ -0,0 +1,37 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/elastic_beanstalk resource attributes. +type ResourceAttributesConfig struct { + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + DeploymentEnvironment ResourceAttributeConfig `mapstructure:"deployment.environment"` + ServiceInstanceID ResourceAttributeConfig `mapstructure:"service.instance.id"` + ServiceVersion ResourceAttributeConfig `mapstructure:"service.version"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + DeploymentEnvironment: ResourceAttributeConfig{ + Enabled: true, + }, + ServiceInstanceID: ResourceAttributeConfig{ + Enabled: true, + }, + ServiceVersion: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..26434c4202b5 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/generated_config_test.go @@ -0,0 +1,62 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + DeploymentEnvironment: ResourceAttributeConfig{Enabled: true}, + ServiceInstanceID: ResourceAttributeConfig{Enabled: true}, + ServiceVersion: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + DeploymentEnvironment: ResourceAttributeConfig{Enabled: false}, + ServiceInstanceID: ResourceAttributeConfig{Enabled: false}, + ServiceVersion: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..fca89c90e422 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/internal/metadata/testdata/config.yaml @@ -0,0 +1,25 @@ +default: +all_set: + resource_attributes: + cloud.platform: + enabled: true + cloud.provider: + enabled: true + deployment.environment: + enabled: true + service.instance.id: + enabled: true + service.version: + enabled: true +none_set: + resource_attributes: + cloud.platform: + enabled: false + cloud.provider: + enabled: false + deployment.environment: + enabled: false + service.instance.id: + enabled: false + service.version: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/metadata.yaml b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/metadata.yaml new file mode 100644 index 000000000000..5da8242cbf8d --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk/metadata.yaml @@ -0,0 +1,23 @@ +type: resourcedetectionprocessor/elastic_beanstalk + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true + deployment.environment: + description: The deployment.environment + type: string + enabled: true + service.instance.id: + description: The service.instance.id + type: string + enabled: true + service.version: + description: The service.version + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/aws/lambda/config.go b/processor/resourcedetectionprocessor/internal/aws/lambda/config.go new file mode 100644 index 000000000000..21268a7de0e1 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/lambda/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package lambda // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config.go new file mode 100644 index 000000000000..99d8a7a44a20 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config.go @@ -0,0 +1,53 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/lambda resource attributes. +type ResourceAttributesConfig struct { + AwsLogGroupNames ResourceAttributeConfig `mapstructure:"aws.log.group.names"` + AwsLogStreamNames ResourceAttributeConfig `mapstructure:"aws.log.stream.names"` + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` + FaasInstance ResourceAttributeConfig `mapstructure:"faas.instance"` + FaasMaxMemory ResourceAttributeConfig `mapstructure:"faas.max_memory"` + FaasName ResourceAttributeConfig `mapstructure:"faas.name"` + FaasVersion ResourceAttributeConfig `mapstructure:"faas.version"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + AwsLogGroupNames: ResourceAttributeConfig{ + Enabled: true, + }, + AwsLogStreamNames: ResourceAttributeConfig{ + Enabled: true, + }, + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + FaasInstance: ResourceAttributeConfig{ + Enabled: true, + }, + FaasMaxMemory: ResourceAttributeConfig{ + Enabled: true, + }, + FaasName: ResourceAttributeConfig{ + Enabled: true, + }, + FaasVersion: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..dd37e51364a2 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config_test.go @@ -0,0 +1,70 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + AwsLogGroupNames: ResourceAttributeConfig{Enabled: true}, + AwsLogStreamNames: ResourceAttributeConfig{Enabled: true}, + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + CloudRegion: ResourceAttributeConfig{Enabled: true}, + FaasInstance: ResourceAttributeConfig{Enabled: true}, + FaasMaxMemory: ResourceAttributeConfig{Enabled: true}, + FaasName: ResourceAttributeConfig{Enabled: true}, + FaasVersion: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + AwsLogGroupNames: ResourceAttributeConfig{Enabled: false}, + AwsLogStreamNames: ResourceAttributeConfig{Enabled: false}, + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + CloudRegion: ResourceAttributeConfig{Enabled: false}, + FaasInstance: ResourceAttributeConfig{Enabled: false}, + FaasMaxMemory: ResourceAttributeConfig{Enabled: false}, + FaasName: ResourceAttributeConfig{Enabled: false}, + FaasVersion: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..491e995990eb --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/testdata/config.yaml @@ -0,0 +1,41 @@ +default: +all_set: + resource_attributes: + aws.log.group.names: + enabled: true + aws.log.stream.names: + enabled: true + cloud.platform: + enabled: true + cloud.provider: + enabled: true + cloud.region: + enabled: true + faas.instance: + enabled: true + faas.max_memory: + enabled: true + faas.name: + enabled: true + faas.version: + enabled: true +none_set: + resource_attributes: + aws.log.group.names: + enabled: false + aws.log.stream.names: + enabled: false + cloud.platform: + enabled: false + cloud.provider: + enabled: false + cloud.region: + enabled: false + faas.instance: + enabled: false + faas.max_memory: + enabled: false + faas.name: + enabled: false + faas.version: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go b/processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go index 3c31de4c7290..8527bae4402f 100644 --- a/processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go +++ b/processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go @@ -13,6 +13,7 @@ import ( "go.uber.org/zap" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata" ) const ( @@ -32,11 +33,13 @@ const ( var _ internal.Detector = (*detector)(nil) type detector struct { - logger *zap.Logger + logger *zap.Logger + resourceAttributes metadata.ResourceAttributesConfig } -func NewDetector(set processor.CreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { - return &detector{logger: set.Logger}, nil +func NewDetector(set processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) + return &detector{logger: set.Logger, resourceAttributes: cfg.ResourceAttributes}, nil } func (d *detector) Detect(_ context.Context) (resource pcommon.Resource, schemaURL string, err error) { @@ -51,35 +54,53 @@ func (d *detector) Detect(_ context.Context) (resource pcommon.Resource, schemaU attrs := res.Attributes() // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/cloud.md - attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) - attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSLambda) - if value, ok := os.LookupEnv(awsRegionEnvVar); ok { - attrs.PutStr(conventions.AttributeCloudRegion, value) + if d.resourceAttributes.CloudProvider.Enabled { + attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAWS) + } + if d.resourceAttributes.CloudPlatform.Enabled { + attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAWSLambda) + } + if d.resourceAttributes.CloudRegion.Enabled { + if value, ok := os.LookupEnv(awsRegionEnvVar); ok { + attrs.PutStr(conventions.AttributeCloudRegion, value) + } } // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/faas.md // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/instrumentation/aws-lambda.md#resource-detector - attrs.PutStr(conventions.AttributeFaaSName, functionName) - if value, ok := os.LookupEnv(awsLambdaFunctionVersionEnvVar); ok { - attrs.PutStr(conventions.AttributeFaaSVersion, value) + if d.resourceAttributes.FaasName.Enabled { + attrs.PutStr(conventions.AttributeFaaSName, functionName) + } + if d.resourceAttributes.FaasVersion.Enabled { + if value, ok := os.LookupEnv(awsLambdaFunctionVersionEnvVar); ok { + attrs.PutStr(conventions.AttributeFaaSVersion, value) + } } // Note: The FaaS spec (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/faas.md) // recommends setting faas.instance to the full log stream name for AWS Lambda. - if value, ok := os.LookupEnv(awsLambdaLogStreamNameEnvVar); ok { - attrs.PutStr(conventions.AttributeFaaSInstance, value) + if d.resourceAttributes.FaasInstance.Enabled { + if value, ok := os.LookupEnv(awsLambdaLogStreamNameEnvVar); ok { + attrs.PutStr(conventions.AttributeFaaSInstance, value) + } } - if value, ok := os.LookupEnv(awsLambdaFunctionMemorySizeEnvVar); ok { - attrs.PutStr(conventions.AttributeFaaSMaxMemory, value) + if d.resourceAttributes.FaasMaxMemory.Enabled { + if value, ok := os.LookupEnv(awsLambdaFunctionMemorySizeEnvVar); ok { + attrs.PutStr(conventions.AttributeFaaSMaxMemory, value) + } } // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/cloud_provider/aws/logs.md - if value, ok := os.LookupEnv(awsLambdaLogGroupNameEnvVar); ok { - logGroupNames := attrs.PutEmptySlice(conventions.AttributeAWSLogGroupNames) - logGroupNames.AppendEmpty().SetStr(value) + if d.resourceAttributes.AwsLogGroupNames.Enabled { + if value, ok := os.LookupEnv(awsLambdaLogGroupNameEnvVar); ok { + logGroupNames := attrs.PutEmptySlice(conventions.AttributeAWSLogGroupNames) + logGroupNames.AppendEmpty().SetStr(value) + } } - if value, ok := os.LookupEnv(awsLambdaLogStreamNameEnvVar); ok { - logStreamNames := attrs.PutEmptySlice(conventions.AttributeAWSLogStreamNames) - logStreamNames.AppendEmpty().SetStr(value) + if d.resourceAttributes.AwsLogStreamNames.Enabled { + if value, ok := os.LookupEnv(awsLambdaLogStreamNameEnvVar); ok { + logStreamNames := attrs.PutEmptySlice(conventions.AttributeAWSLogStreamNames) + logStreamNames.AppendEmpty().SetStr(value) + } } return res, conventions.SchemaURL, nil diff --git a/processor/resourcedetectionprocessor/internal/aws/lambda/lambda_test.go b/processor/resourcedetectionprocessor/internal/aws/lambda/lambda_test.go index aa4e1407ec3f..165cf6006ada 100644 --- a/processor/resourcedetectionprocessor/internal/aws/lambda/lambda_test.go +++ b/processor/resourcedetectionprocessor/internal/aws/lambda/lambda_test.go @@ -15,7 +15,8 @@ import ( ) func TestNewDetector(t *testing.T) { - detector, err := NewDetector(processortest.NewNopCreateSettings(), nil) + dcfg := CreateDefaultConfig() + detector, err := NewDetector(processortest.NewNopCreateSettings(), dcfg) assert.NoError(t, err) assert.NotNil(t, detector) } @@ -28,7 +29,8 @@ func TestLambda(t *testing.T) { t.Setenv(awsLambdaFunctionNameEnvVar, functionName) // Call Lambda Resource detector to detect resources - lambdaDetector := &detector{logger: zap.NewNop()} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + lambdaDetector := &detector{logger: zap.NewNop(), resourceAttributes: resourceAttributes} res, _, err := lambdaDetector.Detect(ctx) require.NoError(t, err) require.NotNil(t, res) @@ -43,7 +45,8 @@ func TestLambda(t *testing.T) { // Tests Lambda resource detector not running in Lambda environment func TestNotLambda(t *testing.T) { ctx := context.Background() - lambdaDetector := &detector{logger: zap.NewNop()} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + lambdaDetector := &detector{logger: zap.NewNop(), resourceAttributes: resourceAttributes} res, _, err := lambdaDetector.Detect(ctx) require.NoError(t, err) require.NotNil(t, res) diff --git a/processor/resourcedetectionprocessor/internal/aws/lambda/metadata.yaml b/processor/resourcedetectionprocessor/internal/aws/lambda/metadata.yaml new file mode 100644 index 000000000000..73cc90f26304 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/aws/lambda/metadata.yaml @@ -0,0 +1,39 @@ +type: resourcedetectionprocessor/lambda + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true + cloud.region: + description: The cloud.region + type: string + enabled: true + aws.log.group.names: + description: The aws.log.group.names + type: string + enabled: true + aws.log.stream.names: + description: The aws.log.stream.names + type: string + enabled: true + faas.name: + description: faas.name + type: string + enabled: true + faas.version: + description: The faas.version + type: string + enabled: true + faas.instance: + description: The faas.instance + type: string + enabled: true + faas.max_memory: + description: The faas.max_memory + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/azure/aks/aks.go b/processor/resourcedetectionprocessor/internal/azure/aks/aks.go index 4871da75b6a9..9bdfb1e690d6 100644 --- a/processor/resourcedetectionprocessor/internal/azure/aks/aks.go +++ b/processor/resourcedetectionprocessor/internal/azure/aks/aks.go @@ -13,6 +13,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/azure" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata" ) const ( @@ -24,12 +25,14 @@ const ( ) type Detector struct { - provider azure.Provider + provider azure.Provider + resourceAttributes metadata.ResourceAttributesConfig } // NewDetector creates a new AKS detector -func NewDetector(processor.CreateSettings, internal.DetectorConfig) (internal.Detector, error) { - return &Detector{provider: azure.NewProvider()}, nil +func NewDetector(_ processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) + return &Detector{provider: azure.NewProvider(), resourceAttributes: cfg.ResourceAttributes}, nil } func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schemaURL string, err error) { @@ -45,8 +48,12 @@ func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schem } attrs := res.Attributes() - attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure) - attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAzureAKS) + if d.resourceAttributes.CloudProvider.Enabled { + attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure) + } + if d.resourceAttributes.CloudPlatform.Enabled { + attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAzureAKS) + } return res, conventions.SchemaURL, nil } diff --git a/processor/resourcedetectionprocessor/internal/azure/aks/aks_test.go b/processor/resourcedetectionprocessor/internal/azure/aks/aks_test.go index 38cab0aaba79..aa8da732bcfc 100644 --- a/processor/resourcedetectionprocessor/internal/azure/aks/aks_test.go +++ b/processor/resourcedetectionprocessor/internal/azure/aks/aks_test.go @@ -18,14 +18,16 @@ import ( ) func TestNewDetector(t *testing.T) { - d, err := NewDetector(processortest.NewNopCreateSettings(), nil) + dcfg := CreateDefaultConfig() + d, err := NewDetector(processortest.NewNopCreateSettings(), dcfg) require.NoError(t, err) assert.NotNil(t, d) } func TestDetector_Detect_K8s_Azure(t *testing.T) { t.Setenv("KUBERNETES_SERVICE_HOST", "localhost") - detector := &Detector{provider: mockProvider()} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mockProvider(), resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) require.NoError(t, err) assert.Equal(t, conventions.SchemaURL, schemaURL) @@ -39,7 +41,8 @@ func TestDetector_Detect_K8s_NonAzure(t *testing.T) { t.Setenv("KUBERNETES_SERVICE_HOST", "localhost") mp := &azure.MockProvider{} mp.On("Metadata").Return(nil, errors.New("")) - detector := &Detector{provider: mp} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mp, resourceAttributes: resourceAttributes} res, _, err := detector.Detect(context.Background()) require.NoError(t, err) attrs := res.Attributes() @@ -48,7 +51,8 @@ func TestDetector_Detect_K8s_NonAzure(t *testing.T) { func TestDetector_Detect_NonK8s(t *testing.T) { os.Clearenv() - detector := &Detector{provider: mockProvider()} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mockProvider(), resourceAttributes: resourceAttributes} res, _, err := detector.Detect(context.Background()) require.NoError(t, err) attrs := res.Attributes() diff --git a/processor/resourcedetectionprocessor/internal/azure/aks/config.go b/processor/resourcedetectionprocessor/internal/azure/aks/config.go new file mode 100644 index 000000000000..546c4715f710 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/aks/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package aks // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/aks" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/generated_config.go new file mode 100644 index 000000000000..c660a4bb8972 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/generated_config.go @@ -0,0 +1,25 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/aks resource attributes. +type ResourceAttributesConfig struct { + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..ddd1c9b4717a --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/generated_config_test.go @@ -0,0 +1,56 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..d00b63470c51 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/aks/internal/metadata/testdata/config.yaml @@ -0,0 +1,13 @@ +default: +all_set: + resource_attributes: + cloud.platform: + enabled: true + cloud.provider: + enabled: true +none_set: + resource_attributes: + cloud.platform: + enabled: false + cloud.provider: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/azure/aks/metadata.yaml b/processor/resourcedetectionprocessor/internal/azure/aks/metadata.yaml new file mode 100644 index 000000000000..ef8303419036 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/aks/metadata.yaml @@ -0,0 +1,11 @@ +type: resourcedetectionprocessor/aks + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/azure/azure.go b/processor/resourcedetectionprocessor/internal/azure/azure.go index a4fe6bd0a99c..227fe2e54141 100644 --- a/processor/resourcedetectionprocessor/internal/azure/azure.go +++ b/processor/resourcedetectionprocessor/internal/azure/azure.go @@ -13,6 +13,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/azure" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/internal/metadata" ) const ( @@ -24,15 +25,18 @@ var _ internal.Detector = (*Detector)(nil) // Detector is an Azure metadata detector type Detector struct { - provider azure.Provider - logger *zap.Logger + provider azure.Provider + logger *zap.Logger + resourceAttributes metadata.ResourceAttributesConfig } // NewDetector creates a new Azure metadata detector -func NewDetector(p processor.CreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { +func NewDetector(p processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) return &Detector{ - provider: azure.NewProvider(), - logger: p.Logger, + provider: azure.NewProvider(), + logger: p.Logger, + resourceAttributes: cfg.ResourceAttributes, }, nil } @@ -47,13 +51,24 @@ func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schem // return an empty Resource and no error return res, "", nil } - - attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure) - attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAzureVM) - attrs.PutStr(conventions.AttributeHostName, compute.Name) - attrs.PutStr(conventions.AttributeCloudRegion, compute.Location) - attrs.PutStr(conventions.AttributeHostID, compute.VMID) - attrs.PutStr(conventions.AttributeCloudAccountID, compute.SubscriptionID) + if d.resourceAttributes.CloudProvider.Enabled { + attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderAzure) + } + if d.resourceAttributes.CloudPlatform.Enabled { + attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformAzureVM) + } + if d.resourceAttributes.HostName.Enabled { + attrs.PutStr(conventions.AttributeHostName, compute.Name) + } + if d.resourceAttributes.CloudRegion.Enabled { + attrs.PutStr(conventions.AttributeCloudRegion, compute.Location) + } + if d.resourceAttributes.HostID.Enabled { + attrs.PutStr(conventions.AttributeHostID, compute.VMID) + } + if d.resourceAttributes.CloudAccountID.Enabled { + attrs.PutStr(conventions.AttributeCloudAccountID, compute.SubscriptionID) + } // Also save compute.Name in "azure.vm.name" as host.id (AttributeHostName) is // used by system detector. attrs.PutStr("azure.vm.name", compute.Name) diff --git a/processor/resourcedetectionprocessor/internal/azure/azure_test.go b/processor/resourcedetectionprocessor/internal/azure/azure_test.go index 8e4aa2545e38..c94f72b7876c 100644 --- a/processor/resourcedetectionprocessor/internal/azure/azure_test.go +++ b/processor/resourcedetectionprocessor/internal/azure/azure_test.go @@ -19,7 +19,8 @@ import ( ) func TestNewDetector(t *testing.T) { - d, err := NewDetector(processortest.NewNopCreateSettings(), nil) + dcfg := CreateDefaultConfig() + d, err := NewDetector(processortest.NewNopCreateSettings(), dcfg) require.NoError(t, err) assert.NotNil(t, d) } @@ -36,7 +37,8 @@ func TestDetectAzureAvailable(t *testing.T) { VMScaleSetName: "myScaleset", }, nil) - detector := &Detector{provider: mp} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mp, resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) require.NoError(t, err) assert.Equal(t, conventions.SchemaURL, schemaURL) @@ -61,8 +63,8 @@ func TestDetectAzureAvailable(t *testing.T) { func TestDetectError(t *testing.T) { mp := &azure.MockProvider{} mp.On("Metadata").Return(&azure.ComputeMetadata{}, fmt.Errorf("mock error")) - - detector := &Detector{provider: mp, logger: zap.NewNop()} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mp, logger: zap.NewNop(), resourceAttributes: resourceAttributes} res, _, err := detector.Detect(context.Background()) assert.NoError(t, err) assert.True(t, internal.IsEmptyResource(res)) diff --git a/processor/resourcedetectionprocessor/internal/azure/config.go b/processor/resourcedetectionprocessor/internal/azure/config.go new file mode 100644 index 000000000000..8013cd25391b --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package azure // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/azure/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/azure/internal/metadata/generated_config.go new file mode 100644 index 000000000000..db0515e5acee --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/internal/metadata/generated_config.go @@ -0,0 +1,57 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/azure resource attributes. +type ResourceAttributesConfig struct { + AzureResourcegroupName ResourceAttributeConfig `mapstructure:"azure.resourcegroup.name"` + AzureVMName ResourceAttributeConfig `mapstructure:"azure.vm.name"` + AzureVMScalesetName ResourceAttributeConfig `mapstructure:"azure.vm.scaleset.name"` + AzureVMSize ResourceAttributeConfig `mapstructure:"azure.vm.size"` + CloudAccountID ResourceAttributeConfig `mapstructure:"cloud.account.id"` + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` + HostID ResourceAttributeConfig `mapstructure:"host.id"` + HostName ResourceAttributeConfig `mapstructure:"host.name"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + AzureResourcegroupName: ResourceAttributeConfig{ + Enabled: true, + }, + AzureVMName: ResourceAttributeConfig{ + Enabled: true, + }, + AzureVMScalesetName: ResourceAttributeConfig{ + Enabled: true, + }, + AzureVMSize: ResourceAttributeConfig{ + Enabled: true, + }, + CloudAccountID: ResourceAttributeConfig{ + Enabled: true, + }, + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + HostID: ResourceAttributeConfig{ + Enabled: true, + }, + HostName: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/azure/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/azure/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..3a5f714513fb --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/internal/metadata/generated_config_test.go @@ -0,0 +1,72 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + AzureResourcegroupName: ResourceAttributeConfig{Enabled: true}, + AzureVMName: ResourceAttributeConfig{Enabled: true}, + AzureVMScalesetName: ResourceAttributeConfig{Enabled: true}, + AzureVMSize: ResourceAttributeConfig{Enabled: true}, + CloudAccountID: ResourceAttributeConfig{Enabled: true}, + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + CloudRegion: ResourceAttributeConfig{Enabled: true}, + HostID: ResourceAttributeConfig{Enabled: true}, + HostName: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + AzureResourcegroupName: ResourceAttributeConfig{Enabled: false}, + AzureVMName: ResourceAttributeConfig{Enabled: false}, + AzureVMScalesetName: ResourceAttributeConfig{Enabled: false}, + AzureVMSize: ResourceAttributeConfig{Enabled: false}, + CloudAccountID: ResourceAttributeConfig{Enabled: false}, + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + CloudRegion: ResourceAttributeConfig{Enabled: false}, + HostID: ResourceAttributeConfig{Enabled: false}, + HostName: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/azure/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/azure/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..d060bcd291d6 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/internal/metadata/testdata/config.yaml @@ -0,0 +1,45 @@ +default: +all_set: + resource_attributes: + azure.resourcegroup.name: + enabled: true + azure.vm.name: + enabled: true + azure.vm.scaleset.name: + enabled: true + azure.vm.size: + enabled: true + cloud.account.id: + enabled: true + cloud.platform: + enabled: true + cloud.provider: + enabled: true + cloud.region: + enabled: true + host.id: + enabled: true + host.name: + enabled: true +none_set: + resource_attributes: + azure.resourcegroup.name: + enabled: false + azure.vm.name: + enabled: false + azure.vm.scaleset.name: + enabled: false + azure.vm.size: + enabled: false + cloud.account.id: + enabled: false + cloud.platform: + enabled: false + cloud.provider: + enabled: false + cloud.region: + enabled: false + host.id: + enabled: false + host.name: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/azure/metadata.yaml b/processor/resourcedetectionprocessor/internal/azure/metadata.yaml new file mode 100644 index 000000000000..5816a1179c86 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/azure/metadata.yaml @@ -0,0 +1,43 @@ +type: resourcedetectionprocessor/azure + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true + cloud.region: + description: The cloud.region + type: string + enabled: true + cloud.account.id: + description: The cloud.account.id + type: string + enabled: true + host.name: + description: The hostname + type: string + enabled: true + host.id: + description: The host.id + type: string + enabled: true + azure.resourcegroup.name: + description: The azure.resourcegroup.name + enabled: true + type: string + azure.vm.name: + description: The azure.vm.name + enabled: true + type: string + azure.vm.scaleset.name: + description: The azure.vm.scaleset.name + enabled: true + type: string + azure.vm.size: + description: The azure.vm.size + enabled: true + type: string \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/consul/config.go b/processor/resourcedetectionprocessor/internal/consul/config.go index 9d8f44719bc6..b47f84fce29f 100644 --- a/processor/resourcedetectionprocessor/internal/consul/config.go +++ b/processor/resourcedetectionprocessor/internal/consul/config.go @@ -3,7 +3,11 @@ package consul // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/consul" -import "go.opentelemetry.io/collector/config/configopaque" +import ( + "go.opentelemetry.io/collector/config/configopaque" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/consul/internal/metadata" +) // The struct requires no user-specified fields by default as consul agent's default // configuration will be provided to the API client. @@ -36,4 +40,13 @@ type Config struct { // Metadata](https://www.consul.io/docs/agent/options#node_meta) keys to use as // resource attributes. MetaLabels map[string]interface{} `mapstructure:"meta"` + + // ResourceAttributes configuration for Consul detector + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } } diff --git a/processor/resourcedetectionprocessor/internal/consul/consul.go b/processor/resourcedetectionprocessor/internal/consul/consul.go index 6005a61f2a44..1c51ab112f50 100644 --- a/processor/resourcedetectionprocessor/internal/consul/consul.go +++ b/processor/resourcedetectionprocessor/internal/consul/consul.go @@ -15,6 +15,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/consul" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/consul/internal/metadata" ) const ( @@ -26,8 +27,9 @@ var _ internal.Detector = (*Detector)(nil) // Detector is a system metadata detector type Detector struct { - provider consul.Provider - logger *zap.Logger + provider consul.Provider + logger *zap.Logger + resourceAttributes metadata.ResourceAttributesConfig } // NewDetector creates a new system metadata detector @@ -57,7 +59,7 @@ func NewDetector(p processor.CreateSettings, dcfg internal.DetectorConfig) (inte } provider := consul.NewProvider(client, userCfg.MetaLabels) - return &Detector{provider: provider, logger: p.Logger}, nil + return &Detector{provider: provider, logger: p.Logger, resourceAttributes: userCfg.ResourceAttributes}, nil } // Detect detects system metadata and returns a resource with the available ones @@ -74,9 +76,15 @@ func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schem attrs.PutStr(key, element) } - attrs.PutStr(conventions.AttributeHostName, metadata.Hostname) - attrs.PutStr(conventions.AttributeCloudRegion, metadata.Datacenter) - attrs.PutStr(conventions.AttributeHostID, metadata.NodeID) + if d.resourceAttributes.HostName.Enabled { + attrs.PutStr(conventions.AttributeHostName, metadata.Hostname) + } + if d.resourceAttributes.CloudRegion.Enabled { + attrs.PutStr(conventions.AttributeCloudRegion, metadata.Datacenter) + } + if d.resourceAttributes.HostID.Enabled { + attrs.PutStr(conventions.AttributeHostID, metadata.NodeID) + } return res, conventions.SchemaURL, nil } diff --git a/processor/resourcedetectionprocessor/internal/consul/consul_test.go b/processor/resourcedetectionprocessor/internal/consul/consul_test.go index 35b1d2eaefb2..29f44cbec0b8 100644 --- a/processor/resourcedetectionprocessor/internal/consul/consul_test.go +++ b/processor/resourcedetectionprocessor/internal/consul/consul_test.go @@ -39,10 +39,11 @@ func TestDetect(t *testing.T) { }, nil, ) - + dcfg := CreateDefaultConfig() detector := &Detector{ - provider: md, - logger: zap.NewNop(), + provider: md, + logger: zap.NewNop(), + resourceAttributes: dcfg.ResourceAttributes, } res, schemaURL, err := detector.Detect(context.Background()) require.NoError(t, err) diff --git a/processor/resourcedetectionprocessor/internal/consul/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/consul/internal/metadata/generated_config.go new file mode 100644 index 000000000000..5d291cebf0fb --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/consul/internal/metadata/generated_config.go @@ -0,0 +1,57 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/consul resource attributes. +type ResourceAttributesConfig struct { + AzureResourcegroupName ResourceAttributeConfig `mapstructure:"azure.resourcegroup.name"` + AzureVMName ResourceAttributeConfig `mapstructure:"azure.vm.name"` + AzureVMScalesetName ResourceAttributeConfig `mapstructure:"azure.vm.scaleset.name"` + AzureVMSize ResourceAttributeConfig `mapstructure:"azure.vm.size"` + CloudAccountID ResourceAttributeConfig `mapstructure:"cloud.account.id"` + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` + HostID ResourceAttributeConfig `mapstructure:"host.id"` + HostName ResourceAttributeConfig `mapstructure:"host.name"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + AzureResourcegroupName: ResourceAttributeConfig{ + Enabled: true, + }, + AzureVMName: ResourceAttributeConfig{ + Enabled: true, + }, + AzureVMScalesetName: ResourceAttributeConfig{ + Enabled: true, + }, + AzureVMSize: ResourceAttributeConfig{ + Enabled: true, + }, + CloudAccountID: ResourceAttributeConfig{ + Enabled: true, + }, + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + HostID: ResourceAttributeConfig{ + Enabled: true, + }, + HostName: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/consul/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/consul/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..3a5f714513fb --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/consul/internal/metadata/generated_config_test.go @@ -0,0 +1,72 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + AzureResourcegroupName: ResourceAttributeConfig{Enabled: true}, + AzureVMName: ResourceAttributeConfig{Enabled: true}, + AzureVMScalesetName: ResourceAttributeConfig{Enabled: true}, + AzureVMSize: ResourceAttributeConfig{Enabled: true}, + CloudAccountID: ResourceAttributeConfig{Enabled: true}, + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + CloudRegion: ResourceAttributeConfig{Enabled: true}, + HostID: ResourceAttributeConfig{Enabled: true}, + HostName: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + AzureResourcegroupName: ResourceAttributeConfig{Enabled: false}, + AzureVMName: ResourceAttributeConfig{Enabled: false}, + AzureVMScalesetName: ResourceAttributeConfig{Enabled: false}, + AzureVMSize: ResourceAttributeConfig{Enabled: false}, + CloudAccountID: ResourceAttributeConfig{Enabled: false}, + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + CloudRegion: ResourceAttributeConfig{Enabled: false}, + HostID: ResourceAttributeConfig{Enabled: false}, + HostName: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/consul/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/consul/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..d060bcd291d6 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/consul/internal/metadata/testdata/config.yaml @@ -0,0 +1,45 @@ +default: +all_set: + resource_attributes: + azure.resourcegroup.name: + enabled: true + azure.vm.name: + enabled: true + azure.vm.scaleset.name: + enabled: true + azure.vm.size: + enabled: true + cloud.account.id: + enabled: true + cloud.platform: + enabled: true + cloud.provider: + enabled: true + cloud.region: + enabled: true + host.id: + enabled: true + host.name: + enabled: true +none_set: + resource_attributes: + azure.resourcegroup.name: + enabled: false + azure.vm.name: + enabled: false + azure.vm.scaleset.name: + enabled: false + azure.vm.size: + enabled: false + cloud.account.id: + enabled: false + cloud.platform: + enabled: false + cloud.provider: + enabled: false + cloud.region: + enabled: false + host.id: + enabled: false + host.name: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/consul/metadata.yaml b/processor/resourcedetectionprocessor/internal/consul/metadata.yaml new file mode 100644 index 000000000000..9431338b20f1 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/consul/metadata.yaml @@ -0,0 +1,43 @@ +type: resourcedetectionprocessor/consul + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true + cloud.region: + description: The cloud.region + type: string + enabled: true + cloud.account.id: + description: The cloud.account.id + type: string + enabled: true + host.name: + description: The hostname + type: string + enabled: true + host.id: + description: The host.id + type: string + enabled: true + azure.resourcegroup.name: + description: The azure.resourcegroup.name + enabled: true + type: string + azure.vm.name: + description: The azure.vm.name + enabled: true + type: string + azure.vm.scaleset.name: + description: The azure.vm.scaleset.name + enabled: true + type: string + azure.vm.size: + description: The azure.vm.size + enabled: true + type: string \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/docker/config.go b/processor/resourcedetectionprocessor/internal/docker/config.go new file mode 100644 index 000000000000..fbb8082ab4a3 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/docker/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package docker // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/docker" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/docker/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/docker/docker.go b/processor/resourcedetectionprocessor/internal/docker/docker.go index ef6f25d6fd1e..74d260864323 100644 --- a/processor/resourcedetectionprocessor/internal/docker/docker.go +++ b/processor/resourcedetectionprocessor/internal/docker/docker.go @@ -14,6 +14,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/docker" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/docker/internal/metadata" ) const ( @@ -25,8 +26,9 @@ var _ internal.Detector = (*Detector)(nil) // Detector is a system metadata detector type Detector struct { - provider docker.Provider - logger *zap.Logger + provider docker.Provider + logger *zap.Logger + resourceAttributes metadata.ResourceAttributesConfig } // NewDetector creates a new system metadata detector @@ -54,8 +56,12 @@ func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schem return res, "", fmt.Errorf("failed getting OS hostname: %w", err) } - attrs.PutStr(conventions.AttributeHostName, hostname) - attrs.PutStr(conventions.AttributeOSType, osType) + if d.resourceAttributes.HostName.Enabled { + attrs.PutStr(conventions.AttributeHostName, hostname) + } + if d.resourceAttributes.OsType.Enabled { + attrs.PutStr(conventions.AttributeOSType, osType) + } return res, conventions.SchemaURL, nil } diff --git a/processor/resourcedetectionprocessor/internal/docker/docker_test.go b/processor/resourcedetectionprocessor/internal/docker/docker_test.go index 10680dd31600..fa06d0c5b2df 100644 --- a/processor/resourcedetectionprocessor/internal/docker/docker_test.go +++ b/processor/resourcedetectionprocessor/internal/docker/docker_test.go @@ -37,7 +37,8 @@ func TestDetect(t *testing.T) { md.On("Hostname").Return("hostname", nil) md.On("OSType").Return("darwin", nil) - detector := &Detector{provider: md, logger: zap.NewNop()} + dcfg := CreateDefaultConfig() + detector := &Detector{provider: md, logger: zap.NewNop(), resourceAttributes: dcfg.ResourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) require.NoError(t, err) assert.Equal(t, conventions.SchemaURL, schemaURL) diff --git a/processor/resourcedetectionprocessor/internal/docker/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/docker/internal/metadata/generated_config.go new file mode 100644 index 000000000000..c7e4a7915906 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/docker/internal/metadata/generated_config.go @@ -0,0 +1,25 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/docker resource attributes. +type ResourceAttributesConfig struct { + HostName ResourceAttributeConfig `mapstructure:"host.name"` + OsType ResourceAttributeConfig `mapstructure:"os.type"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + HostName: ResourceAttributeConfig{ + Enabled: true, + }, + OsType: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/docker/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/docker/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..67d6f5e77de3 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/docker/internal/metadata/generated_config_test.go @@ -0,0 +1,56 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + HostName: ResourceAttributeConfig{Enabled: true}, + OsType: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + HostName: ResourceAttributeConfig{Enabled: false}, + OsType: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/docker/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/docker/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..1c0a9b15d720 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/docker/internal/metadata/testdata/config.yaml @@ -0,0 +1,13 @@ +default: +all_set: + resource_attributes: + host.name: + enabled: true + os.type: + enabled: true +none_set: + resource_attributes: + host.name: + enabled: false + os.type: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/docker/metadata.yaml b/processor/resourcedetectionprocessor/internal/docker/metadata.yaml new file mode 100644 index 000000000000..4b63358ba9db --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/docker/metadata.yaml @@ -0,0 +1,11 @@ +type: resourcedetectionprocessor/docker + +resource_attributes: + host.name: + description: The host.name + type: string + enabled: true + os.type: + description: The os.type + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/gcp/config.go b/processor/resourcedetectionprocessor/internal/gcp/config.go new file mode 100644 index 000000000000..08245a06f5be --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package gcp // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/gcp/gcp.go b/processor/resourcedetectionprocessor/internal/gcp/gcp.go index 8f56262ab419..21ff8ca297ab 100644 --- a/processor/resourcedetectionprocessor/internal/gcp/gcp.go +++ b/processor/resourcedetectionprocessor/internal/gcp/gcp.go @@ -16,6 +16,7 @@ import ( "go.uber.org/zap" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + localMetadata "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/internal/metadata" ) const ( @@ -29,16 +30,19 @@ const ( // * Google App Engine (GAE). // * Cloud Run. // * Cloud Functions. -func NewDetector(set processor.CreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { +func NewDetector(set processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) return &detector{ - logger: set.Logger, - detector: gcp.NewDetector(), + logger: set.Logger, + detector: gcp.NewDetector(), + resourceAttributes: cfg.ResourceAttributes, }, nil } type detector struct { - logger *zap.Logger - detector gcpDetector + logger *zap.Logger + detector gcpDetector + resourceAttributes localMetadata.ResourceAttributesConfig } func (d *detector) Detect(context.Context) (resource pcommon.Resource, schemaURL string, err error) { @@ -47,48 +51,110 @@ func (d *detector) Detect(context.Context) (resource pcommon.Resource, schemaURL return res, "", nil } b := &resourceBuilder{logger: d.logger, attrs: res.Attributes()} - b.attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderGCP) - b.add(conventions.AttributeCloudAccountID, d.detector.ProjectID) + if d.resourceAttributes.CloudProvider.Enabled { + b.attrs.PutStr(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderGCP) + } + if d.resourceAttributes.CloudAccountID.Enabled { + b.add(conventions.AttributeCloudAccountID, d.detector.ProjectID) + } switch d.detector.CloudPlatform() { case gcp.GKE: - b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPKubernetesEngine) - b.addZoneOrRegion(d.detector.GKEAvailabilityZoneOrRegion) - b.add(conventions.AttributeK8SClusterName, d.detector.GKEClusterName) - b.add(conventions.AttributeHostID, d.detector.GKEHostID) + if d.resourceAttributes.CloudPlatform.Enabled { + b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPKubernetesEngine) + } + if d.resourceAttributes.CloudAvailabilityZone.Enabled { + b.addZoneOrRegion(d.detector.GKEAvailabilityZoneOrRegion, d.resourceAttributes) + } + if d.resourceAttributes.K8sClusterName.Enabled { + b.add(conventions.AttributeK8SClusterName, d.detector.GKEClusterName) + } + if d.resourceAttributes.HostID.Enabled { + b.add(conventions.AttributeHostID, d.detector.GKEHostID) + } // GCEHostname is fallible on GKE, since it's not available when using workload identity. - b.addFallible(conventions.AttributeHostName, d.detector.GCEHostName) + if d.resourceAttributes.HostName.Enabled { + b.addFallible(conventions.AttributeHostName, d.detector.GCEHostName) + } case gcp.CloudRun: - b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPCloudRun) - b.add(conventions.AttributeFaaSName, d.detector.FaaSName) - b.add(conventions.AttributeFaaSVersion, d.detector.FaaSVersion) - b.add(conventions.AttributeFaaSID, d.detector.FaaSID) - b.add(conventions.AttributeCloudRegion, d.detector.FaaSCloudRegion) + if d.resourceAttributes.CloudPlatform.Enabled { + b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPCloudRun) + } + if d.resourceAttributes.FaasName.Enabled { + b.add(conventions.AttributeFaaSName, d.detector.FaaSName) + } + if d.resourceAttributes.FaasVersion.Enabled { + b.add(conventions.AttributeFaaSVersion, d.detector.FaaSVersion) + } + if d.resourceAttributes.FaasID.Enabled { + b.add(conventions.AttributeFaaSID, d.detector.FaaSID) + } + if d.resourceAttributes.CloudRegion.Enabled { + b.add(conventions.AttributeCloudRegion, d.detector.FaaSCloudRegion) + } case gcp.CloudFunctions: - b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPCloudFunctions) - b.add(conventions.AttributeFaaSName, d.detector.FaaSName) - b.add(conventions.AttributeFaaSVersion, d.detector.FaaSVersion) - b.add(conventions.AttributeFaaSID, d.detector.FaaSID) - b.add(conventions.AttributeCloudRegion, d.detector.FaaSCloudRegion) + if d.resourceAttributes.CloudPlatform.Enabled { + b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPCloudFunctions) + } + if d.resourceAttributes.FaasName.Enabled { + b.add(conventions.AttributeFaaSName, d.detector.FaaSName) + } + if d.resourceAttributes.FaasVersion.Enabled { + b.add(conventions.AttributeFaaSVersion, d.detector.FaaSVersion) + } + if d.resourceAttributes.FaasID.Enabled { + b.add(conventions.AttributeFaaSID, d.detector.FaaSID) + } + if d.resourceAttributes.CloudRegion.Enabled { + b.add(conventions.AttributeCloudRegion, d.detector.FaaSCloudRegion) + } case gcp.AppEngineFlex: - b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPAppEngine) - b.addZoneAndRegion(d.detector.AppEngineFlexAvailabilityZoneAndRegion) - b.add(conventions.AttributeFaaSName, d.detector.AppEngineServiceName) - b.add(conventions.AttributeFaaSVersion, d.detector.AppEngineServiceVersion) - b.add(conventions.AttributeFaaSID, d.detector.AppEngineServiceInstance) + if d.resourceAttributes.CloudPlatform.Enabled { + b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPAppEngine) + } + b.addZoneAndRegion(d.detector.AppEngineFlexAvailabilityZoneAndRegion, d.resourceAttributes) + if d.resourceAttributes.FaasName.Enabled { + b.add(conventions.AttributeFaaSName, d.detector.AppEngineServiceName) + } + if d.resourceAttributes.FaasVersion.Enabled { + b.add(conventions.AttributeFaaSVersion, d.detector.AppEngineServiceVersion) + } + if d.resourceAttributes.FaasID.Enabled { + b.add(conventions.AttributeFaaSID, d.detector.AppEngineServiceInstance) + } case gcp.AppEngineStandard: - b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPAppEngine) - b.add(conventions.AttributeFaaSName, d.detector.AppEngineServiceName) - b.add(conventions.AttributeFaaSVersion, d.detector.AppEngineServiceVersion) - b.add(conventions.AttributeFaaSID, d.detector.AppEngineServiceInstance) - b.add(conventions.AttributeCloudAvailabilityZone, d.detector.AppEngineStandardAvailabilityZone) - b.add(conventions.AttributeCloudRegion, d.detector.AppEngineStandardCloudRegion) + if d.resourceAttributes.CloudPlatform.Enabled { + b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPAppEngine) + } + if d.resourceAttributes.FaasName.Enabled { + b.add(conventions.AttributeFaaSName, d.detector.AppEngineServiceName) + } + if d.resourceAttributes.FaasVersion.Enabled { + b.add(conventions.AttributeFaaSVersion, d.detector.AppEngineServiceVersion) + } + if d.resourceAttributes.FaasID.Enabled { + b.add(conventions.AttributeFaaSID, d.detector.AppEngineServiceInstance) + } + if d.resourceAttributes.CloudAvailabilityZone.Enabled { + b.add(conventions.AttributeCloudAvailabilityZone, d.detector.AppEngineStandardAvailabilityZone) + } + if d.resourceAttributes.CloudRegion.Enabled { + b.add(conventions.AttributeCloudRegion, d.detector.AppEngineStandardCloudRegion) + } case gcp.GCE: - b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPComputeEngine) - b.addZoneAndRegion(d.detector.GCEAvailabilityZoneAndRegion) - b.add(conventions.AttributeHostType, d.detector.GCEHostType) - b.add(conventions.AttributeHostID, d.detector.GCEHostID) - b.add(conventions.AttributeHostName, d.detector.GCEHostName) + if d.resourceAttributes.CloudPlatform.Enabled { + b.attrs.PutStr(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPComputeEngine) + } + b.addZoneAndRegion(d.detector.GCEAvailabilityZoneAndRegion, d.resourceAttributes) + if d.resourceAttributes.HostType.Enabled { + b.add(conventions.AttributeHostType, d.detector.GCEHostType) + } + if d.resourceAttributes.HostID.Enabled { + b.add(conventions.AttributeHostID, d.detector.GCEHostID) + } + if d.resourceAttributes.HostName.Enabled { + b.add(conventions.AttributeHostName, d.detector.GCEHostName) + } default: // We don't support this platform yet, so just return with what we have } @@ -123,17 +189,21 @@ func (r *resourceBuilder) addFallible(key string, detect func() (string, error)) } // zoneAndRegion functions are expected to return zone, region, err. -func (r *resourceBuilder) addZoneAndRegion(detect func() (string, string, error)) { +func (r *resourceBuilder) addZoneAndRegion(detect func() (string, string, error), resourceAttributes localMetadata.ResourceAttributesConfig) { zone, region, err := detect() if err != nil { r.errs = append(r.errs, err) return } - r.attrs.PutStr(conventions.AttributeCloudAvailabilityZone, zone) - r.attrs.PutStr(conventions.AttributeCloudRegion, region) + if resourceAttributes.CloudAvailabilityZone.Enabled { + r.attrs.PutStr(conventions.AttributeCloudAvailabilityZone, zone) + } + if resourceAttributes.CloudRegion.Enabled { + r.attrs.PutStr(conventions.AttributeCloudRegion, region) + } } -func (r *resourceBuilder) addZoneOrRegion(detect func() (string, gcp.LocationType, error)) { +func (r *resourceBuilder) addZoneOrRegion(detect func() (string, gcp.LocationType, error), resourceAttributes localMetadata.ResourceAttributesConfig) { v, locType, err := detect() if err != nil { r.errs = append(r.errs, err) @@ -142,9 +212,13 @@ func (r *resourceBuilder) addZoneOrRegion(detect func() (string, gcp.LocationTyp switch locType { case gcp.Zone: - r.attrs.PutStr(conventions.AttributeCloudAvailabilityZone, v) + if resourceAttributes.CloudAvailabilityZone.Enabled { + r.attrs.PutStr(conventions.AttributeCloudAvailabilityZone, v) + } case gcp.Region: - r.attrs.PutStr(conventions.AttributeCloudRegion, v) + if resourceAttributes.CloudRegion.Enabled { + r.attrs.PutStr(conventions.AttributeCloudRegion, v) + } default: r.errs = append(r.errs, fmt.Errorf("location must be zone or region. Got %v", locType)) } diff --git a/processor/resourcedetectionprocessor/internal/gcp/gcp_test.go b/processor/resourcedetectionprocessor/internal/gcp/gcp_test.go index a6520744d51d..8a279264036c 100644 --- a/processor/resourcedetectionprocessor/internal/gcp/gcp_test.go +++ b/processor/resourcedetectionprocessor/internal/gcp/gcp_test.go @@ -227,9 +227,11 @@ func TestDetect(t *testing.T) { } func newTestDetector(gcpDetector *fakeGCPDetector) *detector { + resourceAttributes := CreateDefaultConfig().ResourceAttributes return &detector{ - logger: zap.NewNop(), - detector: gcpDetector, + logger: zap.NewNop(), + detector: gcpDetector, + resourceAttributes: resourceAttributes, } } diff --git a/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/generated_config.go new file mode 100644 index 000000000000..1182790753d5 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/generated_config.go @@ -0,0 +1,65 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/gcp resource attributes. +type ResourceAttributesConfig struct { + CloudAccountID ResourceAttributeConfig `mapstructure:"cloud.account.id"` + CloudAvailabilityZone ResourceAttributeConfig `mapstructure:"cloud.availability_zone"` + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` + FaasID ResourceAttributeConfig `mapstructure:"faas.id"` + FaasName ResourceAttributeConfig `mapstructure:"faas.name"` + FaasVersion ResourceAttributeConfig `mapstructure:"faas.version"` + HostID ResourceAttributeConfig `mapstructure:"host.id"` + HostName ResourceAttributeConfig `mapstructure:"host.name"` + HostType ResourceAttributeConfig `mapstructure:"host.type"` + K8sClusterName ResourceAttributeConfig `mapstructure:"k8s.cluster.name"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + CloudAccountID: ResourceAttributeConfig{ + Enabled: true, + }, + CloudAvailabilityZone: ResourceAttributeConfig{ + Enabled: true, + }, + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + FaasID: ResourceAttributeConfig{ + Enabled: true, + }, + FaasName: ResourceAttributeConfig{ + Enabled: true, + }, + FaasVersion: ResourceAttributeConfig{ + Enabled: true, + }, + HostID: ResourceAttributeConfig{ + Enabled: true, + }, + HostName: ResourceAttributeConfig{ + Enabled: true, + }, + HostType: ResourceAttributeConfig{ + Enabled: true, + }, + K8sClusterName: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..eed44a322ddf --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/generated_config_test.go @@ -0,0 +1,76 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + CloudAccountID: ResourceAttributeConfig{Enabled: true}, + CloudAvailabilityZone: ResourceAttributeConfig{Enabled: true}, + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + CloudRegion: ResourceAttributeConfig{Enabled: true}, + FaasID: ResourceAttributeConfig{Enabled: true}, + FaasName: ResourceAttributeConfig{Enabled: true}, + FaasVersion: ResourceAttributeConfig{Enabled: true}, + HostID: ResourceAttributeConfig{Enabled: true}, + HostName: ResourceAttributeConfig{Enabled: true}, + HostType: ResourceAttributeConfig{Enabled: true}, + K8sClusterName: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + CloudAccountID: ResourceAttributeConfig{Enabled: false}, + CloudAvailabilityZone: ResourceAttributeConfig{Enabled: false}, + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + CloudRegion: ResourceAttributeConfig{Enabled: false}, + FaasID: ResourceAttributeConfig{Enabled: false}, + FaasName: ResourceAttributeConfig{Enabled: false}, + FaasVersion: ResourceAttributeConfig{Enabled: false}, + HostID: ResourceAttributeConfig{Enabled: false}, + HostName: ResourceAttributeConfig{Enabled: false}, + HostType: ResourceAttributeConfig{Enabled: false}, + K8sClusterName: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..da1950ccb8d1 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/internal/metadata/testdata/config.yaml @@ -0,0 +1,53 @@ +default: +all_set: + resource_attributes: + cloud.account.id: + enabled: true + cloud.availability_zone: + enabled: true + cloud.platform: + enabled: true + cloud.provider: + enabled: true + cloud.region: + enabled: true + faas.id: + enabled: true + faas.name: + enabled: true + faas.version: + enabled: true + host.id: + enabled: true + host.name: + enabled: true + host.type: + enabled: true + k8s.cluster.name: + enabled: true +none_set: + resource_attributes: + cloud.account.id: + enabled: false + cloud.availability_zone: + enabled: false + cloud.platform: + enabled: false + cloud.provider: + enabled: false + cloud.region: + enabled: false + faas.id: + enabled: false + faas.name: + enabled: false + faas.version: + enabled: false + host.id: + enabled: false + host.name: + enabled: false + host.type: + enabled: false + k8s.cluster.name: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/gcp/metadata.yaml b/processor/resourcedetectionprocessor/internal/gcp/metadata.yaml new file mode 100644 index 000000000000..333b0385700f --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/metadata.yaml @@ -0,0 +1,51 @@ +type: resourcedetectionprocessor/gcp + +resource_attributes: + host.name: + description: The host.name + type: string + enabled: true + host.id: + description: The host.id + type: string + enabled: true + host.type: + description: The host.type + type: string + enabled: true + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true + cloud.account.id: + description: The cloud.account.id + type: string + enabled: true + cloud.region: + description: The cloud.region + type: string + enabled: true + cloud.availability_zone: + description: The cloud.availability_zone + type: string + enabled: true + faas.name: + description: faas.name + type: string + enabled: true + faas.version: + description: The faas.version + type: string + enabled: true + faas.id: + description: The faas.id + type: string + enabled: true + k8s.cluster.name: + description: The k8s.cluster.name + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/heroku/config.go b/processor/resourcedetectionprocessor/internal/heroku/config.go new file mode 100644 index 000000000000..ac1ff97f5b43 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/heroku/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package heroku // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/heroku/heroku.go b/processor/resourcedetectionprocessor/internal/heroku/heroku.go index efb0dc61c0c4..e7326ecae845 100644 --- a/processor/resourcedetectionprocessor/internal/heroku/heroku.go +++ b/processor/resourcedetectionprocessor/internal/heroku/heroku.go @@ -13,6 +13,7 @@ import ( "go.uber.org/zap" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku/internal/metadata" ) const ( @@ -28,14 +29,17 @@ const ( ) // NewDetector returns a detector which can detect resource attributes on Heroku -func NewDetector(set processor.CreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { +func NewDetector(set processor.CreateSettings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) return &detector{ - logger: set.Logger, + logger: set.Logger, + resourceAttributes: cfg.ResourceAttributes, }, nil } type detector struct { - logger *zap.Logger + logger *zap.Logger + resourceAttributes metadata.ResourceAttributesConfig } // Detect detects heroku metadata and returns a resource with the available ones @@ -48,23 +52,36 @@ func (d *detector) Detect(_ context.Context) (resource pcommon.Resource, schemaU } attrs := res.Attributes() - attrs.PutStr(conventions.AttributeCloudProvider, "heroku") - - attrs.PutStr(conventions.AttributeServiceInstanceID, dynoID) - if v, ok := os.LookupEnv("HEROKU_APP_ID"); ok { - attrs.PutStr(herokuAppID, v) + if d.resourceAttributes.CloudProvider.Enabled { + attrs.PutStr(conventions.AttributeCloudProvider, "heroku") + } + if d.resourceAttributes.ServiceInstanceID.Enabled { + attrs.PutStr(conventions.AttributeServiceInstanceID, dynoID) + } + if d.resourceAttributes.HerokuAppID.Enabled { + if v, ok := os.LookupEnv("HEROKU_APP_ID"); ok { + attrs.PutStr(herokuAppID, v) + } } - if v, ok := os.LookupEnv("HEROKU_APP_NAME"); ok { - attrs.PutStr(conventions.AttributeServiceName, v) + if d.resourceAttributes.HerokuAppName.Enabled { + if v, ok := os.LookupEnv("HEROKU_APP_NAME"); ok { + attrs.PutStr(conventions.AttributeServiceName, v) + } } - if v, ok := os.LookupEnv("HEROKU_RELEASE_CREATED_AT"); ok { - attrs.PutStr(herokuReleaseCreationTimestamp, v) + if d.resourceAttributes.HerokuReleaseCreationTimestamp.Enabled { + if v, ok := os.LookupEnv("HEROKU_RELEASE_CREATED_AT"); ok { + attrs.PutStr(herokuReleaseCreationTimestamp, v) + } } - if v, ok := os.LookupEnv("HEROKU_RELEASE_VERSION"); ok { - attrs.PutStr(conventions.AttributeServiceVersion, v) + if d.resourceAttributes.HerokuReleaseVersion.Enabled { + if v, ok := os.LookupEnv("HEROKU_RELEASE_VERSION"); ok { + attrs.PutStr(conventions.AttributeServiceVersion, v) + } } - if v, ok := os.LookupEnv("HEROKU_SLUG_COMMIT"); ok { - attrs.PutStr(herokuReleaseCommit, v) + if d.resourceAttributes.HerokuReleaseCommit.Enabled { + if v, ok := os.LookupEnv("HEROKU_SLUG_COMMIT"); ok { + attrs.PutStr(herokuReleaseCommit, v) + } } return res, conventions.SchemaURL, nil diff --git a/processor/resourcedetectionprocessor/internal/heroku/heroku_test.go b/processor/resourcedetectionprocessor/internal/heroku/heroku_test.go index b0ae1779b692..0c2b5e460b3a 100644 --- a/processor/resourcedetectionprocessor/internal/heroku/heroku_test.go +++ b/processor/resourcedetectionprocessor/internal/heroku/heroku_test.go @@ -17,7 +17,8 @@ import ( ) func TestNewDetector(t *testing.T) { - d, err := NewDetector(processortest.NewNopCreateSettings(), nil) + dcfg := CreateDefaultConfig() + d, err := NewDetector(processortest.NewNopCreateSettings(), dcfg) assert.NotNil(t, d) assert.NoError(t, err) } @@ -30,7 +31,8 @@ func TestDetectTrue(t *testing.T) { t.Setenv("HEROKU_RELEASE_VERSION", "v1") t.Setenv("HEROKU_SLUG_COMMIT", "23456") - detector := &detector{} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &detector{resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) assert.Equal(t, conventions.SchemaURL, schemaURL) require.NoError(t, err) @@ -52,7 +54,8 @@ func TestDetectTruePartial(t *testing.T) { t.Setenv("HEROKU_APP_NAME", "appname") t.Setenv("HEROKU_RELEASE_VERSION", "v1") - detector := &detector{} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &detector{resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) assert.Equal(t, conventions.SchemaURL, schemaURL) require.NoError(t, err) diff --git a/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/generated_config.go new file mode 100644 index 000000000000..8d4d9c7c74c4 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/generated_config.go @@ -0,0 +1,49 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/heroku resource attributes. +type ResourceAttributesConfig struct { + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + HerokuAppID ResourceAttributeConfig `mapstructure:"heroku.app.id"` + HerokuAppName ResourceAttributeConfig `mapstructure:"heroku.app.name"` + HerokuDynoID ResourceAttributeConfig `mapstructure:"heroku.dyno.id"` + HerokuReleaseCommit ResourceAttributeConfig `mapstructure:"heroku.release.commit"` + HerokuReleaseCreationTimestamp ResourceAttributeConfig `mapstructure:"heroku.release.creation_timestamp"` + HerokuReleaseVersion ResourceAttributeConfig `mapstructure:"heroku.release.version"` + ServiceInstanceID ResourceAttributeConfig `mapstructure:"service.instance.id"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + HerokuAppID: ResourceAttributeConfig{ + Enabled: true, + }, + HerokuAppName: ResourceAttributeConfig{ + Enabled: true, + }, + HerokuDynoID: ResourceAttributeConfig{ + Enabled: true, + }, + HerokuReleaseCommit: ResourceAttributeConfig{ + Enabled: true, + }, + HerokuReleaseCreationTimestamp: ResourceAttributeConfig{ + Enabled: true, + }, + HerokuReleaseVersion: ResourceAttributeConfig{ + Enabled: true, + }, + ServiceInstanceID: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..9e7dd9e5dc25 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/generated_config_test.go @@ -0,0 +1,68 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + CloudProvider: ResourceAttributeConfig{Enabled: true}, + HerokuAppID: ResourceAttributeConfig{Enabled: true}, + HerokuAppName: ResourceAttributeConfig{Enabled: true}, + HerokuDynoID: ResourceAttributeConfig{Enabled: true}, + HerokuReleaseCommit: ResourceAttributeConfig{Enabled: true}, + HerokuReleaseCreationTimestamp: ResourceAttributeConfig{Enabled: true}, + HerokuReleaseVersion: ResourceAttributeConfig{Enabled: true}, + ServiceInstanceID: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + CloudProvider: ResourceAttributeConfig{Enabled: false}, + HerokuAppID: ResourceAttributeConfig{Enabled: false}, + HerokuAppName: ResourceAttributeConfig{Enabled: false}, + HerokuDynoID: ResourceAttributeConfig{Enabled: false}, + HerokuReleaseCommit: ResourceAttributeConfig{Enabled: false}, + HerokuReleaseCreationTimestamp: ResourceAttributeConfig{Enabled: false}, + HerokuReleaseVersion: ResourceAttributeConfig{Enabled: false}, + ServiceInstanceID: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..a9a7a0ccc9f5 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/heroku/internal/metadata/testdata/config.yaml @@ -0,0 +1,37 @@ +default: +all_set: + resource_attributes: + cloud.provider: + enabled: true + heroku.app.id: + enabled: true + heroku.app.name: + enabled: true + heroku.dyno.id: + enabled: true + heroku.release.commit: + enabled: true + heroku.release.creation_timestamp: + enabled: true + heroku.release.version: + enabled: true + service.instance.id: + enabled: true +none_set: + resource_attributes: + cloud.provider: + enabled: false + heroku.app.id: + enabled: false + heroku.app.name: + enabled: false + heroku.dyno.id: + enabled: false + heroku.release.commit: + enabled: false + heroku.release.creation_timestamp: + enabled: false + heroku.release.version: + enabled: false + service.instance.id: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/heroku/metadata.yaml b/processor/resourcedetectionprocessor/internal/heroku/metadata.yaml new file mode 100644 index 000000000000..13e9056e856d --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/heroku/metadata.yaml @@ -0,0 +1,35 @@ +type: resourcedetectionprocessor/heroku + +resource_attributes: + cloud.provider: + description: The cloud.provider + enabled: true + type: string + heroku.app.id: + description: The heroku.app.id + enabled: true + type: string + heroku.app.name: + description: The heroku.app.name + enabled: true + type: string + heroku.dyno.id: + description: The heroku.dyno.id + enabled: true + type: string + heroku.release.commit: + description: The heroku.release.commit + enabled: true + type: string + heroku.release.creation_timestamp: + description: The heroku.release.creation_timestamp + enabled: true + type: string + heroku.release.version: + description: The heroku.release.version + enabled: true + type: string + service.instance.id: + description: The service.instance.id + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/openshift/config.go b/processor/resourcedetectionprocessor/internal/openshift/config.go index 14e89c2cfe9d..57e9a0c56b53 100644 --- a/processor/resourcedetectionprocessor/internal/openshift/config.go +++ b/processor/resourcedetectionprocessor/internal/openshift/config.go @@ -8,6 +8,8 @@ import ( "os" "go.opentelemetry.io/collector/config/configtls" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openshift/internal/metadata" ) const ( @@ -47,6 +49,8 @@ type Config struct { // TLSSettings contains TLS configurations that are specific to client // connection used to communicate with the Openshift API. TLSSettings configtls.TLSClientSetting `mapstructure:"tls"` + + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` } // MergeWithDefaults fills unset fields with default values. @@ -72,3 +76,9 @@ func (c *Config) MergeWithDefaults() error { } return nil } + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/generated_config.go new file mode 100644 index 000000000000..f11616c9b116 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/generated_config.go @@ -0,0 +1,33 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/openshift resource attributes. +type ResourceAttributesConfig struct { + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` + K8sClusterName ResourceAttributeConfig `mapstructure:"k8s.cluster.name"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + K8sClusterName: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..0ad3ed3f6212 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/generated_config_test.go @@ -0,0 +1,60 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: true}, + CloudProvider: ResourceAttributeConfig{Enabled: true}, + CloudRegion: ResourceAttributeConfig{Enabled: true}, + K8sClusterName: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + CloudPlatform: ResourceAttributeConfig{Enabled: false}, + CloudProvider: ResourceAttributeConfig{Enabled: false}, + CloudRegion: ResourceAttributeConfig{Enabled: false}, + K8sClusterName: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..8590ac7a0f78 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/openshift/internal/metadata/testdata/config.yaml @@ -0,0 +1,21 @@ +default: +all_set: + resource_attributes: + cloud.platform: + enabled: true + cloud.provider: + enabled: true + cloud.region: + enabled: true + k8s.cluster.name: + enabled: true +none_set: + resource_attributes: + cloud.platform: + enabled: false + cloud.provider: + enabled: false + cloud.region: + enabled: false + k8s.cluster.name: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/openshift/metadata.yaml b/processor/resourcedetectionprocessor/internal/openshift/metadata.yaml new file mode 100644 index 000000000000..76104ed7e54b --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/openshift/metadata.yaml @@ -0,0 +1,19 @@ +type: resourcedetectionprocessor/openshift + +resource_attributes: + cloud.provider: + description: The cloud.provider + type: string + enabled: true + cloud.platform: + description: The cloud.platform + type: string + enabled: true + cloud.region: + description: The cloud.region + type: string + enabled: true + k8s.cluster.name: + description: The k8s.cluster.name + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/openshift/openshift.go b/processor/resourcedetectionprocessor/internal/openshift/openshift.go index bdc66a80b9e0..b0e7cf245779 100644 --- a/processor/resourcedetectionprocessor/internal/openshift/openshift.go +++ b/processor/resourcedetectionprocessor/internal/openshift/openshift.go @@ -14,6 +14,7 @@ import ( ocp "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/openshift" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openshift/internal/metadata" ) const ( @@ -35,14 +36,16 @@ func NewDetector(set processor.CreateSettings, dcfg internal.DetectorConfig) (in } return &detector{ - logger: set.Logger, - provider: ocp.NewProvider(userCfg.Address, userCfg.Token, tlsCfg), + logger: set.Logger, + provider: ocp.NewProvider(userCfg.Address, userCfg.Token, tlsCfg), + resourceAttributes: userCfg.ResourceAttributes, }, nil } type detector struct { - logger *zap.Logger - provider ocp.Provider + logger *zap.Logger + provider ocp.Provider + resourceAttributes metadata.ResourceAttributesConfig } func (d *detector) Detect(ctx context.Context) (resource pcommon.Resource, schemaURL string, err error) { @@ -83,17 +86,25 @@ func (d *detector) Detect(ctx context.Context) (resource pcommon.Resource, schem region = strings.ToLower(infra.Status.PlatformStatus.OpenStack.CloudName) } - if infra.Status.InfrastructureName != "" { - attrs.PutStr(conventions.AttributeK8SClusterName, infra.Status.InfrastructureName) + if d.resourceAttributes.K8sClusterName.Enabled { + if infra.Status.InfrastructureName != "" { + attrs.PutStr(conventions.AttributeK8SClusterName, infra.Status.InfrastructureName) + } } - if provider != "" { - attrs.PutStr(conventions.AttributeCloudProvider, provider) + if d.resourceAttributes.CloudProvider.Enabled { + if provider != "" { + attrs.PutStr(conventions.AttributeCloudProvider, provider) + } } - if platform != "" { - attrs.PutStr(conventions.AttributeCloudPlatform, platform) + if d.resourceAttributes.CloudPlatform.Enabled { + if platform != "" { + attrs.PutStr(conventions.AttributeCloudPlatform, platform) + } } - if region != "" { - attrs.PutStr(conventions.AttributeCloudRegion, region) + if d.resourceAttributes.CloudRegion.Enabled { + if region != "" { + attrs.PutStr(conventions.AttributeCloudRegion, region) + } } // TODO(frzifus): support conventions openshift and kubernetes cluster version. diff --git a/processor/resourcedetectionprocessor/internal/openshift/openshift_test.go b/processor/resourcedetectionprocessor/internal/openshift/openshift_test.go index 70b41ae02755..5b7193350cf2 100644 --- a/processor/resourcedetectionprocessor/internal/openshift/openshift_test.go +++ b/processor/resourcedetectionprocessor/internal/openshift/openshift_test.go @@ -53,6 +53,7 @@ func (m *mockProvider) Infrastructure(context.Context) (*ocp.InfrastructureAPIRe } func newTestDetector(t *testing.T, res *providerResponse, ocpCVErr, k8sCVErr, infraErr error) internal.Detector { + resourceAttributes := CreateDefaultConfig().ResourceAttributes return &detector{ logger: zaptest.NewLogger(t), provider: &mockProvider{ @@ -61,6 +62,7 @@ func newTestDetector(t *testing.T, res *providerResponse, ocpCVErr, k8sCVErr, in k8sCVErr: k8sCVErr, infraErr: infraErr, }, + resourceAttributes: resourceAttributes, } } diff --git a/processor/resourcedetectionprocessor/internal/system/config.go b/processor/resourcedetectionprocessor/internal/system/config.go index b4680ca0120a..6762746999f2 100644 --- a/processor/resourcedetectionprocessor/internal/system/config.go +++ b/processor/resourcedetectionprocessor/internal/system/config.go @@ -3,7 +3,11 @@ package system // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system" -import "fmt" +import ( + "fmt" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system/internal/metadata" +) // Config defines user-specified configurations unique to the system detector type Config struct { @@ -11,6 +15,8 @@ type Config struct { // In case of the error in fetching hostname from source, // the next source from the list will be considered.(**default**: `["dns", "os"]`) HostnameSources []string `mapstructure:"hostname_sources"` + + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` } // Validate config @@ -23,3 +29,9 @@ func (cfg *Config) Validate() error { } return nil } + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_config.go b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_config.go new file mode 100644 index 000000000000..0da3b1308527 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_config.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/system resource attributes. +type ResourceAttributesConfig struct { + HostID ResourceAttributeConfig `mapstructure:"host.id"` + HostName ResourceAttributeConfig `mapstructure:"host.name"` + OsType ResourceAttributeConfig `mapstructure:"os.type"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + HostID: ResourceAttributeConfig{ + Enabled: true, + }, + HostName: ResourceAttributeConfig{ + Enabled: true, + }, + OsType: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_config_test.go b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_config_test.go new file mode 100644 index 000000000000..c936169bb72b --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_config_test.go @@ -0,0 +1,58 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + HostID: ResourceAttributeConfig{Enabled: true}, + HostName: ResourceAttributeConfig{Enabled: true}, + OsType: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + HostID: ResourceAttributeConfig{Enabled: false}, + HostName: ResourceAttributeConfig{Enabled: false}, + OsType: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(tt.name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/system/internal/metadata/testdata/config.yaml b/processor/resourcedetectionprocessor/internal/system/internal/metadata/testdata/config.yaml new file mode 100644 index 000000000000..67f6e661e937 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/system/internal/metadata/testdata/config.yaml @@ -0,0 +1,17 @@ +default: +all_set: + resource_attributes: + host.id: + enabled: true + host.name: + enabled: true + os.type: + enabled: true +none_set: + resource_attributes: + host.id: + enabled: false + host.name: + enabled: false + os.type: + enabled: false diff --git a/processor/resourcedetectionprocessor/internal/system/metadata.yaml b/processor/resourcedetectionprocessor/internal/system/metadata.yaml new file mode 100644 index 000000000000..570d25e93036 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/system/metadata.yaml @@ -0,0 +1,15 @@ +type: resourcedetectionprocessor/system + +resource_attributes: + host.name: + description: The host.name + type: string + enabled: true + host.id: + description: The host.id + type: string + enabled: true + os.type: + description: The os.type + type: string + enabled: true \ No newline at end of file diff --git a/processor/resourcedetectionprocessor/internal/system/system.go b/processor/resourcedetectionprocessor/internal/system/system.go index 20721402aaca..82162e747c9c 100644 --- a/processor/resourcedetectionprocessor/internal/system/system.go +++ b/processor/resourcedetectionprocessor/internal/system/system.go @@ -15,6 +15,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/system" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system/internal/metadata" ) const ( @@ -33,9 +34,10 @@ var _ internal.Detector = (*Detector)(nil) // Detector is a system metadata detector type Detector struct { - provider system.Provider - logger *zap.Logger - hostnameSources []string + provider system.Provider + logger *zap.Logger + hostnameSources []string + resourceAttributes metadata.ResourceAttributesConfig } // NewDetector creates a new system metadata detector @@ -45,7 +47,7 @@ func NewDetector(p processor.CreateSettings, dcfg internal.DetectorConfig) (inte cfg.HostnameSources = []string{"dns", "os"} } - return &Detector{provider: system.NewProvider(), logger: p.Logger, hostnameSources: cfg.HostnameSources}, nil + return &Detector{provider: system.NewProvider(), logger: p.Logger, hostnameSources: cfg.HostnameSources, resourceAttributes: cfg.ResourceAttributes}, nil } // Detect detects system metadata and returns a resource with the available ones @@ -69,9 +71,15 @@ func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schem getHostFromSource := hostnameSourcesMap[source] hostname, err = getHostFromSource(d) if err == nil { - attrs.PutStr(conventions.AttributeHostName, hostname) - attrs.PutStr(conventions.AttributeOSType, osType) - attrs.PutStr(conventions.AttributeHostID, hostID) + if d.resourceAttributes.HostName.Enabled { + attrs.PutStr(conventions.AttributeHostName, hostname) + } + if d.resourceAttributes.OsType.Enabled { + attrs.PutStr(conventions.AttributeOSType, osType) + } + if d.resourceAttributes.HostID.Enabled { + attrs.PutStr(conventions.AttributeHostID, hostID) + } return res, conventions.SchemaURL, nil } diff --git a/processor/resourcedetectionprocessor/internal/system/system_test.go b/processor/resourcedetectionprocessor/internal/system/system_test.go index ea50a0e9de89..b93a5906eed7 100644 --- a/processor/resourcedetectionprocessor/internal/system/system_test.go +++ b/processor/resourcedetectionprocessor/internal/system/system_test.go @@ -88,7 +88,8 @@ func TestDetectFQDNAvailable(t *testing.T) { md.On("OSType").Return("darwin", nil) md.On("HostID").Return("2", nil) - detector := &Detector{provider: md, logger: zap.NewNop(), hostnameSources: []string{"dns"}} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: md, logger: zap.NewNop(), hostnameSources: []string{"dns"}, resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) require.NoError(t, err) assert.Equal(t, conventions.SchemaURL, schemaURL) @@ -112,7 +113,8 @@ func TestFallbackHostname(t *testing.T) { mdHostname.On("OSType").Return("darwin", nil) mdHostname.On("HostID").Return("3", nil) - detector := &Detector{provider: mdHostname, logger: zap.NewNop(), hostnameSources: []string{"dns", "os"}} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mdHostname, logger: zap.NewNop(), hostnameSources: []string{"dns", "os"}, resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) require.NoError(t, err) assert.Equal(t, conventions.SchemaURL, schemaURL) @@ -133,7 +135,8 @@ func TestUseHostname(t *testing.T) { mdHostname.On("OSType").Return("darwin", nil) mdHostname.On("HostID").Return("1", nil) - detector := &Detector{provider: mdHostname, logger: zap.NewNop(), hostnameSources: []string{"os"}} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mdHostname, logger: zap.NewNop(), hostnameSources: []string{"os"}, resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) require.NoError(t, err) assert.Equal(t, conventions.SchemaURL, schemaURL) @@ -156,7 +159,8 @@ func TestDetectError(t *testing.T) { mdFQDN.On("Hostname").Return("", errors.New("err")) mdFQDN.On("HostID").Return("", errors.New("err")) - detector := &Detector{provider: mdFQDN, logger: zap.NewNop(), hostnameSources: []string{"dns"}} + resourceAttributes := CreateDefaultConfig().ResourceAttributes + detector := &Detector{provider: mdFQDN, logger: zap.NewNop(), hostnameSources: []string{"dns"}, resourceAttributes: resourceAttributes} res, schemaURL, err := detector.Detect(context.Background()) assert.Error(t, err) assert.Equal(t, "", schemaURL) @@ -168,7 +172,7 @@ func TestDetectError(t *testing.T) { mdHostname.On("Hostname").Return("", errors.New("err")) mdHostname.On("HostID").Return("", errors.New("err")) - detector = &Detector{provider: mdHostname, logger: zap.NewNop(), hostnameSources: []string{"os"}} + detector = &Detector{provider: mdHostname, logger: zap.NewNop(), hostnameSources: []string{"os"}, resourceAttributes: resourceAttributes} res, schemaURL, err = detector.Detect(context.Background()) assert.Error(t, err) assert.Equal(t, "", schemaURL) @@ -180,7 +184,7 @@ func TestDetectError(t *testing.T) { mdOSType.On("OSType").Return("", errors.New("err")) mdOSType.On("HostID").Return("", errors.New("err")) - detector = &Detector{provider: mdOSType, logger: zap.NewNop(), hostnameSources: []string{"dns"}} + detector = &Detector{provider: mdOSType, logger: zap.NewNop(), hostnameSources: []string{"dns"}, resourceAttributes: resourceAttributes} res, schemaURL, err = detector.Detect(context.Background()) assert.Error(t, err) assert.Equal(t, "", schemaURL) diff --git a/processor/resourcedetectionprocessor/testdata/config.yaml b/processor/resourcedetectionprocessor/testdata/config.yaml index 9e637659fd14..42acce86c364 100644 --- a/processor/resourcedetectionprocessor/testdata/config.yaml +++ b/processor/resourcedetectionprocessor/testdata/config.yaml @@ -62,3 +62,20 @@ resourcedetection/invalid: override: false system: hostname_sources: [invalid_source] + +resourcedetection/resourceattributes: + detectors: [system, ec2] + timeout: 2s + override: false + ec2: + resource_attributes: + host.name: + enabled: false + host.id: + enabled: false + host.type: + enabled: false + system: + resource_attributes: + os.type: + enabled: false \ No newline at end of file