Skip to content

Add root-level cluster_name and standardize collection_interval for OpenTelemetry features#2189

Open
Paamicky wants to merge 13 commits into
mainfrom
zeus-V2-json-configs
Open

Add root-level cluster_name and standardize collection_interval for OpenTelemetry features#2189
Paamicky wants to merge 13 commits into
mainfrom
zeus-V2-json-configs

Conversation

@Paamicky

@Paamicky Paamicky commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Description of the issue

The OpenTelemetry config section had two inconsistencies: cluster_name was required per-component, forcing customers to repeat the same cluster value for every feature, and the collection interval field name differed across features (metrics_collection_interval vs collection_interval). This has been updated to use the newer version collection_interval.

Description of changes

  • Root-level cluster_name: Moved to opentelemetry.cluster_name. A single value now applies to all features (Container Insights, Prometheus, Host Metrics, OTLP). Container Insights and Prometheus require it; Host Metrics and OTLP apply it when present.
  • Standardized collection_interval: All OpenTelemetry features now use collection_interval with a 30-second default. Host Metrics renamed from metrics_collection_interval. Database Insights retains its own hardcoded intervals.
  • Centralized validation: ClusterNameRegex moved to the common package. GetOtelClusterName and GetCollectionInterval added as shared helpers.
  • Schema updated: schema.json reflects the new root-level cluster_name field and standardized collection_interval across features.
  • Renamed mode to role in the Container Insights JSON config field (opentelemetry.collect.container_insights.role) to align with the CWAGENT_ROLE environment
    variable naming.

Tests

  • Unit tests for GetOtelClusterName verifies root-level reads, env var is not used as fallback, empty config returns empty
  • Unit tests for GetCollectionInterval verifies feature-level override, 30s default, zero/negative values ignored
  • Updated golden file tests and confirm set_cluster_name processor appears in all applicable pipelines
  • All existing translator tests pass

License

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@Paamicky Paamicky added the ready for testing Indicates this PR is ready for integration tests to run label Jul 9, 2026
@Paamicky
Paamicky marked this pull request as ready for review July 9, 2026 16:17
@Paamicky
Paamicky requested a review from a team as a code owner July 9, 2026 16:17
@Paamicky Paamicky changed the title Add root-level cluster_name and standardize collection_interval for … Add root-level cluster_name and standardize collection_interval for OpenTelemetry features Jul 9, 2026
@Paamicky
Paamicky removed the request for review from a team July 10, 2026 16:54
Comment on lines +1020 to +1029
transform/set_cluster_name:
error_mode: ignore
flatten_data: false
log_statements:
- context: resource
error_mode: ignore
statements:
- set(resource.attributes["k8s.cluster.name"], "TestCluster")
metric_statements: []
trace_statements: []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this have resource statements for each of the resource types? I see the same processor is being used in metric pipelines as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. otlp logs now uses its own processor (transform/set_cluster_name_logs) so it doesn't overwrite the metric_statements used by the metrics pipelines

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't they share a single transform processor?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. set_cluster_name now registers with both metric_statements and log_statements in a single processor. Pipelines will use statements relevant to its signal.

WithTraceResourceStatements is not yet supported in the transform processor.

// Traces are not handled: WithTraceResourceStatements is not yet supported.
// Traces sent via OTLP on EKS should include k8s.cluster.name from the SDK.

This will need a separate PR if we want to add it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add WithTraceResourceStatements or a WithResourceStatements to that transformprocessor translator so it's consistent?

@Paamicky
Paamicky force-pushed the zeus-V2-json-configs branch 2 times, most recently from 23cab82 to 59cea26 Compare July 10, 2026 20:25
mitali-salvi
mitali-salvi previously approved these changes Jul 13, 2026

// GetCollectionInterval returns the collection interval for an OpenTelemetry feature.
// It checks the feature-specific collection_interval field. Default is 30s.
func GetCollectionInterval(conf *confmap.Conf, featureKey string) time.Duration {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does the exact same thing as GetOrDefaultDuration

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah removed to use the already existing function: GetOrDefaultDuration


// GetOtelClusterName returns the cluster name for OpenTelemetry-based features.
// It reads exclusively from opentelemetry::cluster_name.
func GetOtelClusterName(conf *confmap.Conf) string {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need a separate function for this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the function wrapper and defined inline at each call site.

}

// DefaultCollectionInterval is the default collection interval for OpenTelemetry-based features.
const DefaultCollectionInterval = 30 * time.Second

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't define this here. It doesn't apply to all cases of collection interval. It's only for the opentelemetry pipelines.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to a local constant in each package that uses it.

@Paamicky
Paamicky force-pushed the zeus-V2-json-configs branch from d7d65ea to 23ade6b Compare July 14, 2026 20:43
"opentelemetry": map[string]interface{}{
"collect": map[string]interface{}{
"container_insights": map[string]interface{}{
"cluster_name": "test-cluster",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like the cluster_name field is still showing up under container_insights section instead of showing up under opentelemetry/collect section, mind updating this please ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@Paamicky
Paamicky force-pushed the zeus-V2-json-configs branch from a522694 to 939e783 Compare July 16, 2026 19:04
@Paamicky
Paamicky force-pushed the zeus-V2-json-configs branch from 5689959 to 65265df Compare July 16, 2026 19:12
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Binary Size Report

linux/amd64

Binary PR vs main (5d99671) vs v1.300070.0
amazon-cloudwatch-agent 233.3 MB +0 B ${\color{red}▲}$ +2.0 MB (+0.8%)
amazon-cloudwatch-agent-config-wizard 2.0 MB +0 B ${\color{red}▲}$ +86.0 KB (+4.5%)
config-downloader 2.0 MB +0 B ${\color{red}▲}$ +86.0 KB (+4.5%)
config-translator 2.0 MB +0 B ${\color{red}▲}$ +86.0 KB (+4.5%)
start-amazon-cloudwatch-agent 2.5 MB +0 B ${\color{red}▲}$ +81.9 KB (+3.4%)
workload-discovery 3.0 MB +0 B ${\color{red}▲}$ +86.0 KB (+2.9%)
Total 244.8 MB +0 B ${\color{red}▲}$ +2.4 MB (+1.0%)
linux/amd64 amazon-cloudwatch-agent (last 9 main commits + this PR)

 233 ┤                                        
     ┤    ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ███ ███ 
     ┤    ███ ███ ███ ███ ███ ███ ███ ███ ███ 
     ┤    ███ ███ ███ ███ ███ ███ ███ ███ ███ 
     ┤    ███ ███ ███ ███ ███ ███ ███ ███ ███ 
     ┤    ███ ███ ███ ███ ███ ███ ███ ███ ███ 
     ┤    ███ ███ ███ ███ ███ ███ ███ ███ ███ 
     ┤    ███ ███ ███ ███ ███ ███ ███ ███ ███ 
 231 ┤▄▄▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ 
 MB  └────────────────────────────────────────
      a53d263                             PR

Notable changes:

linux/arm64
Binary PR vs main (5d99671) vs v1.300070.0
amazon-cloudwatch-agent 212.2 MB +0 B ${\color{red}▲}$ +720.9 KB (+0.3%)
amazon-cloudwatch-agent-config-wizard 2.0 MB +0 B ${\color{green}▼}$ 22 B (-0.0%)
config-downloader 2.0 MB +0 B ${\color{green}▼}$ 22 B (-0.0%)
config-translator 2.0 MB +0 B ${\color{green}▼}$ 22 B (-0.0%)
start-amazon-cloudwatch-agent 2.4 MB +0 B ${\color{red}▲}$ +65.5 KB (+2.8%)
workload-discovery 2.9 MB +0 B ${\color{red}▲}$ +65.5 KB (+2.3%)
Total 223.5 MB +0 B ${\color{red}▲}$ +851.8 KB (+0.4%)
windows/amd64
Binary PR vs main (5d99671) vs v1.300070.0
amazon-cloudwatch-agent.exe 236.3 MB ${\color{red}▲}$ +7.7 KB (+0.0%) ${\color{red}▲}$ +2.1 MB (+0.9%)
amazon-cloudwatch-agent-config-wizard.exe 2.1 MB +0 B ${\color{red}▲}$ +130.6 KB (+6.5%)
config-downloader.exe 2.1 MB +0 B ${\color{red}▲}$ +130.0 KB (+6.5%)
config-translator.exe 2.1 MB +0 B ${\color{red}▲}$ +130.6 KB (+6.5%)
start-amazon-cloudwatch-agent.exe 2.3 MB +0 B ${\color{red}▲}$ +112.1 KB (+5.2%)
workload-discovery.exe 2.9 MB +0 B ${\color{red}▲}$ +91.6 KB (+3.3%)
Total 247.9 MB ${\color{red}▲}$ +7.7 KB (+0.0%) ${\color{red}▲}$ +2.7 MB (+1.1%)
Investigating size changes

Use go-size-analyzer to compare binaries:

GOEXPERIMENT=jsonv2 go install github.com/Zxilly/go-size-analyzer/cmd/gsa@latest
gsa diff --old <baseline-binary> --new <new-binary>

mitali-salvi
mitali-salvi previously approved these changes Jul 17, 2026
Comment on lines +1020 to +1029
transform/set_cluster_name:
error_mode: ignore
flatten_data: false
log_statements:
- context: resource
error_mode: ignore
statements:
- set(resource.attributes["k8s.cluster.name"], "TestCluster")
metric_statements: []
trace_statements: []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add WithTraceResourceStatements or a WithResourceStatements to that transformprocessor translator so it's consistent?

Comment thread translator/translate/otel/common/common.go Outdated
Comment thread translator/translate/otel/pipeline/opentelemetry/otlp/translator.go Outdated
@Paamicky
Paamicky force-pushed the zeus-V2-json-configs branch from 10d20a4 to 8ca11d7 Compare July 17, 2026 21:35
Comment on lines 1553 to 1562
transform/set_cluster_name:
error_mode: ignore
flatten_data: false
log_statements: []
metric_statements:
metric_statements: []
trace_statements:
- context: resource
error_mode: ignore
statements:
- set(resource.attributes["k8s.cluster.name"], "TestCluster")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't quite right. I would expect to see the same statement in each of the *_statements sections.

    transform/set_cluster_name:
        error_mode: ignore
        flatten_data: false
        log_statements:
            - context: resource
              error_mode: ignore
              statements:
                - set(resource.attributes["k8s.cluster.name"], "TestCluster")
        metric_statements:
            - context: resource
              error_mode: ignore
              statements:
                - set(resource.attributes["k8s.cluster.name"], "TestCluster")
        trace_statements:
            - context: resource
              error_mode: ignore
              statements:
                - set(resource.attributes["k8s.cluster.name"], "TestCluster")

"type": "object",
"properties": {
"cluster_name": {
"description": "The name of the EKS/AKS cluster. Applied to all components under opentelemetry.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
"description": "The name of the EKS/AKS cluster. Applied to all components under opentelemetry.",
"description": "The name of the k8s cluster. Applied to all telemetry collected under opentelemetry.",

stmt := fmt.Sprintf(`set(resource.attributes["k8s.cluster.name"], "%s")`, clusterName)
processors.Set(transformprocessor.NewTranslatorWithName("set_cluster_name",
transformprocessor.WithTraceResourceStatements([]string{stmt}),
))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each of the set_cluster_name transform processors needs to have all three ResourceStatements set because the same transform processor is used in all pipelines.

Suggested change
))
stmt := fmt.Sprintf(`set(resource.attributes["k8s.cluster.name"], "%s")`, clusterName)
processors.Set(transformprocessor.NewTranslatorWithName("set_cluster_name",
transformprocessor.WithMetricResourceStatements([]string{stmt}),
transformprocessor.WithLogResourceStatements([]string{stmt}),
transformprocessor.WithTraceResourceStatements([]string{stmt}),
))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can revert the changes for this file.

// clusterNameRegex restricts cluster_name to safe characters, preventing
// OTTL injection and template metacharacter issues in YAML templates.
var clusterNameRegex = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`)
var otelClusterNameKey = common.ConfigKey(common.OpenTelemetryKey, common.ClusterNameKey)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define this in common and reuse it for all of the cluster name checks.

yamlConfig, err := mapstructure.Marshal(cfg)
require.NoError(t, err)
yamlStr := toyamlconfig.ToYamlConfig(yamlConfig)
// os.WriteFile("./sampleConfig/opentelemetry/container_insights_config.yaml", []byte(yamlStr), 0644)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Don't leave commented out code unnecessarily.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready for testing Indicates this PR is ready for integration tests to run

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants