diff --git a/.chloggen/awsemf_defaultrollup.yaml b/.chloggen/awsemf_defaultrollup.yaml new file mode 100755 index 000000000000..ffd973260f01 --- /dev/null +++ b/.chloggen/awsemf_defaultrollup.yaml @@ -0,0 +1,22 @@ +# 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: awsemfexporter + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add awsemf.nodimrollupdefault feature gate to aws emf exporter + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [23997] + +# (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: | + Enabling the awsemf.nodimrollupdefault will cause the AWS EMF Exporter to use the NoDimensionRollup configuration + setting by default instead of ZeroAndSingleDimensionRollup. diff --git a/exporter/awsemfexporter/README.md b/exporter/awsemfexporter/README.md index 83221bca04b7..e80b62911901 100644 --- a/exporter/awsemfexporter/README.md +++ b/exporter/awsemfexporter/README.md @@ -30,8 +30,8 @@ The following exporter configuration parameters are supported. |:---------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------- | | `log_group_name` | Customized log group name which supports `{ClusterName}` and `{TaskId}` placeholders. One valid example is `/aws/metrics/{ClusterName}`. It will search for `ClusterName` (or `aws.ecs.cluster.name`) resource attribute in the metrics data and replace with the actual cluster name. If none of them are found in the resource attribute map, `{ClusterName}` will be replaced by `undefined`. Similar way, for the `{TaskId}`, it searches for `TaskId` (or `aws.ecs.task.id`) key in the resource attribute map. For `{NodeName}`, it searches for `NodeName` (or `k8s.node.name`) |"/metrics/default"| | `log_stream_name` | Customized log stream name which supports `{TaskId}`, `{ClusterName}`, `{NodeName}`, `{ContainerInstanceId}`, and `{TaskDefinitionFamily}` placeholders. One valid example is `{TaskId}`. It will search for `TaskId` (or `aws.ecs.task.id`) resource attribute in the metrics data and replace with the actual task id. If none of them are found in the resource attribute map, `{TaskId}` will be replaced by `undefined`. Similarly, for the `{TaskDefinitionFamily}`, it searches for `TaskDefinitionFamily` (or `aws.ecs.task.family`). For the `{ClusterName}`, it searches for `ClusterName` (or `aws.ecs.cluster.name`). For `{NodeName}`, it searches for `NodeName` (or `k8s.node.name`). For `{ContainerInstanceId}`, it searches for `ContainerInstanceId` (or `aws.ecs.container.instance.id`). (Note: ContainerInstanceId (or `aws.ecs.container.instance.id`) only works for AWS ECS EC2 launch type. |"otel-stream"| -| `log_retention` | LogRetention is the option to set the log retention policy for only newly created CloudWatch Log Groups. Defaults to Never Expire if not specified or set to 0. Possible values for retention in days are 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, or 3653. |"Never Expire"| -| `tags` | Tags is the option to set tags for the CloudWatch Log Group. If specified, please add at most 50 tags. Input is a string to string map like so: { 'key': 'value' }. Keys must be between 1-128 characters and follow the regex pattern: `^([\p{L}\p{Z}\p{N}_.:/=+\-@]+)$`(alphanumerics, whitespace, and _.:/=+-!). Values must be between 1-256 characters and follow the regex pattern: `^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`(alphanumerics, whitespace, and _.:/=+-!). [Link to tagging restrictions](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html#:~:text=Required%3A%20Yes-,tags,-The%20key%2Dvalue) | No tags set | +| `log_retention` | LogRetention is the option to set the log retention policy for only newly created CloudWatch Log Groups. Defaults to Never Expire if not specified or set to 0. Possible values for retention in days are 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, or 3653. |"Never Expire"| +| `tags` | Tags is the option to set tags for the CloudWatch Log Group. If specified, please add at most 50 tags. Input is a string to string map like so: { 'key': 'value' }. Keys must be between 1-128 characters and follow the regex pattern: `^([\p{L}\p{Z}\p{N}_.:/=+\-@]+)$`(alphanumerics, whitespace, and _.:/=+-!). Values must be between 1-256 characters and follow the regex pattern: `^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`(alphanumerics, whitespace, and _.:/=+-!). [Link to tagging restrictions](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html#:~:text=Required%3A%20Yes-,tags,-The%20key%2Dvalue) | No tags set | | `namespace` | Customized CloudWatch metrics namespace | "default" | | `endpoint` | Optionally override the default CloudWatch service endpoint. | | | `no_verify_ssl` | Enable or disable TLS certificate verification. | false | @@ -39,10 +39,10 @@ The following exporter configuration parameters are supported. | `region` | Send Structured Logs to AWS CloudWatch in a specific region. If this field is not present in config, environment variable "AWS_REGION" can then be used to set region. | determined by metadata | | `role_arn` | IAM role to upload segments to a different account. | | | `max_retries` | Maximum number of retries before abandoning an attempt to post data. | 1 | -| `dimension_rollup_option` | DimensionRollupOption is the option for metrics dimension rollup. Three options are available: `NoDimensionRollup`, `SingleDimensionRollupOnly` and `ZeroAndSingleDimensionRollup` |"ZeroAndSingleDimensionRollup" (Enable both zero dimension rollup and single dimension rollup)| +| `dimension_rollup_option` | DimensionRollupOption is the option for metrics dimension rollup. Three options are available: `NoDimensionRollup`, `SingleDimensionRollupOnly` and `ZeroAndSingleDimensionRollup`. The default value is `ZeroAndSingleDimensionRollup`. Enabling feature gate `awsemf.nodimrollupdefault` will set default to `NoDimensionRollup`. |"ZeroAndSingleDimensionRollup" (Enable both zero dimension rollup and single dimension rollup)| | `resource_to_telemetry_conversion` | "resource_to_telemetry_conversion" is the option for converting resource attributes to telemetry attributes. It has only one config onption- `enabled`. For metrics, if `enabled=true`, all the resource attributes will be converted to metric labels by default. See `Resource Attributes to Metric Labels` section below for examples. | `enabled=false` | | `output_destination` | "output_destination" is an option to specify the EMFExporter output. Currently, two options are available. "cloudwatch" or "stdout" | `cloudwatch` | -| `detailed_metrics` | Retain detailed datapoint values in exported metrics (e.g instead of exporting a quantile as a statistical value, preserve the quantile's population) | `false` | +| `detailed_metrics` | Retain detailed datapoint values in exported metrics (e.g instead of exporting a quantile as a statistical value, preserve the quantile's population) | `false` | | `parse_json_encoded_attr_values` | List of attribute keys whose corresponding values are JSON-encoded strings and will be converted to JSON structures in emf logs. For example, the attribute string value "{\\"x\\":5,\\"y\\":6}" will be converted to a json object: ```{"x": 5, "y": 6}``` | [ ] | | [`metric_declarations`](#metric_declaration) | List of rules for filtering exported metrics and their dimensions. | [ ] | | [`metric_descriptors`](#metric_descriptor) | List of rules for inserting or updating metric descriptors. | [ ] | diff --git a/exporter/awsemfexporter/config_test.go b/exporter/awsemfexporter/config_test.go index 3ba599d63382..21d664f23d85 100644 --- a/exporter/awsemfexporter/config_test.go +++ b/exporter/awsemfexporter/config_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/featuregate" "go.uber.org/zap" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsemfexporter/internal/metadata" @@ -260,3 +261,12 @@ func TestValidateTags(t *testing.T) { }) } } + +func TestNoDimensionRollupFeatureGate(t *testing.T) { + err := featuregate.GlobalRegistry().Set("awsemf.nodimrollupdefault", true) + require.NoError(t, err) + cfg := createDefaultConfig() + + assert.Equal(t, cfg.(*Config).DimensionRollupOption, "NoDimensionRollup") + _ = featuregate.GlobalRegistry().Set("awsemf.nodimrollupdefault", false) +} diff --git a/exporter/awsemfexporter/emf_exporter.go b/exporter/awsemfexporter/emf_exporter.go index f861c026e9d7..76d2fb34ce70 100644 --- a/exporter/awsemfexporter/emf_exporter.go +++ b/exporter/awsemfexporter/emf_exporter.go @@ -71,6 +71,10 @@ func newEmfExporter(config *Config, set exporter.CreateSettings) (*emfExporter, pusherMap: map[cwlogs.PusherKey]cwlogs.Pusher{}, } + config.logger.Warn("the default value for DimensionRollupOption will be changing to NoDimensionRollup" + + "in a future release. See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/23997 for more" + + "information") + return emfExporter, nil } diff --git a/exporter/awsemfexporter/emf_exporter_test.go b/exporter/awsemfexporter/emf_exporter_test.go index 67e2739516b0..93a0d2e37261 100644 --- a/exporter/awsemfexporter/emf_exporter_test.go +++ b/exporter/awsemfexporter/emf_exporter_test.go @@ -589,6 +589,12 @@ func TestNewExporterWithMetricDeclarations(t *testing.T) { // Test output warning logs expectedLogs := []observer.LoggedEntry{ + { + Entry: zapcore.Entry{Level: zap.WarnLevel, Message: "the default value for DimensionRollupOption will be changing to NoDimensionRollup" + + "in a future release. See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/23997 for more" + + "information"}, + Context: []zapcore.Field{}, + }, { Entry: zapcore.Entry{Level: zap.WarnLevel, Message: "Dropped metric declaration."}, Context: []zapcore.Field{zap.Error(errors.New("invalid metric declaration: no metric name selectors defined"))}, @@ -598,7 +604,7 @@ func TestNewExporterWithMetricDeclarations(t *testing.T) { Context: []zapcore.Field{zap.String("dimensions", "a,b,c,d,e,f,g,h,i,j,k")}, }, } - assert.Equal(t, 2, logs.Len()) + assert.Equal(t, len(expectedLogs), logs.Len()) assert.Equal(t, expectedLogs, logs.AllUntimed()) } diff --git a/exporter/awsemfexporter/factory.go b/exporter/awsemfexporter/factory.go index 8741cb771e56..d0cf78a5dd2d 100644 --- a/exporter/awsemfexporter/factory.go +++ b/exporter/awsemfexporter/factory.go @@ -9,6 +9,7 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper" + "go.opentelemetry.io/collector/featuregate" "go.uber.org/zap" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsemfexporter/internal/metadata" @@ -16,6 +17,11 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry" ) +var defaultNoRollupfg = featuregate.GlobalRegistry().MustRegister("awsemf.nodimrollupdefault", featuregate.StageAlpha, + featuregate.WithRegisterFromVersion("v0.83.0"), + featuregate.WithRegisterDescription("Changes the default AWS EMF Exporter Dimension rollup option to "+ + "NoDimensionRollup")) + // NewFactory creates a factory for AWS EMF exporter. func NewFactory() exporter.Factory { return exporter.NewFactory( @@ -26,12 +32,18 @@ func NewFactory() exporter.Factory { // CreateDefaultConfig creates the default configuration for exporter. func createDefaultConfig() component.Config { + var defaultDimensionRollupOption string + if defaultNoRollupfg.IsEnabled() { + defaultDimensionRollupOption = "NoDimensionRollup" + } else { + defaultDimensionRollupOption = "ZeroAndSingleDimensionRollup" + } return &Config{ AWSSessionSettings: awsutil.CreateDefaultSessionConfig(), LogGroupName: "", LogStreamName: "", Namespace: "", - DimensionRollupOption: "ZeroAndSingleDimensionRollup", + DimensionRollupOption: defaultDimensionRollupOption, Version: "1", RetainInitialValueOfDeltaMetric: false, OutputDestination: "cloudwatch", diff --git a/exporter/awsemfexporter/go.mod b/exporter/awsemfexporter/go.mod index 2390337f6885..2d75f11e2d06 100644 --- a/exporter/awsemfexporter/go.mod +++ b/exporter/awsemfexporter/go.mod @@ -17,6 +17,7 @@ require ( go.opentelemetry.io/collector/confmap v0.82.0 go.opentelemetry.io/collector/consumer v0.82.0 go.opentelemetry.io/collector/exporter v0.82.0 + go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.opentelemetry.io/collector/semconv v0.82.0 go.uber.org/zap v1.25.0 @@ -45,7 +46,6 @@ require ( go.opentelemetry.io/collector v0.82.0 // indirect go.opentelemetry.io/collector/config/configtelemetry v0.82.0 // indirect go.opentelemetry.io/collector/extension v0.82.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/processor v0.82.0 // indirect go.opentelemetry.io/collector/receiver v0.82.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect