diff --git a/components-rs/Cargo.toml b/components-rs/Cargo.toml index 84c1aa0f83..35ba698004 100644 --- a/components-rs/Cargo.toml +++ b/components-rs/Cargo.toml @@ -16,7 +16,7 @@ datadog-live-debugger = { path = "../libdatadog/datadog-live-debugger" } datadog-live-debugger-ffi = { path = "../libdatadog/datadog-live-debugger-ffi", default-features = false } datadog-ipc = { path = "../libdatadog/datadog-ipc" } datadog-ffe = { path = "../libdatadog/datadog-ffe" } -datadog-remote-config = { path = "../libdatadog/datadog-remote-config" } +datadog-remote-config = { path = "../libdatadog/datadog-remote-config", features = ["ffe"] } datadog-sidecar = { path = "../libdatadog/datadog-sidecar" } datadog-sidecar-ffi = { path = "../libdatadog/datadog-sidecar-ffi" } libdd-data-pipeline = { path = "../libdatadog/libdd-data-pipeline" } diff --git a/components-rs/common.h b/components-rs/common.h index 67718a21d4..adf46fad3e 100644 --- a/components-rs/common.h +++ b/components-rs/common.h @@ -480,6 +480,19 @@ typedef struct ddog_SidecarTransport ddog_SidecarTransport; */ typedef struct ddog_SpanConcentrator ddog_SpanConcentrator; +/** + * Flags selecting which Remote Config products/capabilities to subscribe to. + * + * Passed as a single C-ABI struct so call sites can use designated initializers + * and name the flags, instead of a positional sequence of bool args. + */ +typedef struct ddog_DdogRemoteConfigFlags { + bool live_debugging_enabled; + bool appsec_activation; + bool appsec_config; + bool ffe_enabled; +} ddog_DdogRemoteConfigFlags; + /** * Holds the raw parts of a Rust Vec; it should only be created from Rust, * never from C. diff --git a/components-rs/ddtrace.h b/components-rs/ddtrace.h index 855cc84a3b..da49888728 100644 --- a/components-rs/ddtrace.h +++ b/components-rs/ddtrace.h @@ -144,9 +144,7 @@ void ddog_reset_logger(void); uint32_t ddog_get_logs_count(ddog_CharSlice level); -void ddog_init_remote_config(bool live_debugging_enabled, - bool appsec_activation, - bool appsec_config); +void ddog_init_remote_config(struct ddog_DdogRemoteConfigFlags flags); struct ddog_RemoteConfigState *ddog_init_remote_config_state(const struct ddog_Endpoint *endpoint, bool di_enabled); diff --git a/components-rs/remote_config.rs b/components-rs/remote_config.rs index 515aede6f3..fc0ec34fb7 100644 --- a/components-rs/remote_config.rs +++ b/components-rs/remote_config.rs @@ -1,4 +1,5 @@ use crate::sidecar::MaybeShmLimiter; +use datadog_ffe::rules_based::Configuration; use datadog_live_debugger::debugger_defs::{DebuggerData, DebuggerPayload}; use datadog_live_debugger::{FilterList, LiveDebuggingData, ServiceConfiguration}; use datadog_live_debugger_ffi::data::Probe; @@ -116,13 +117,28 @@ pub struct LiveDebuggerState { pub di_enabled: bool, } +/// Flags selecting which Remote Config products/capabilities to subscribe to. +/// +/// Passed as a single C-ABI struct so call sites can use designated initializers +/// and name the flags, instead of a positional sequence of bool args. +#[repr(C)] +pub struct DdogRemoteConfigFlags { + pub live_debugging_enabled: bool, + pub appsec_activation: bool, + pub appsec_config: bool, + pub ffe_enabled: bool, +} + #[no_mangle] #[allow(static_mut_refs)] -pub unsafe extern "C" fn ddog_init_remote_config( - live_debugging_enabled: bool, - appsec_activation: bool, - appsec_config: bool, -) { +pub unsafe extern "C" fn ddog_init_remote_config(flags: DdogRemoteConfigFlags) { + let DdogRemoteConfigFlags { + live_debugging_enabled, + appsec_activation, + appsec_config, + ffe_enabled, + } = flags; + DDTRACE_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::ApmTracing); DDTRACE_REMOTE_CONFIG_CAPABILITIES.push(RemoteConfigCapabilities::ApmTracingCustomTags); DDTRACE_REMOTE_CONFIG_CAPABILITIES.push(RemoteConfigCapabilities::ApmTracingEnabled); @@ -139,6 +155,11 @@ pub unsafe extern "C" fn ddog_init_remote_config( DDTRACE_REMOTE_CONFIG_CAPABILITIES.push(RemoteConfigCapabilities::AsmActivation); } + if ffe_enabled { + DDTRACE_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::FfeFlags); + DDTRACE_REMOTE_CONFIG_CAPABILITIES.push(RemoteConfigCapabilities::FfeFlagConfigurationRules); + } + if live_debugging_enabled { DDTRACE_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::LiveDebugger) } @@ -377,6 +398,10 @@ pub extern "C" fn ddog_process_remote_configs(remote_config: &mut RemoteConfigSt ); } } + RemoteConfigData::FfeFlags(ufc) => { + debug!("Received FFE flags configuration"); + crate::ffe::store_config(Configuration::from_server_response(ufc)); + } RemoteConfigData::Ignored(_) => (), RemoteConfigData::TracerFlareConfig(_) => {} RemoteConfigData::TracerFlareTask(_) => {} @@ -402,6 +427,10 @@ pub extern "C" fn ddog_process_remote_configs(remote_config: &mut RemoteConfigSt } } } + RemoteConfigProduct::FfeFlags => { + debug!("FFE flags configuration removed"); + crate::ffe::clear_config(); + } _ => (), }, } diff --git a/ext/configuration.h b/ext/configuration.h index 1c95a47abd..0fafcc56b1 100644 --- a/ext/configuration.h +++ b/ext/configuration.h @@ -278,6 +278,7 @@ enum ddtrace_sidecar_connection_mode { CONFIG(INT, DD_CODE_ORIGIN_MAX_USER_FRAMES, "8") \ CONFIG(BOOL, DD_TRACE_RESOURCE_RENAMING_ENABLED, "false") \ CONFIG(BOOL, DD_TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT, "false") \ + CONFIG(BOOL, DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED, "false") \ CONFIG(BOOL, DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED, "true") \ CONFIG(BOOL, DD_TRACE_STATS_COMPUTATION_ENABLED, "false") \ DD_INTEGRATIONS diff --git a/ext/sidecar.c b/ext/sidecar.c index 9ea81ab222..15675daa56 100644 --- a/ext/sidecar.c +++ b/ext/sidecar.c @@ -390,7 +390,12 @@ void ddtrace_sidecar_setup(bool appsec_activation, bool appsec_config) { ddtrace_set_non_resettable_sidecar_globals(); ddtrace_set_resettable_sidecar_globals(); - ddog_init_remote_config(get_global_DD_INSTRUMENTATION_TELEMETRY_ENABLED(), appsec_activation, appsec_config); + ddog_init_remote_config((struct ddog_DdogRemoteConfigFlags){ + .live_debugging_enabled = get_global_DD_INSTRUMENTATION_TELEMETRY_ENABLED(), + .appsec_activation = appsec_activation, + .appsec_config = appsec_config, + .ffe_enabled = get_global_DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED(), + }); zend_long mode = get_global_DD_TRACE_SIDECAR_CONNECTION_MODE(); diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index e65fd5c4c9..b146be36e0 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -382,6 +382,13 @@ "default": "false" } ], + "DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED": [ + { + "implementation": "A", + "type": "boolean", + "default": "false" + } + ], "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": [ { "implementation": "B", diff --git a/tests/ext/ffe/remote_config_lifecycle.phpt b/tests/ext/ffe/remote_config_lifecycle.phpt new file mode 100644 index 0000000000..bfcb6351e8 --- /dev/null +++ b/tests/ext/ffe/remote_config_lifecycle.phpt @@ -0,0 +1,90 @@ +--TEST-- +FFE Remote Config loads and removes UFC config +--SKIPIF-- + +--ENV-- +DD_AGENT_HOST=request-replayer +DD_TRACE_AGENT_PORT=80 +DD_TRACE_GENERATE_ROOT_SPAN=0 +DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS=0.01 +DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=1 +--INI-- +datadog.trace.agent_test_session_token=ffe/remote_config_lifecycle +--FILE-- + $version); +?> +--CLEAN-- + +--EXPECT-- +before=false +loaded=true +has_config_after_add=true +success={"value_json":"\"blue\"","variant":"blue","allocation_key":"alloc-string","reason":0,"error_code":0,"do_log":true} +removed=true +has_config_after_remove=false +version_increased=true