Add prometheus pipeline translator under opentelemetry config - #2148
Conversation
Adds support for opentelemetry.collect.prometheus with a mandatory
config_path field pointing to an external Prometheus scrape config YAML.
The translator auto-detects OTel wrapper format vs plain Prometheus
format and supports target_allocator with TLS. The pipeline feeds
into the shared base metrics pipeline via forward connector.
Config:
{"opentelemetry": {"collect": {"prometheus": {"config_path": "/path/to/prometheus.yml"}}}}
…and tests - Validate cluster_name to prevent OTTL injection (alphanumeric, hyphens, dots, underscores only) - Add cluster_name to prometheus schema (was missing from pushed commit) - Add test cases: cluster_name processor, invalid cluster_name, missing config file, no-cluster-name path
| service: | ||
| extensions: [] | ||
| pipelines: | ||
| metrics/prometheus: |
There was a problem hiding this comment.
Any potential conflicts with V1 naming on this?
There was a problem hiding this comment.
renamed to metrics/otel_prometheus to avoid any collision
- Rename pipeline from metrics/prometheus to metrics/otel_prometheus to avoid conflict with V1 legacy prometheus pipeline naming - Add test for plain prometheus format (global + scrape_configs) - Only inject default TLS paths for target_allocator if customer hasn't provided their own certs
The opentelemetry.collect.prometheus path should not assume operator deployment model. If target_allocator needs TLS, users should specify cert paths in their prometheus config explicitly.
Remove OTel wrapper format detection and target_allocator TLS injection. Only standard Prometheus format (scrape_configs at root) is supported. No format ambiguity, no error string matching.
| // references (os.Expand), which can cause failures or empty replacements. | ||
| // This is a known limitation when prometheus configs with relabel_configs | ||
| // are loaded through the OTel config resolver pipeline. | ||
| if err := componentParser.Unmarshal(&cfg); err != nil { |
There was a problem hiding this comment.
so if it is a invalid prometheus config such as with a typo we assume it is an Otel config?
There was a problem hiding this comment.
I removed OTel wrapper format support entirely in a previous commit. The translator now only accepts plain Prometheus format. If the config has a typo or is invalid YAML, it will fail rather than silently falling through to a different parsing path.
| if clusterName, ok := common.GetString(conf, clusterNameKey); ok && clusterName != "" { | ||
| // Validate cluster_name to prevent OTTL injection (must be alphanumeric, hyphens, dots, underscores) | ||
| for _, c := range clusterName { | ||
| if (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '-' && c != '.' && c != '_' { |
There was a problem hiding this comment.
Can we use a regex check instead?
…name - Add filepath.Clean on config_path before use - Replace character-by-character loop with regexp for cluster_name validation - Add comment explaining fwdConnector in both Exporters and Connectors
| } | ||
|
|
||
| func (t *prometheusReceiverTranslator) Translate(conf *confmap.Conf) (component.Config, error) { | ||
| factory := prometheusreceiver.NewFactory() |
There was a problem hiding this comment.
Why are we reinitializing the factory if we already created it in ID or vise versa?
Description
Adds support for
opentelemetry.collect.prometheusconfiguration that reads an external Prometheus scrape config file and generates an OTel prometheus receiver pipeline feeding into the shared base metrics pipeline.Config
{ "opentelemetry": { "collect": { "prometheus": { "config_path": "/opt/aws/prometheus.yml", "cluster_name": "my-cluster" } } } }k8s.cluster.nameresource attribute)Behavior
cluster_nameis set, adds a transform processor to tag metrics withk8s.cluster.namemetrics/otel_prometheus(avoids conflict with V1metrics/prometheus/*)Known limitation
Prometheus relabel configs using
$1,$2capture group references can conflict with the OTel confmapexpandconverterwhich interprets$as environment variable substitution. Documented in code comment.Tests
Unit tests
TestPrometheusTranslator— nil conf, missing key, valid config, cluster_name, invalid cluster_name, missing fileTestPrometheusReceiverTranslator— OTel format parsingTestPrometheusReceiverTranslatorPlainFormat— plain Prometheus format (global + scrape_configs)TestPrometheusReceiverTranslatorMissingFile— file not found errorTestPrometheusTranslatorClusterNameProcessor/NoClusterNameProcessor— conditional processorTestPrometheusOtelPipelineConfig— golden file test (end-to-end translation)EC2 integration test (us-west-2,
mitsalvi-otel-test)EKS integration test (us-east-1,
cwa-otel-test)cluster_name: "cwa-otel-test"k8s.cluster.nameresource attribute applied via transform processor ✅Linting
make fmt✓ |make lint✓ (only pre-existing plugins/plugins.go impi issue) |go build✓