Skip to content

Add opentelemetry root level config section with host_metrics, prometheus, OTLP, container_insights, and database_insights pipelines - #2152

Merged
jefchien merged 46 commits into
mainfrom
feature/opentelemetry
Jun 18, 2026
Merged

Add opentelemetry root level config section with host_metrics, prometheus, OTLP, container_insights, and database_insights pipelines#2152
jefchien merged 46 commits into
mainfrom
feature/opentelemetry

Conversation

@mitali-salvi

@mitali-salvi mitali-salvi commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the opentelemetry.collect config translation pipeline, enabling users to configure OTel pipelines via JSON config instead of raw YAML. This is the unified feature branch containing all v2 OTel collect sub-features.

Features

  • host_metrics — hostmetrics receiver (cpu, disk, filesystem, load, memory, network, processes) with configurable collection interval
  • container_insights — Full CI metrics pipeline (kubeletstats, cadvisor, node_exporter, dcgm, neuron, ebs-csi, lis-csi, kube-state-metrics, apiserver) with per-source processor chains, k8sattributes enrichment, and OTTL transforms
  • container_insights logs — Application and node log pipelines (filelog receiver) with dedicated exporters (compression: none for FluentBit migration parity)
  • prometheus — User-provided prometheus scrape config (config_path) with optional cluster_name enrichment
  • otlp — OTLP receivers (gRPC + HTTP) for metrics, logs, and traces with configurable endpoints
  • Shared metrics/logs/traces export pipelines — resourcedetection, batch, otlphttp export to CloudWatch OTLP endpoint with sigv4 auth and agenthealth
  • Identity and log routing processors — Platform-aware (host vs K8s) service.name, cloud.resource_id, deployment.environment derivation; log group/stream routing from aws.log.source

Architecture

Source Pipelines (per-feature):          Destination Pipelines (shared):
┌─────────────────────────┐             ┌──────────────────────────┐
│ host_metrics            │             │ metrics/opentelemetry    │
│ container_insights (x8) │──forward──▶│  resourcedetection       │
│ prometheus              │             │  identity transform      │
│ otlp (metrics)          │             │  batch → otlphttp        │
├─────────────────────────┤             ├──────────────────────────┤
│ otlp (logs)             │──forward──▶│ logs/opentelemetry       │
│ container_insights logs │             │  resourcedetection       │
├─────────────────────────┤             │  identity + routing      │
│ otlp (traces)           │──forward──▶│  batch → otlphttp        │
└─────────────────────────┘             └──────────────────────────┘

Key Design Decisions

  • rawMapConfig passthrough for CI templates — avoids factory struct round-trip bugs ($1 expansion, zero-value ErrorMode, filelog operator marshaling)
  • Per-source pipelines matching helm chart architecture (separate prometheus receivers, not consolidated)
  • forward connector fan-in to shared export pipelines
  • Explicit batch sizes from CW OTLP endpoint limits (1000 metrics, 10000 logs/traces per request; see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-OTLPEndpoint.html)
  • escapeDollarDigit scoped to CI translator only for k8sattributes regex backreferences

Testing

  • Full translator unit tests with golden YAML comparison
  • Schema validation tests
  • Verified on EKS cluster (cwa-otel-test) with all CI pipelines producing metrics
  • Lint passes (make lint clean)

@mitali-salvi
mitali-salvi requested a review from a team as a code owner June 11, 2026 17:40
@mitali-salvi mitali-salvi added the ready for testing Indicates this PR is ready for integration tests to run label Jun 11, 2026
@mitali-salvi mitali-salvi changed the title Feature/opentelemetry Add opentelemetry.collect config section with host_insights, prometheus, OTLP, container_insights, and database_insights pipelines Jun 11, 2026
@mitali-salvi mitali-salvi changed the title Add opentelemetry.collect config section with host_insights, prometheus, OTLP, container_insights, and database_insights pipelines Add opentelemetry root level config section with host_insights, prometheus, OTLP, container_insights, and database_insights pipelines Jun 11, 2026
…races exporters)

Switch TestOtlpOtelConfig to use checkTranslation (like host_insights) so the
TOML translator sets Global_Config.Region first, enabling the base export
pipelines to generate. The golden YAML now includes otlphttp exporters,
sigv4 auth, batch processors, and the complete pipeline routing.
@mitali-salvi mitali-salvi removed the ready for testing Indicates this PR is ready for integration tests to run label Jun 11, 2026
…irectory

Groups all opentelemetry.collect related golden files (host_insights,
container_insights, dbi, prometheus, otlp) into a dedicated subdirectory
for easier navigation.
… files

- Switch host_insights, prometheus, otlp, dbi to checkTranslation (full
  TOML+YAML path) so golden files include complete pipeline output
- Keep checkTranslationNoValidation only for container_insights (K8s
  service account token validation fails in unit tests) but improved it
  to run TOML translation first so region/base pipelines generate
- Regenerate all opentelemetry golden YAML files with full pipeline output
- Remove unused mapstructure/otel imports where not needed
Aligns the logs pipeline with metrics and traces pipelines which both
have resourcedetection for EC2/EKS metadata enrichment.
Previously only host_insights had a schema validation test. Now all
opentelemetry.collect features have valid/invalid sample JSON files
and corresponding test functions.
Aligns all three base pipelines with consistent agent health reporting.
- Metrics: agenthealth/otlphttp_metrics (already had it)
- Logs: agenthealth/logs (wraps headerssetter auth chain)
- Traces: agenthealth/traces (wraps sigv4/xray auth)
…tion

The function was only used in one place. Inlined the logic directly into
TestContainerInsightsConfig with a comment explaining why collector
validation is skipped (K8s service account token path is root-owned).
Add sample configs demonstrating both traditional (metrics/logs/traces) and
opentelemetry.collect sections working together:
- EC2 config: all v1 features + host_insights, database_insights, prometheus, otlp
- EKS config: all v1 features + all v2 features including container_insights

Includes golden files, translation tests, and schema validation.
Comment thread translator/translate/otel/processor/transformprocessor/translate.go
Comment thread translator/config/schema.json
mitali-salvi and others added 5 commits June 17, 2026 16:08
…statement-level

Pass the configured errorMode into buildStatements so statement-level
error_mode matches the top-level value. Previously buildStatements
hardcoded 'propagate' regardless of the WithErrorMode option.

Remove unnecessary WithErrorMode("ignore") from otlp_log_source and
logs_cleanup since their statements (set with where guard, delete_key)
cannot produce errors and propagate is the correct default.
movence
movence previously approved these changes Jun 18, 2026
Comment thread translator/tocwconfig/sampleConfig/opentelemetry/otlp_otel_config.yaml Outdated
@mitali-salvi
mitali-salvi force-pushed the feature/opentelemetry branch from 23e5800 to 3213115 Compare June 18, 2026 21:45
@mitali-salvi
mitali-salvi force-pushed the feature/opentelemetry branch from 3213115 to e547991 Compare June 18, 2026 21:53
"github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/common"
ci "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/pipeline/opentelemetry/containerinsights"
dbi "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/pipeline/opentelemetry/databaseinsights"
hi "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/pipeline/opentelemetry/hostmetrics"

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: hi -> hm

@@ -0,0 +1,217 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

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: this file should be called translators.go to be consistent with the others.

// CI logs pipelines are self-contained with dedicated exporters (compression: none)
// to match the helm chart behavior for FluentBit migration parity. They cannot share
// the base logs/opentelemetry exporter which uses gzip compression. See:
// https://github.com/aws-observability/helm-charts/blob/main/charts/amazon-cloudwatch-observability/templates/linux/_otel-container-insights-config.tpl

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: This reference in the helm chart is going to disappear from main pretty soon, either pin it to the commit or copy over the actual reasoning from the helm chart in here - like to prevent a cpu spike etc.

// - omitted: all pipelines
func NewTranslators(conf *confmap.Conf) common.PipelineTranslatorMap {
translators := common.NewTranslatorMap[*common.ComponentTranslators, pipeline.ID]()
mode := getMode(conf)

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.

As discussed, we should consider aligning this to the CollectionRole we have today. It will allow us to use the same default config in our helm and tweak the behavior with an env var.

We could continue to do this flag in addition to the env var and have a fallthrough ordering, but lets make the naming consistent i.e. instead of mode, might wanna call this role or something.

}

// Deployment metrics pipelines
if mode == "" || mode == "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.

If mode is empty, itll end up doing the work for both cluster and node.. do we want that?
Might be safer to just do node level work if empty.

Region: agent.Global_Config.Region,
CollectionInterval: collectionInterval.String(),
ScrapeTimeout: scrapeTimeout.String(),
NodeName: envOrPlaceholder("K8S_NODE_NAME"),

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: While we set both, HOST_NAME is what we've historically used in the context of CI, so Id stick to that.

Comment on lines +203 to +206
keys = make([]string, 0, len(sectionMap))
for k := range sectionMap {
keys = append(keys, k)
}

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.

Suggested change
keys = make([]string, 0, len(sectionMap))
for k := range sectionMap {
keys = append(keys, k)
}
slices.Collect(maps.Keys(sectionMap))

var scrapersWindowsConfig []byte

// Config is a serializable representation of
// hostmetricsreceiver.Config. The upstream type uses mapstructure:"-" on its

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 be a follow up but we should ideally update this in our fork instead of the below.


var prometheusKey = common.ConfigKey(common.OpenTelemetryKey, common.CollectKey, common.PrometheusKey)
var configPathKey = common.ConfigKey(prometheusKey, "config_path")
var clusterNameKey = common.ConfigKey(prometheusKey, "cluster_name")

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 be a follow up, but some of these we should standerdize in this new schema. Like if cluster_name can be set here, why not for otlp.

"auth_type": "serviceAccount",
"passthrough": false,
"filter": map[string]interface{}{
"node_from_env_var": "K8S_NODE_NAME",

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.

related to the other comment if we do end up changing that to HOST_NAME at some point

MaxMetricsPerRequest = 1000
MaxLogsPerRequest = 10000
MaxSpansPerRequest = 10000
BatchTimeout = 15 * 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.

Should this be 15 or 30?

}

func isLocalhostEndpoint(endpoint string) bool {
return strings.HasPrefix(endpoint, "localhost") ||

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: This seems a little fragile... consider parsing the host (net.SplitHostPort) and compare exactly.

"host_metrics": {
"type": "object",
"properties": {
"metrics_collection_interval": {

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: We should probably standardize and call it just collection_interval

@mitali-salvi
mitali-salvi force-pushed the feature/opentelemetry branch from 66280f8 to bc0d2a6 Compare June 18, 2026 23:42
@jefchien jefchien changed the title Add opentelemetry root level config section with host_insights, prometheus, OTLP, container_insights, and database_insights pipelines Add opentelemetry root level config section with host_metrics, prometheus, OTLP, container_insights, and database_insights pipelines Jun 18, 2026
@jefchien
jefchien merged commit 460134e into main Jun 18, 2026
384 of 387 checks passed
@jefchien
jefchien deleted the feature/opentelemetry branch June 18, 2026 23:58

@musa-asad musa-asad left a comment

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.

.

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.

6 participants