diff --git a/.changeset/beholder-metric-views-deny-attributes.md b/.changeset/beholder-metric-views-deny-attributes.md new file mode 100644 index 00000000000..d394e5f7ad8 --- /dev/null +++ b/.changeset/beholder-metric-views-deny-attributes.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added Add `Telemetry.MetricViewsDenyAttributes` config option to drop specified metric attribute keys from Beholder default views. diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 81af909205f..f48dd599dd1 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -172,8 +172,9 @@ func newBeholderClient( LogMaxQueueSize: cfgTelemetry.LogMaxQueueSize(), // Due to OpenTelemetry semantics, histogram bucket boundaries must be set // when the Beholder client is constructed. - MetricViews: metricViews(), - MetricCardinalityLimit: cfgTelemetry.MetricCardinalityLimit(), + MetricViews: metricViews(), + MetricViewsDenyAttributes: cfgTelemetry.MetricViewsDenyAttributes(), + MetricCardinalityLimit: cfgTelemetry.MetricCardinalityLimit(), } if cfgTracing.Enabled() { diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 45b477b4a35..0938e997843 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -928,6 +928,9 @@ LogExportMaxBatchSize = 512 # Default LogExportInterval = '1s' # Default # LogMaxQueueSize sets the maximum queue size used by the batcher LogMaxQueueSize = 2048 # Default +# MetricViewsDenyAttributes lists attribute keys dropped before export (e.g. event_id). +# Empty disables default Beholder metric attribute deny views. +MetricViewsDenyAttributes = ['event_id'] # Default # MetricCardinalityLimit sets the OTel SDK per-instrument attribute-set limit (0 disables). MetricCardinalityLimit = 100000 # Default diff --git a/core/config/telemetry_config.go b/core/config/telemetry_config.go index dffe23bab60..eb744003be3 100644 --- a/core/config/telemetry_config.go +++ b/core/config/telemetry_config.go @@ -38,6 +38,7 @@ type Telemetry interface { LogExportMaxBatchSize() int LogExportInterval() time.Duration LogMaxQueueSize() int + MetricViewsDenyAttributes() []string MetricCardinalityLimit() int PrometheusBridge() PrometheusBridge } diff --git a/core/config/toml/types.go b/core/config/toml/types.go index 136dcb112a8..de7e22e4076 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -3002,8 +3002,8 @@ type Telemetry struct { LogExportMaxBatchSize *int LogExportInterval *commonconfig.Duration LogMaxQueueSize *int - - MetricCardinalityLimit *int + MetricViewsDenyAttributes []string + MetricCardinalityLimit *int PrometheusBridge PrometheusBridge `toml:",omitempty"` } @@ -3102,6 +3102,9 @@ func (b *Telemetry) setFrom(f *Telemetry) { if v := f.LogMaxQueueSize; v != nil { b.LogMaxQueueSize = v } + if v := f.MetricViewsDenyAttributes; v != nil { + b.MetricViewsDenyAttributes = v + } if v := f.MetricCardinalityLimit; v != nil { b.MetricCardinalityLimit = v } diff --git a/core/services/chainlink/config_telemetry.go b/core/services/chainlink/config_telemetry.go index 05849240ed1..83c1fa56c58 100644 --- a/core/services/chainlink/config_telemetry.go +++ b/core/services/chainlink/config_telemetry.go @@ -263,7 +263,14 @@ func (b *telemetryConfig) LogMaxQueueSize() int { return *b.s.LogMaxQueueSize } +func (b *telemetryConfig) MetricViewsDenyAttributes() []string { + return b.s.MetricViewsDenyAttributes +} + func (b *telemetryConfig) MetricCardinalityLimit() int { + if b.s.MetricCardinalityLimit == nil { + return 100000 + } return *b.s.MetricCardinalityLimit } diff --git a/core/services/chainlink/config_telemetry_test.go b/core/services/chainlink/config_telemetry_test.go index b1545cb57bb..55a382e292e 100644 --- a/core/services/chainlink/config_telemetry_test.go +++ b/core/services/chainlink/config_telemetry_test.go @@ -553,6 +553,27 @@ func TestTelemetryConfig_LogMaxQueueSize(t *testing.T) { } } +func TestTelemetryConfig_MetricViewsDenyAttributes(t *testing.T) { + t.Parallel() + tests := []struct { + name string + telemetry toml.Telemetry + expected []string + }{ + {"DenylistSet", toml.Telemetry{MetricViewsDenyAttributes: []string{"event_id"}}, []string{"event_id"}}, + {"DenylistNil", toml.Telemetry{MetricViewsDenyAttributes: nil}, nil}, + {"DenylistEmpty", toml.Telemetry{MetricViewsDenyAttributes: []string{}}, []string{}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + tc := telemetryConfig{s: tt.telemetry} + assert.Equal(t, tt.expected, tc.MetricViewsDenyAttributes()) + }) + } +} + func TestTelemetryConfig_MetricCardinalityLimit(t *testing.T) { t.Parallel() tests := []struct { diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index cf11b4c4eab..630d1e74daa 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -582,6 +582,7 @@ func TestConfig_Marshal(t *testing.T) { LogExportMaxBatchSize: new(512), LogExportInterval: ptrDuration(1 * time.Second), LogMaxQueueSize: new(2048), + MetricViewsDenyAttributes: []string{"event_id"}, MetricCardinalityLimit: new(100000), PrometheusBridge: toml.PrometheusBridge{ diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index 399d320f252..547fa5fab70 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -369,6 +369,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 742de0515ba..322198e45cc 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -404,6 +404,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.ResourceAttributes] diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 2d7a08ea046..60d8850612b 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -369,6 +369,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index 399d320f252..547fa5fab70 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -369,6 +369,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 3894abf4f0e..03f178828e7 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -383,6 +383,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.ResourceAttributes] diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index dfe8c2e3f79..1a7a1e84bae 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -369,6 +369,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 42be8c5d409..5036a6b15ce 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -2412,6 +2412,7 @@ LogExportTimeout = '1s' # Default LogExportMaxBatchSize = 512 # Default LogExportInterval = '1s' # Default LogMaxQueueSize = 2048 # Default +MetricViewsDenyAttributes = ['event_id'] # Default MetricCardinalityLimit = 100000 # Default ``` Telemetry holds OTEL settings. @@ -2603,6 +2604,13 @@ LogMaxQueueSize = 2048 # Default ``` LogMaxQueueSize sets the maximum queue size used by the batcher +### MetricViewsDenyAttributes +```toml +MetricViewsDenyAttributes = ['event_id'] # Default +``` +MetricViewsDenyAttributes lists attribute keys dropped before export (e.g. event_id). +Empty disables default Beholder metric attribute deny views. + ### MetricCardinalityLimit ```toml MetricCardinalityLimit = 100000 # Default diff --git a/plugins/loop_registry.go b/plugins/loop_registry.go index 0c1faf2fcf5..a20b064688e 100644 --- a/plugins/loop_registry.go +++ b/plugins/loop_registry.go @@ -170,6 +170,7 @@ func (m *LoopRegistry) Register(id string) (*RegisteredLoop, error) { envCfg.TelemetryLogExportMaxBatchSize = m.cfgTelemetry.LogExportMaxBatchSize() envCfg.TelemetryLogExportInterval = m.cfgTelemetry.LogExportInterval() envCfg.TelemetryLogMaxQueueSize = m.cfgTelemetry.LogMaxQueueSize() + envCfg.TelemetryMetricViewsDenyAttributes = m.cfgTelemetry.MetricViewsDenyAttributes() limit := m.cfgTelemetry.MetricCardinalityLimit() envCfg.TelemetryMetricCardinalityLimit = &limit envCfg.TelemetryPrometheusBridgeEnabled = m.cfgTelemetry.PrometheusBridge().Enabled() diff --git a/plugins/loop_registry_test.go b/plugins/loop_registry_test.go index bc827b89cec..6c2d74e53da 100644 --- a/plugins/loop_registry_test.go +++ b/plugins/loop_registry_test.go @@ -108,6 +108,9 @@ func (m mockCfgTelemetry) LogExportMaxBatchSize() int { return 512 } func (m mockCfgTelemetry) LogExportInterval() time.Duration { return 5 * time.Second } func (m mockCfgTelemetry) LogMaxQueueSize() int { return 2048 } +func (m mockCfgTelemetry) MetricViewsDenyAttributes() []string { + return []string{"event_id"} +} func (m mockCfgTelemetry) MetricCardinalityLimit() int { return 100000 } func (m mockCfgTelemetry) PrometheusBridge() config.PrometheusBridge { @@ -272,6 +275,7 @@ func TestLoopRegistry_Register(t *testing.T) { require.Equal(t, 512, envCfg.TelemetryLogExportMaxBatchSize) require.Equal(t, 5*time.Second, envCfg.TelemetryLogExportInterval) require.Equal(t, 2048, envCfg.TelemetryLogMaxQueueSize) + require.Equal(t, []string{"event_id"}, envCfg.TelemetryMetricViewsDenyAttributes) require.NotNil(t, envCfg.TelemetryMetricCardinalityLimit) require.Equal(t, 100000, *envCfg.TelemetryMetricCardinalityLimit) diff --git a/testdata/scripts/config/merge_raw_configs.txtar b/testdata/scripts/config/merge_raw_configs.txtar index 3714476c9dd..f95c7a74340 100644 --- a/testdata/scripts/config/merge_raw_configs.txtar +++ b/testdata/scripts/config/merge_raw_configs.txtar @@ -516,6 +516,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index 2129039fd26..4f9b1257602 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -381,6 +381,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index a2ee61f66d2..8d63c6feda3 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -442,6 +442,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 059122a677d..1fa1e759592 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -425,6 +425,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 57c12bf7df8..0baf393ad79 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -425,6 +425,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 380f90de77c..62fc1cab5c1 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -425,6 +425,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/fallback-override.txtar b/testdata/scripts/node/validate/fallback-override.txtar index b01de8746f5..441f0929955 100644 --- a/testdata/scripts/node/validate/fallback-override.txtar +++ b/testdata/scripts/node/validate/fallback-override.txtar @@ -527,6 +527,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 0703e2f2341..00bf4a9fabd 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -410,6 +410,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 87a04fd9f81..feedbb650e4 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -421,6 +421,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 4b184a30eee..95c57299de3 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -422,6 +422,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge] diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index a668666af86..5ea398bb912 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -404,6 +404,7 @@ LogExportTimeout = '1s' LogExportMaxBatchSize = 512 LogExportInterval = '1s' LogMaxQueueSize = 2048 +MetricViewsDenyAttributes = ['event_id'] MetricCardinalityLimit = 100000 [Telemetry.PrometheusBridge]