Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
13 changes: 13 additions & 0 deletions components-rs/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 1 addition & 3 deletions components-rs/ddtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
39 changes: 34 additions & 5 deletions components-rs/remote_config.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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)
}
Expand Down Expand Up @@ -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(_) => {}
Expand All @@ -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();
}
_ => (),
},
}
Expand Down
1 change: 1 addition & 0 deletions ext/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion ext/sidecar.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
7 changes: 7 additions & 0 deletions metadata/supported-configurations.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
90 changes: 90 additions & 0 deletions tests/ext/ffe/remote_config_lifecycle.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
--TEST--
FFE Remote Config loads and removes UFC config
--SKIPIF--
<?php include __DIR__ . '/../includes/skipif_no_dev_env.inc'; ?>
--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--
<?php
require __DIR__ . "/../remote_config/remote_config.inc";
include __DIR__ . '/../includes/request_replayer.inc';

function show($label, $value) {
echo $label . '=' . json_encode($value, JSON_UNESCAPED_SLASHES) . "\n";
}

function put_ffe_config_file($json) {
$path = "datadog/2/FFE_FLAGS/" . sha1($json) . "/config";
put_rc_file($path, $json);
return $path;
}

function wait_for_ffe_config($expected) {
for ($i = 0; $i < 200; $i++) {
if (\DDTrace\ffe_has_config() === $expected) {
return true;
}
usleep(100000);
}
return false;
}

reset_request_replayer();
show('before', \DDTrace\ffe_has_config());

$config = <<<'JSON'
{
"createdAt": "2024-01-01T00:00:00Z",
"environment": {"name": "test"},
"flags": {
"string.flag": {
"key": "string.flag",
"enabled": true,
"variationType": "STRING",
"variations": {
"blue": {"key": "blue", "value": "blue"}
},
"allocations": [{
"key": "alloc-string",
"rules": [],
"splits": [{"variationKey": "blue", "serialId": 7, "shards": []}],
"doLog": true
}]
}
}
}
JSON;

$path = put_ffe_config_file($config);
\DDTrace\start_span();

show('loaded', wait_for_ffe_config(true));
show('has_config_after_add', \DDTrace\ffe_has_config());
show('success', \DDTrace\ffe_evaluate('string.flag', 0, 'user-1', array()));

$version = \DDTrace\ffe_config_version();
del_rc_file($path);

show('removed', wait_for_ffe_config(false));
show('has_config_after_remove', \DDTrace\ffe_has_config());
show('version_increased', \DDTrace\ffe_config_version() > $version);
?>
--CLEAN--
<?php
require __DIR__ . "/../remote_config/remote_config.inc";
reset_request_replayer();
?>
--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
Loading