Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2b3f9e5
feat(ffe): wire runtime-backed feature flags
leoromanovsky May 22, 2026
782f622
feat(ffe): package runtime evaluation milestone
leoromanovsky May 22, 2026
9163839
Fix FFE fixture validation in package CI
leoromanovsky May 22, 2026
cc6058f
Fix FFE fixture submodules in child pipelines
leoromanovsky May 22, 2026
e55ebb9
Skip FFE fixture sweep under valgrind
leoromanovsky May 22, 2026
81f2206
Merge remote-tracking branch 'origin/master' into leo.romanovsky/mile…
leoromanovsky May 22, 2026
4a810a2
Make FFE runtime state thread-local
leoromanovsky May 22, 2026
2f46d97
Preload FFE API classes for OpenFeature bridge
leoromanovsky May 22, 2026
7abe806
Return defaults for null FFE assignments
leoromanovsky May 22, 2026
eaa44fc
Avoid duplicate OpenFeature bridge preloads
leoromanovsky May 22, 2026
4496908
Validate FFE runtime through PHP system tests
leoromanovsky May 22, 2026
555e9a0
fix: preserve empty FFE targeting keys
leoromanovsky May 22, 2026
75c5c10
docs(ffe): add PR-stack and system diagrams for #3906 (M1 Evaluations)
leoromanovsky May 23, 2026
d201d40
docs(ffe): rename 'Hook seam' → 'Hook layer' in README
leoromanovsky May 23, 2026
78e9f65
chore(ffe): remove generated stack diagrams
leoromanovsky May 24, 2026
3b1358e
Fix OpenFeature autoload state for ZTS requests
leoromanovsky May 26, 2026
c2fb467
Merge remote-tracking branch 'origin/master' into leo.romanovsky/mile…
leoromanovsky May 27, 2026
a61647f
Address FFE evaluation review feedback
leoromanovsky May 27, 2026
d82e50d
Simplify FFE result ownership
leoromanovsky May 27, 2026
027c7aa
Address FFE runtime review feedback
leoromanovsky May 27, 2026
5800827
Restrict FFE fixture submodule updates
leoromanovsky May 27, 2026
f2c66a7
Merge branch 'master' into leo.romanovsky/milestone-1-runtime-evaluation
leoromanovsky May 27, 2026
c36a566
Address FFE API review follow-up
leoromanovsky May 27, 2026
4cf261d
fix(ffe): use compatible result property updates
leoromanovsky May 27, 2026
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
11 changes: 11 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ compile_rust.sh @Datadog/libdatadog-apm
# APM IDM Team
/src/ @DataDog/apm-idm-php

# FFE (Feature Flagging & Experimentation) SDK Team
/components-rs/ffe.rs @Datadog/libdatadog-apm @DataDog/feature-flagging-and-experimentation-sdk
/libdatadog @Datadog/libdatadog-apm @DataDog/feature-flagging-and-experimentation-sdk
/src/api/FeatureFlags/ @DataDog/feature-flagging-and-experimentation-sdk
/src/DDTrace/OpenFeature/ @DataDog/feature-flagging-and-experimentation-sdk
/src/bridge/_files_openfeature.php @DataDog/feature-flagging-and-experimentation-sdk
/tests/FeatureFlags/ @DataDog/feature-flagging-and-experimentation-sdk
/tests/api/Unit/FeatureFlags/ @DataDog/feature-flagging-and-experimentation-sdk
/tests/OpenFeature/ @DataDog/feature-flagging-and-experimentation-sdk
/tests/ext/ffe/ @DataDog/feature-flagging-and-experimentation-sdk

# Release files
Cargo.lock @DataDog/apm-php @DataDog/profiling-php @Datadog/libdatadog-apm
package.xml @DataDog/apm-php @DataDog/profiling-php @Datadog/asm-php
Expand Down
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@

version: 2
updates:
- package-ecosystem: "gitsubmodule"
Comment thread
leoromanovsky marked this conversation as resolved.
directory: "/"
schedule:
interval: "weekly"
allow:
- dependency-name: "tests/FeatureFlags/ffe-system-test-data"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
Expand Down
9 changes: 6 additions & 3 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ stages:

variables:
GIT_SUBMODULE_STRATEGY: recursive
# Only clone libdatadog submodule by default
GIT_SUBMODULE_PATHS: libdatadog
# Only clone submodules required by default test jobs
GIT_SUBMODULE_PATHS: libdatadog tests/FeatureFlags/ffe-system-test-data
RELIABILITY_ENV_BRANCH:
value: "master"
description: "Run a specific datadog-reliability-env branch downstream"
Expand Down Expand Up @@ -74,6 +74,8 @@ tracer-trigger:
strategy: depend
variables:
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
GIT_SUBMODULE_STRATEGY: recursive
GIT_SUBMODULE_PATHS: libdatadog tests/FeatureFlags/ffe-system-test-data

appsec-trigger:
stage: tests
Expand Down Expand Up @@ -122,7 +124,8 @@ package-trigger:
pipeline_variables: true
variables:
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
GIT_SUBMODULE_PATHS: libdatadog appsec/third_party/cpp-base64 appsec/third_party/libddwaf appsec/third_party/libddwaf-rust appsec/third_party/msgpack-c
GIT_SUBMODULE_STRATEGY: recursive
GIT_SUBMODULE_PATHS: libdatadog tests/FeatureFlags/ffe-system-test-data appsec/third_party/cpp-base64 appsec/third_party/libddwaf appsec/third_party/libddwaf-rust appsec/third_party/msgpack-c
NIGHTLY_BUILD: $NIGHTLY_BUILD

# Runs after the full CI completes. Triggered in two situations:
Expand Down
20 changes: 20 additions & 0 deletions .gitlab/generate-tracer.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,26 @@ function before_script_steps($with_docker_auth = false) {
- make test_unit PHPUNIT_JUNIT="artifacts/tests/php-tests.xml" <?= ASSERT_NO_MEMLEAKS ?>
<?php after_script(); ?>

<?php if (version_compare($major_minor, "8.0", ">=")): ?>
"Feature flags tests: [<?= $major_minor ?>]":
extends: .debug_test
needs:
- job: "compile extension: debug"
parallel:
matrix:
- PHP_MAJOR_MINOR: "<?= $major_minor ?>"
ARCH: "amd64"
artifacts: true
- job: "Prepare code"
artifacts: true
variables:
PHP_MAJOR_MINOR: "<?= $major_minor ?>"
ARCH: "amd64"
script:
- make test_featureflags PHPUNIT_JUNIT="artifacts/tests/php-tests.xml" <?= ASSERT_NO_MEMLEAKS ?>
<?php after_script(); ?>
<?php endif; ?>

"API unit tests: [<?= $major_minor ?>]":
extends: .debug_test
needs:
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@
path = appsec/third_party/libddwaf-rust
url = https://github.com/DataDog/libddwaf-rust.git
branch = glopes/v2
[submodule "tests/FeatureFlags/ffe-system-test-data"]
path = tests/FeatureFlags/ffe-system-test-data
url = https://github.com/DataDog/ffe-system-test-data
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,12 @@ test_distributed_tracing_coverage:
test_metrics: global_test_run_dependencies
$(call run_tests,--testsuite=metrics $(TESTS))

test_featureflags: global_test_run_dependencies tests/OpenFeature/composer.lock-php$(PHP_MAJOR_MINOR)
$(eval FEATUREFLAGS_TEST_EXTRA_INI := $(TEST_EXTRA_INI))
$(eval TEST_EXTRA_INI=$(FEATUREFLAGS_TEST_EXTRA_INI) -d auto_prepend_file=$(PWD)/tests/OpenFeature/vendor/autoload.php)
$(call run_tests,--testsuite=featureflags $(TESTS))
$(eval TEST_EXTRA_INI=$(FEATUREFLAGS_TEST_EXTRA_INI))

benchmarks_run_dependencies: global_test_run_dependencies tests/Frameworks/Symfony/Version_5_2/composer.lock-php$(PHP_MAJOR_MINOR) tests/Frameworks/Laravel/Version_10_x/composer.lock-php$(PHP_MAJOR_MINOR) tests/Benchmarks/composer.lock-php$(PHP_MAJOR_MINOR)
php tests/Frameworks/Symfony/Version_5_2/bin/console cache:clear --no-warmup --env=prod

Expand Down
3 changes: 2 additions & 1 deletion components-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ libdd-telemetry-ffi = { path = "../libdatadog/libdd-telemetry-ffi", default-feat
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-remote-config = { path = "../libdatadog/datadog-remote-config" }
datadog-ffe = { path = "../libdatadog/datadog-ffe" }
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
33 changes: 33 additions & 0 deletions components-rs/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ typedef struct ddog_DebuggerPayload ddog_DebuggerPayload;

typedef struct ddog_DslString ddog_DslString;

typedef struct ddog_FfeResult ddog_FfeResult;

typedef struct ddog_HashMap_ShmCacheKey__ShmCache ddog_HashMap_ShmCacheKey__ShmCache;

/**
Expand Down Expand Up @@ -478,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 All @@ -495,6 +510,16 @@ typedef struct ddog_Tag {

typedef struct _zend_string *ddog_OwnedZendString;

struct ddog_FfeResult {
ddog_OwnedZendString value_json;
ddog_OwnedZendString variant;
ddog_OwnedZendString allocation_key;
int32_t reason;
int32_t error_code;
bool do_log;
bool valid;
};

typedef struct _zend_string *(*ddog_DynamicConfigUpdate)(ddog_CharSlice config,
ddog_OwnedZendString value,
enum ddog_DynamicConfigUpdateMode mode);
Expand Down Expand Up @@ -679,6 +704,14 @@ typedef struct ddog_Vec_DebuggerPayload {
*/
typedef uint64_t ddog_QueueId;

typedef struct ddog_FfeAttribute {
ddog_CharSlice key;
int32_t value_type;
ddog_CharSlice string_value;
double number_value;
bool bool_value;
} ddog_FfeAttribute;

/**
* A (key, value) pair for peer-service tags, borrowed from PHP/concentrator memory.
*/
Expand Down
16 changes: 13 additions & 3 deletions components-rs/ddtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ int posix_spawn_file_actions_addchdir_np(void *file_actions, const char *path);

uint64_t dd_fnv1a_64(const uint8_t *data, uintptr_t len);

bool ddog_ffe_load_config(ddog_CharSlice json);

bool ddog_ffe_has_config(void);

uint64_t ddog_ffe_config_version(void);

struct ddog_FfeResult ddog_ffe_evaluate(ddog_CharSlice flag_key,
int32_t expected_type,
ddog_CharSlice targeting_key,
const struct ddog_FfeAttribute *attributes,
uintptr_t attributes_count);

const char *ddog_normalize_process_tag_value(ddog_CharSlice tag_value);

void ddog_free_normalized_tag_value(const char *ptr);
Expand Down Expand Up @@ -118,9 +130,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
Loading
Loading