diff --git a/.changeset/short-parks-retire.md b/.changeset/short-parks-retire.md new file mode 100644 index 00000000000..4436098073b --- /dev/null +++ b/.changeset/short-parks-retire.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added add LogStreamingEnabled config that enables streaming logs to the OTel exporter diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index f291f4c3f7e..79e2063b423 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -815,6 +815,8 @@ EmitterExportTimeout = '1s' # Default ChipIngressEndpoint = '' # Default # HeartbeatInterval is the interval at which a the application heartbeat is sent to telemetry backends. HeartbeatInterval = '1s' # Default +# LogStreamingEnabled enables log streaming to the OTel log exporter +LogStreamingEnabled = false # Default # ResourceAttributes are global metadata to include with all telemetry. [Telemetry.ResourceAttributes] diff --git a/core/config/telemetry_config.go b/core/config/telemetry_config.go index e3784c78104..517c93d760d 100644 --- a/core/config/telemetry_config.go +++ b/core/config/telemetry_config.go @@ -13,4 +13,5 @@ type Telemetry interface { EmitterExportTimeout() time.Duration ChipIngressEndpoint() string HeartbeatInterval() time.Duration + LogStreamingEnabled() bool } diff --git a/core/config/toml/types.go b/core/config/toml/types.go index c3530838496..5d61a49258e 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -2275,6 +2275,7 @@ type Telemetry struct { EmitterExportTimeout *commonconfig.Duration ChipIngressEndpoint *string HeartbeatInterval *commonconfig.Duration + LogStreamingEnabled *bool } func (b *Telemetry) setFrom(f *Telemetry) { @@ -2308,6 +2309,9 @@ func (b *Telemetry) setFrom(f *Telemetry) { if v := f.HeartbeatInterval; v != nil { b.HeartbeatInterval = v } + if v := f.LogStreamingEnabled; v != nil { + b.LogStreamingEnabled = v + } } func (b *Telemetry) ValidateConfig() (err error) { diff --git a/core/services/chainlink/config_telemetry.go b/core/services/chainlink/config_telemetry.go index 68ad89e3185..8a8f222f49d 100644 --- a/core/services/chainlink/config_telemetry.go +++ b/core/services/chainlink/config_telemetry.go @@ -95,3 +95,10 @@ func (b *telemetryConfig) HeartbeatInterval() time.Duration { } return b.s.HeartbeatInterval.Duration() } + +func (b *telemetryConfig) LogStreamingEnabled() bool { + if b.s.LogStreamingEnabled == nil { + return false + } + return *b.s.LogStreamingEnabled +} diff --git a/core/services/chainlink/config_telemetry_test.go b/core/services/chainlink/config_telemetry_test.go index 98de4b4bd02..fc817434c0d 100644 --- a/core/services/chainlink/config_telemetry_test.go +++ b/core/services/chainlink/config_telemetry_test.go @@ -225,3 +225,21 @@ func TestTelemetryConfig_HeartbeatInterval(t *testing.T) { }) } } + +func TestTelemetryConfig_LogStreamingEnabled(t *testing.T) { + tests := []struct { + name string + telemetry toml.Telemetry + expected bool + }{ + {"LogStreamingEnabledTrue", toml.Telemetry{LogStreamingEnabled: ptr(true)}, true}, + {"LogStreamingEnabledFalse", toml.Telemetry{LogStreamingEnabled: ptr(false)}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tc := telemetryConfig{s: tt.telemetry} + assert.Equal(t, tt.expected, tc.LogStreamingEnabled()) + }) + } +} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index b8f1e86ab6e..d57a4b3889c 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -591,6 +591,7 @@ func TestConfig_Marshal(t *testing.T) { EmitterExportTimeout: commoncfg.MustNewDuration(1 * time.Second), ChipIngressEndpoint: ptr("example.com/chip-ingress"), HeartbeatInterval: commoncfg.MustNewDuration(1 * time.Second), + LogStreamingEnabled: ptr(false), } full.CRE = toml.CreConfig{ Streams: &toml.StreamsConfig{ diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index 7a028fd4929..7e8357ec935 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -335,6 +335,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 4c7762361f8..0d4f642a3fb 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -345,6 +345,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = 'example.com/chip-ingress' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Telemetry.ResourceAttributes] Baz = 'test' diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index dba38fc6f6f..4d41dc8eb1f 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -335,6 +335,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index 7a028fd4929..7e8357ec935 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -335,6 +335,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index d132893e5a5..97de1ed94da 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -345,6 +345,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = 'example.com/chip-ingress' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Telemetry.ResourceAttributes] Baz = 'test' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 2f7263368c0..278dda5def8 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -335,6 +335,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 1233c0975bd..19f1850abdd 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -2222,6 +2222,7 @@ EmitterBatchProcessor = true # Default EmitterExportTimeout = '1s' # Default ChipIngressEndpoint = '' # Default HeartbeatInterval = '1s' # Default +LogStreamingEnabled = false # Default ``` Telemetry holds OTEL settings. This data includes open telemetry metrics, traces, & logs. @@ -2283,6 +2284,12 @@ HeartbeatInterval = '1s' # Default ``` HeartbeatInterval is the interval at which a the application heartbeat is sent to telemetry backends. +### LogStreamingEnabled +```toml +LogStreamingEnabled = false # Default +``` +LogStreamingEnabled enables log streaming to the OTel log exporter + ## Telemetry.ResourceAttributes ```toml [Telemetry.ResourceAttributes] diff --git a/plugins/loop_registry.go b/plugins/loop_registry.go index b4909172254..c28384f31cd 100644 --- a/plugins/loop_registry.go +++ b/plugins/loop_registry.go @@ -127,6 +127,7 @@ func (m *LoopRegistry) Register(id string) (*RegisteredLoop, error) { envCfg.TelemetryEmitterExportTimeout = m.cfgTelemetry.EmitterExportTimeout() envCfg.TelemetryAuthPubKeyHex = m.telemetryAuthPubKeyHex envCfg.ChipIngressEndpoint = m.cfgTelemetry.ChipIngressEndpoint() + envCfg.TelemetryLogStreamingEnabled = m.cfgTelemetry.LogStreamingEnabled() } m.lggr.Debugf("Registered loopp %q with port %d", id, envCfg.PrometheusPort) diff --git a/plugins/loop_registry_test.go b/plugins/loop_registry_test.go index e253865347f..8cdbf7e64cd 100644 --- a/plugins/loop_registry_test.go +++ b/plugins/loop_registry_test.go @@ -70,6 +70,8 @@ func (m mockCfgTelemetry) HeartbeatInterval() time.Duration { return 5 * time.Second } +func (m mockCfgTelemetry) LogStreamingEnabled() bool { return false } + type mockCfgDatabase struct{} func (m mockCfgDatabase) Backup() config.Backup { panic("unimplemented") } @@ -215,6 +217,7 @@ func TestLoopRegistry_Register(t *testing.T) { require.Equal(t, 0.42, envCfg.TelemetryTraceSampleRatio) require.True(t, envCfg.TelemetryEmitterBatchProcessor) require.Equal(t, 1*time.Second, envCfg.TelemetryEmitterExportTimeout) + require.False(t, envCfg.TelemetryLogStreamingEnabled) require.Equal(t, "example.com/chip-ingress", envCfg.ChipIngressEndpoint) } diff --git a/testdata/scripts/config/merge_raw_configs.txtar b/testdata/scripts/config/merge_raw_configs.txtar index 08ea54c689a..ff6d70a3ddb 100644 --- a/testdata/scripts/config/merge_raw_configs.txtar +++ b/testdata/scripts/config/merge_raw_configs.txtar @@ -482,6 +482,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index 3f5e7412b75..5a6610ce4c0 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -347,6 +347,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index 48167b45000..36e94b7d622 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -408,6 +408,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index da246169bc6..543e751a3c1 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -391,6 +391,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] 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 91af349e853..da9633d4861 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -391,6 +391,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 04c70a11654..da4c4e27e18 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -391,6 +391,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/fallback-override.txtar b/testdata/scripts/node/validate/fallback-override.txtar index c3c43a1c22e..4aab3d6375b 100644 --- a/testdata/scripts/node/validate/fallback-override.txtar +++ b/testdata/scripts/node/validate/fallback-override.txtar @@ -489,6 +489,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 6d9a00a99bf..8e30f875e0b 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -376,6 +376,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 09090a15c2b..8f3300e3292 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -387,6 +387,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 0d469a42102..1fcab2c826a 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -388,6 +388,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits] diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 5fbe915ea9b..f1f55c74345 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -370,6 +370,7 @@ EmitterBatchProcessor = true EmitterExportTimeout = '1s' ChipIngressEndpoint = '' HeartbeatInterval = '1s' +LogStreamingEnabled = false [Workflows] [Workflows.Limits]