Skip to content
Draft
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
7 changes: 5 additions & 2 deletions metadata/supported-configurations.json
Original file line number Diff line number Diff line change
Expand Up @@ -609,11 +609,14 @@
"default": "false"
}
],
"DD_PROFILING_EXPERIMENTAL_IO_ENABLED": [
"DD_PROFILING_IO_ENABLED": [
{
"implementation": "A",
"type": "boolean",
"default": "false"
"default": "true",
"aliases": [
"DD_PROFILING_EXPERIMENTAL_IO_ENABLED"
]
}
],
"DD_PROFILING_LOG_LEVEL": [
Expand Down
37 changes: 20 additions & 17 deletions profiling/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use crate::profiling::bindings::zai_config_type::*;
use crate::profiling::bindings::{
datadog_php_profiling_copy_string_view_into_zval, ddog_php_prof_config_is_set_by_user,
ddog_php_prof_get_memoized_config, zai_config_entry, zai_config_get_value, zai_config_minit,
zai_config_name, zai_config_system_ini_change, zend_ini_entry, zend_long, zend_string,
zend_write, zval, StringError, ZaiStr, IS_FALSE, IS_LONG, IS_TRUE, ZAI_CONFIG_NAME_BUFSIZ,
ZEND_INI_DISPLAY_ORIG,
zai_config_minit_ini_change, zai_config_name, zai_config_system_ini_change, zend_ini_entry,
zend_long, zend_string, zend_write, zval, StringError, ZaiStr, IS_FALSE, IS_LONG, IS_TRUE,
ZAI_CONFIG_NAME_BUFSIZ, ZEND_INI_DISPLAY_ORIG,
};
use crate::profiling::zend::zai_str_from_zstr;
use crate::profiling::{allocation, bindings};
Expand Down Expand Up @@ -415,7 +415,7 @@ pub(crate) enum ConfigId {
ProfilingExceptionEnabled,
ProfilingExceptionMessageEnabled,
ProfilingExceptionSamplingDistance,
ProfilingExperimentalIOEnabled,
ProfilingIOEnabled,
ProfilingLogLevel,
ProfilingOutputPprof,
ProfilingWallTimeEnabled,
Expand Down Expand Up @@ -450,7 +450,7 @@ impl ConfigId {
ProfilingExceptionEnabled => b"DD_PROFILING_EXCEPTION_ENABLED\0",
ProfilingExceptionMessageEnabled => b"DD_PROFILING_EXCEPTION_MESSAGE_ENABLED\0",
ProfilingExceptionSamplingDistance => b"DD_PROFILING_EXCEPTION_SAMPLING_DISTANCE\0",
ProfilingExperimentalIOEnabled => b"DD_PROFILING_EXPERIMENTAL_IO_ENABLED\0",
ProfilingIOEnabled => b"DD_PROFILING_IO_ENABLED\0",
ProfilingLogLevel => b"DD_PROFILING_LOG_LEVEL\0",

// Note: this group is meant only for debugging and testing. Please
Expand Down Expand Up @@ -489,7 +489,7 @@ static DEFAULT_SYSTEM_SETTINGS: SystemSettings = SystemSettings {
profiling_exception_enabled: true,
profiling_exception_message_enabled: false,
profiling_wall_time_enabled: true,
profiling_io_enabled: false,
profiling_io_enabled: true,
output_pprof: None,
profiling_exception_sampling_distance: 100,
profiling_log_level: LevelFilter::Off,
Expand Down Expand Up @@ -625,11 +625,10 @@ unsafe fn profiling_exception_sampling_distance() -> u32 {
/// rinit, and before it is uninitialized in mshutdown.
unsafe fn profiling_io_enabled() -> bool {
profiling_enabled()
&& (profiling_experimental_features_enabled()
|| get_system_bool(
ProfilingExperimentalIOEnabled,
DEFAULT_SYSTEM_SETTINGS.profiling_io_enabled,
))
&& get_system_bool(
ProfilingIOEnabled,
DEFAULT_SYSTEM_SETTINGS.profiling_io_enabled,
)
}

/// # Safety
Expand Down Expand Up @@ -1002,6 +1001,9 @@ pub(crate) fn minit(module_number: libc::c_int) {
)]
};

const IO_ALIASES: &[ZaiStr] =
unsafe { &[ZaiStr::literal(b"DD_PROFILING_EXPERIMENTAL_IO_ENABLED\0")] };

// Note that function pointers cannot appear in const functions, so we
// can't extract each entry into a helper function.
static mut ENTRIES: &mut [zai_config_entry] = unsafe {
Expand Down Expand Up @@ -1139,13 +1141,13 @@ pub(crate) fn minit(module_number: libc::c_int) {
env_config_fallback: None,
},
zai_config_entry {
id: transmute::<ConfigId, u16>(ProfilingExperimentalIOEnabled),
name: ProfilingExperimentalIOEnabled.env_var_name(),
id: transmute::<ConfigId, u16>(ProfilingIOEnabled),
name: ProfilingIOEnabled.env_var_name(),
type_: ZAI_CONFIG_TYPE_BOOL,
default_encoded_value: ZaiStr::literal(b"0\0"),
aliases: ptr::null_mut(),
aliases_count: 0,
ini_change: Some(zai_config_system_ini_change),
default_encoded_value: ZaiStr::literal(b"1\0"),
aliases: IO_ALIASES.as_ptr(),
aliases_count: IO_ALIASES.len() as u8,
ini_change: Some(zai_config_minit_ini_change),
parser: None,
displayer: None,
env_config_fallback: None,
Expand Down Expand Up @@ -1405,6 +1407,7 @@ mod tests {
b"DD_PROFILING_TIMELINE_ENABLED\0",
"datadog.profiling.timeline_enabled",
),
(b"DD_PROFILING_IO_ENABLED\0", "datadog.profiling.io_enabled"),
(
b"DD_PROFILING_EXPERIMENTAL_IO_ENABLED\0",
"datadog.profiling.experimental_io_enabled",
Expand Down
1 change: 1 addition & 0 deletions profiling/tests/phpt/exceptions_01.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED=no
DD_PROFILING_EXPERIMENTAL_EXCEPTION_ENABLED=true
DD_PROFILING_EXPERIMENTAL_EXCEPTION_SAMPLING_DISTANCE=20
DD_PROFILING_ALLOCATION_ENABLED=no
DD_PROFILING_IO_ENABLED=no
DD_PROFILING_LOG_LEVEL=trace
--FILE--
<?php
Expand Down
1 change: 1 addition & 0 deletions profiling/tests/phpt/exceptions_zts_01.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED=no
DD_PROFILING_EXPERIMENTAL_EXCEPTION_ENABLED=true
DD_PROFILING_EXPERIMENTAL_EXCEPTION_SAMPLING_DISTANCE=20
DD_PROFILING_ALLOCATION_ENABLED=no
DD_PROFILING_IO_ENABLED=no
DD_PROFILING_LOG_LEVEL=trace
--FILE--
<?php
Expand Down
1 change: 1 addition & 0 deletions profiling/tests/phpt/gc_collect_cycles_01.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ DD_PROFILING_ENABLED=yes
DD_PROFILING_EXPERIMENTAL_CPU_TIME_ENABLED=no
DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED=yes
DD_PROFILING_ALLOCATION_ENABLED=no
DD_PROFILING_IO_ENABLED=no
DD_PROFILING_LOG_LEVEL=trace
--FILE--
<?php
Expand Down
1 change: 1 addition & 0 deletions profiling/tests/phpt/heap_live_01.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ DD_PROFILING_EXPERIMENTAL_HEAP_LIVE_ENABLED=yes
DD_PROFILING_ALLOCATION_SAMPLING_DISTANCE=1
DD_PROFILING_LOG_LEVEL=trace
DD_PROFILING_EXPERIMENTAL_CPU_TIME_ENABLED=no
DD_PROFILING_IO_ENABLED=no
--INI--
opcache.jit=off
--FILE--
Expand Down
1 change: 1 addition & 0 deletions profiling/tests/phpt/heap_live_02.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ DD_PROFILING_EXPERIMENTAL_HEAP_LIVE_ENABLED=yes
DD_PROFILING_ALLOCATION_SAMPLING_DISTANCE=1
DD_PROFILING_LOG_LEVEL=trace
DD_PROFILING_EXPERIMENTAL_CPU_TIME_ENABLED=no
DD_PROFILING_IO_ENABLED=no
--INI--
opcache.jit=off
--FILE--
Expand Down
29 changes: 29 additions & 0 deletions profiling/tests/phpt/io_config_01.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--TEST--
[profiling] I/O profiling configuration is system-only
--SKIPIF--
<?php
if (!extension_loaded('datadog-profiling'))
echo "skip: test requires Datadog Continuous Profiler\n";
?>
--INI--
assert.exception=1
datadog.profiling.io_enabled=0
--FILE--
<?php

$config = ini_get_all();
foreach ([
'datadog.profiling.io_enabled',
'datadog.profiling.experimental_io_enabled',
] as $name) {
assert($config[$name]['access'] === INI_SYSTEM);
assert(ini_get($name) === '0');
assert(ini_set($name, '1') === false);
assert(ini_get($name) === '0');
}

echo "Done.\n";

?>
--EXPECT--
Done.
2 changes: 1 addition & 1 deletion profiling/tests/phpt/phpinfo_03.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ $sections = [
["Experimental CPU Time Profiling Enabled", "false"],
["Allocation Profiling Enabled", "false"],
["Exception Profiling Enabled", "false"],
["I/O Profiling Enabled", "false"],
["I/O Profiling Enabled", "true"],
["Endpoint Collection Enabled", "true"],
["Profiling Log Level", "off"],
["Profiling Agent Endpoint", "http://datadog:8126/"],
Expand Down
3 changes: 3 additions & 0 deletions profiling/tests/phpt/phpinfo_05.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ DD_PROFILING_ALLOCATION_ENABLED=no
DD_PROFILING_EXPERIMENTAL_ALLOCATION_ENABLED=yes
DD_PROFILING_EXCEPTION_ENABLED=no
DD_PROFILING_EXPERIMENTAL_EXCEPTION_ENABLED=yes
DD_PROFILING_IO_ENABLED=no
DD_PROFILING_EXPERIMENTAL_IO_ENABLED=yes
--INI--
assert.exception=1
opcache.jit=off
Expand Down Expand Up @@ -43,6 +45,7 @@ $sections = [
["Profiling Enabled", "true"],
["Allocation Profiling Enabled", "false"],
["Exception Profiling Enabled", "false"],
["I/O Profiling Enabled", "false"],
];

foreach ($sections as [$key, $expected]) {
Expand Down
3 changes: 2 additions & 1 deletion profiling/tests/phpt/phpinfo_07.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ DD_PROFILING_EXPERIMENTAL_CPU_TIME_ENABLED=no
DD_PROFILING_ALLOCATION_ENABLED=no
DD_PROFILING_EXCEPTION_ENABLED=no
DD_PROFILING_TIMELINE_ENABLED=no
DD_PROFILING_EXPERIMENTAL_IO_ENABLED=no
--INI--
assert.exception=1
opcache.jit=off
Expand Down Expand Up @@ -48,7 +49,7 @@ $sections = [
["Allocation Profiling Enabled", "false"],
["Exception Profiling Enabled", "false"],
["Timeline Enabled", "false"],
["I/O Profiling Enabled", "true"],
["I/O Profiling Enabled", "false"],
];

foreach ($sections as [$key, $expected]) {
Expand Down
8 changes: 7 additions & 1 deletion zend_abstract_interface/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,9 @@ void zai_config_first_time_rinit(bool in_request) {

for (uint16_t i = 0; i < zai_config_memoized_entries_count; i++) {
zai_config_memoized_entry *memoized = &zai_config_memoized_entries[i];
zai_config_find_and_set_value(memoized, i, in_request);
if (!in_request || memoized->ini_change != zai_config_minit_ini_change) {
zai_config_find_and_set_value(memoized, i, in_request);
}
#if PHP_VERSION_ID >= 70300
zai_config_intern_zval(&memoized->decoded_value);
#else
Expand Down Expand Up @@ -331,3 +333,7 @@ bool zai_config_system_ini_change(zval *old_value, zval *new_value, zend_string
(void)new_str;
return false;
}

bool zai_config_minit_ini_change(zval *old_value, zval *new_value, zend_string *new_str) {
return zai_config_system_ini_change(old_value, new_value, new_str);
}
5 changes: 3 additions & 2 deletions zend_abstract_interface/config/config_ini.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ static void zai_config_add_ini_entry(zai_config_memoized_entry *memoized, zai_st
entry->value = memoized->default_encoded_value.ptr;
entry->value_length = memoized->default_encoded_value.len;
entry->on_modify = ZaiConfigOnUpdateIni;
entry->modifiable = memoized->ini_change == zai_config_system_ini_change ? PHP_INI_SYSTEM : PHP_INI_ALL;
entry->modifiable =
memoized->ini_change == zai_config_system_ini_change || memoized->ini_change == zai_config_minit_ini_change ? PHP_INI_SYSTEM : PHP_INI_ALL;

if (memoized->displayer) {
entry->displayer = memoized->displayer;
Expand Down Expand Up @@ -441,7 +442,7 @@ void zai_config_ini_rinit(void) {
for (uint16_t i = 0; i < zai_config_memoized_entries_count; ++i) {
ZAI_ENV_BUFFER_INIT(buf, ZAI_ENV_MAX_BUFSIZ);
zai_config_memoized_entry *memoized = &zai_config_memoized_entries[i];
if (memoized->ini_change == zai_config_system_ini_change) {
if (memoized->ini_change == zai_config_system_ini_change || memoized->ini_change == zai_config_minit_ini_change) {
continue;
}

Expand Down
2 changes: 2 additions & 0 deletions zend_abstract_interface/config/config_ini.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ typedef bool (*zai_config_apply_ini_change)(zval *old_value, zval *new_value, ze
typedef bool (*zai_env_config_fallback)(zai_env_buffer *buf, bool pre_rinit);

bool zai_config_system_ini_change(zval *old_value, zval *new_value, zend_string *new_str);
// A PHP_INI_SYSTEM value that cannot be refreshed from SAPI config after MINIT.
bool zai_config_minit_ini_change(zval *old_value, zval *new_value, zend_string *new_str);

bool zai_config_is_modified(zai_config_id entry_id);
void zai_config_change_default_ini(zai_config_id entry_id, zai_str str);
11 changes: 9 additions & 2 deletions zend_abstract_interface/config/tests/ini.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ typedef enum {
EXT_CFG_INI_BAR_ALIASED_INT,
EXT_CFG_INI_BAR_ALIASED_STRING,
EXT_CFG_INI_BAZ_MAP_EMPTY,
EXT_CFG_INI_MINIT_BOOL,
} ext_ini_cfg_id;

static void ext_ini_env_to_ini_name(zai_str env_name, zai_config_name *ini_name) {
Expand All @@ -35,6 +36,7 @@ static PHP_MINIT_FUNCTION(zai_config_ini) {
EXT_CFG_ALIASED_ENTRY(INI_BAR_ALIASED_INT, INT, "0", aliases_int),
EXT_CFG_ALIASED_ENTRY(INI_BAR_ALIASED_STRING, STRING, "0", aliases_string),
EXT_CFG_ENTRY(INI_BAZ_MAP_EMPTY, MAP, ""),
ZAI_CONFIG_ENTRY(EXT_CFG_INI_MINIT_BOOL, INI_MINIT_BOOL, BOOL, "1", .ini_change = zai_config_minit_ini_change),
};
if (!zai_config_minit(entries, (sizeof entries / sizeof entries[0]), ext_ini_env_to_ini_name, module_number)) {
return FAILURE;
Expand Down Expand Up @@ -551,6 +553,7 @@ static char *second_consumer_sapi_getenv(char *name, size_t name_len) {
if (second_consumer_sapi_phase == 0) {
if (strcmp(name, "INI_FOO_STRING") == 0) return estrdup("sapi_val");
if (strcmp(name, "INI_FOO_INT") == 0) return estrdup("2");
if (strcmp(name, "INI_MINIT_BOOL") == 0) return estrdup("0");
} else if (second_consumer_sapi_phase == 1) {
if (strcmp(name, "INI_FOO_INT") == 0) return estrdup("3");
}
Expand All @@ -562,8 +565,8 @@ static char *second_consumer_sapi_getenv(char *name, size_t name_len) {
// 1. SAPI is consulted on every rinit, including the first; sys env cache (set at minit) is the
// fallback when SAPI returns NULL — consulting SAPI on first rinit is required for backwards
// compatibility with health metrics
// 2. SAPI env takes priority over sys env for ALL entries, including those with original_on_modify —
// the presence of a second consumer does not affect SAPI precedence
// 2. SAPI env takes priority over sys env for regular entries, including those with
// original_on_modify; MINIT-only entries remain unchanged
// 3. Sys env changes between requests are NOT reflected — the cache is immutable after minit (request 3)
TEA_TEST_CASE_BARE("config/ini", "second consumer extension causes original_on_modify to be set", {
REQUIRE(tea_sapi_sinit());
Expand Down Expand Up @@ -593,6 +596,10 @@ TEA_TEST_CASE_BARE("config/ini", "second consumer extension causes original_on_m
REQUIRE(Z_TYPE_P(int_val) == IS_LONG);
REQUIRE(Z_LVAL_P(int_val) == 2); // SAPI "2" overrides sys cache "1"

zval *minit_val = zai_config_get_value(EXT_CFG_INI_MINIT_BOOL);
REQUIRE(minit_val != NULL);
REQUIRE(Z_TYPE_P(minit_val) == IS_TRUE); // SAPI "0" cannot replace the MINIT value

REQUEST_END()

// Change sys env between requests — cache is immutable after minit, this is ignored.
Expand Down
Loading