Skip to content

Commit dc920e6

Browse files
authored
Support the frankenphp SAPI (#2602)
* Support the frankenphp SAPI Signed-off-by: Bob Weinand <[email protected]> * Skip on NTS * Remove debug stmt * Use WeakMap for frankenphp closure Signed-off-by: Bob Weinand <[email protected]> --------- Signed-off-by: Bob Weinand <[email protected]>
1 parent 7169ff4 commit dc920e6

File tree

24 files changed

+519
-16
lines changed

24 files changed

+519
-16
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ TEST_INTEGRATIONS_82 := \
891891
test_integrations_elasticsearch7 \
892892
test_integrations_elasticsearch8 \
893893
test_integrations_predis1 \
894+
test_integrations_frankenphp \
894895
test_integrations_roadrunner \
895896
test_integrations_sqlsrv \
896897
test_integrations_swoole_5 \
@@ -943,6 +944,7 @@ TEST_INTEGRATIONS_83 := \
943944
test_integrations_elasticsearch7 \
944945
test_integrations_elasticsearch8 \
945946
test_integrations_predis1 \
947+
test_integrations_frankenphp \
946948
test_integrations_roadrunner \
947949
test_integrations_sqlsrv \
948950
test_integrations_swoole_5 \
@@ -1217,6 +1219,9 @@ test_integrations_phpredis5: global_test_run_dependencies
12171219
test_integrations_predis1: global_test_run_dependencies
12181220
$(MAKE) test_scenario_predis1
12191221
$(call run_tests_debug,tests/Integrations/Predis)
1222+
test_integrations_frankenphp: global_test_run_dependencies
1223+
$(MAKE) test_scenario_default
1224+
$(call run_tests_debug,--testsuite=frankenphp-test)
12201225
test_integrations_roadrunner: global_test_run_dependencies
12211226
$(call run_composer_with_retry,tests/Frameworks/Roadrunner/Version_2,)
12221227
$(call run_tests_debug,tests/Integrations/Roadrunner/V2)

bridge/_files_integrations.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
__DIR__ . '/../src/Integrations/Integrations/Mongo/MongoIntegration.php',
3131
__DIR__ . '/../src/Integrations/Integrations/MongoDB/MongoDBIntegration.php',
3232
__DIR__ . '/../src/Integrations/Integrations/Slim/SlimIntegration.php',
33+
__DIR__ . '/../src/Integrations/Integrations/Frankenphp/FrankenphpIntegration.php',
3334
__DIR__ . '/../src/Integrations/Integrations/Swoole/SwooleIntegration.php',
3435
__DIR__ . '/../src/Integrations/Integrations/SQLSRV/SQLSRVIntegration.php',
3536
__DIR__ . '/../src/Integrations/Integrations/Symfony/SymfonyIntegration.php',

dockerfiles/ci/buster/Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ ENV DEVLIBS \
1414
libclang-rt-16-dev \
1515
llvm-16-dev \
1616
lld-16 \
17+
libbrotli-dev \
1718
libcurl4-openssl-dev \
1819
libedit-dev \
1920
libffi-dev \
@@ -282,6 +283,20 @@ RUN mkdir -p -v "${CARGO_HOME}" "${RUSTUP_HOME}" \
282283

283284
ENV PATH="/rust/cargo/bin:${PATH}"
284285

286+
ARG GO_VERSION="1.22.1"
287+
ARG GO_SHA256_ARM="e56685a245b6a0c592fc4a55f0b7803af5b3f827aaa29feab1f40e491acf35b8"
288+
ARG GO_SHA256_X86="aab8e15785c997ae20f9c88422ee35d962c4562212bb0f879d052a35c8307c7f"
289+
ENV GOROOT=/go
290+
RUN MARCH=$(uname -m) \
291+
&& GO_SHA256=$(if [ "$MARCH" = "x86_64" ]; then echo ${GO_SHA256_X86}; elif [ "$MARCH" = "aarch64" ]; then echo ${GO_SHA256_ARM}; fi) \
292+
&& FILENAME=go${GO_VERSION}.linux-$(if [ "$MARCH" = "x86_64" ]; then echo amd64; elif [ "$MARCH" = "aarch64" ]; then echo arm64; fi).tar.gz \
293+
&& curl -L --write-out '%{http_code}' -O https://go.dev/dl/${FILENAME} \
294+
&& printf '%s %s' "$GO_SHA256" "$FILENAME" | sha256sum --check --status \
295+
&& tar -xf "$FILENAME" -C / \
296+
&& rm "${FILENAME}"
297+
298+
ENV PATH="/go/bin:${PATH}"
299+
285300
# Add the wait script to the image: note SHA 672a28f0509433e3b4b9bcd4d9cd7668cea7e31a has been reviewed and should not
286301
# be changed without an appropriate code review.
287302
ADD https://raw.githubusercontent.com/eficode/wait-for/672a28f0509433e3b4b9bcd4d9cd7668cea7e31a/wait-for /usr/bin/wait-for

dockerfiles/ci/buster/build-php.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ ${PHP_SRC_DIR}/configure \
7979
$(if [[ $INSTALL_VERSION == *zts* ]]; then echo --enable$(if grep -q 'maintainer-zts' ${PHP_SRC_DIR}/configure; then echo "-maintainer"; fi)-zts; fi) \
8080
`# https://externals.io/message/118859` \
8181
$(if [[ $INSTALL_VERSION == *zts* ]]; then echo --disable-zend-signals; fi) \
82+
$(if [[ $INSTALL_VERSION == *zts* && ${PHP_VERSION_ID} -ge 82 ]]; then echo --enable-zend-max-execution-timers; fi) \
8283
--prefix=${INSTALL_DIR} \
8384
--with-config-file-path=${INSTALL_DIR} \
8485
--with-config-file-scan-dir=${INSTALL_DIR}/conf.d

dockerfiles/ci/buster/switch-php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ sudo ln -sf /opt/php/${phpVersion}/bin/php-config /usr/local/bin/php-config
1818
sudo ln -sf /opt/php/${phpVersion}/bin/phpdbg /usr/local/bin/phpdbg
1919
sudo ln -sf /opt/php/${phpVersion}/bin/phpize /usr/local/bin/phpize
2020
sudo ln -sf /opt/php/${phpVersion}/sbin/php-fpm /usr/local/bin/php-fpm
21+
sudo ln -sf /opt/php/${phpVersion}/lib/libphp.so /usr/lib/libphp.so
22+
sudo ln -sf /opt/php/${phpVersion}/bin/frankenphp /usr/local/bin/frankenphp
2123
if [ "${phpVersion}" != *asan* ]; then
2224
sudo ln -sf /opt/php/${phpVersion}/lib/apache2handler-libphp.so /usr/lib/apache2/modules/libphp.so
2325
fi

ext/ddtrace.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <Zend/zend_exceptions.h>
1010
#include <Zend/zend_extensions.h>
1111
#include <Zend/zend_smart_str.h>
12-
#include <components/sapi/sapi.h>
1312
#include <headers/headers.h>
1413
#include <hook/hook.h>
1514
#include <json/json.h>
@@ -118,7 +117,7 @@ static bool dd_has_other_observers;
118117
static int dd_observer_extension_backup = -1;
119118
#endif
120119

121-
static datadog_php_sapi ddtrace_active_sapi = DATADOG_PHP_SAPI_UNKNOWN;
120+
datadog_php_sapi ddtrace_active_sapi = DATADOG_PHP_SAPI_UNKNOWN;
122121

123122
_Atomic(int64_t) ddtrace_warn_legacy_api;
124123

@@ -2651,11 +2650,14 @@ static ddtrace_distributed_tracing_result dd_parse_distributed_tracing_headers_f
26512650
UNUSED(return_value);
26522651

26532652
dd_fci_fcc_pair func;
2653+
bool use_server_headers = false;
26542654
zend_array *array = NULL;
26552655

26562656
ZEND_PARSE_PARAMETERS_START(1, 1)
26572657
DD_PARAM_PROLOGUE(0, 0);
2658-
if (UNEXPECTED(!zend_parse_arg_func(_arg, &func.fci, &func.fcc, false, &_error, true))) {
2658+
if (Z_TYPE_P(_arg) == IS_NULL) {
2659+
use_server_headers = true;
2660+
} else if (UNEXPECTED(!zend_parse_arg_func(_arg, &func.fci, &func.fcc, false, &_error, true))) {
26592661
if (!_error) {
26602662
zend_argument_type_error(1, "must be a valid callback or of type array, %s given", zend_zval_value_name(_arg));
26612663
_error_code = ZPP_ERROR_FAILURE;
@@ -2687,6 +2689,8 @@ static ddtrace_distributed_tracing_result dd_parse_distributed_tracing_headers_f
26872689

26882690
if (array) {
26892691
return ddtrace_read_distributed_tracing_ids(dd_read_array_header, array);
2692+
} else if (use_server_headers) {
2693+
return ddtrace_read_distributed_tracing_ids(ddtrace_read_zai_header, &func);
26902694
} else {
26912695
return ddtrace_read_distributed_tracing_ids(dd_read_userspace_header, &func);
26922696
}

ext/ddtrace.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <stdbool.h>
55
#include <stdint.h>
66
#include <components-rs/ddtrace.h>
7+
#include <components/sapi/sapi.h>
78

89
#ifndef _WIN32
910
#include <dogstatsd_client/client.h>
@@ -25,6 +26,8 @@ typedef struct ddtrace_root_span_data ddtrace_root_span_data;
2526
typedef struct ddtrace_span_stack ddtrace_span_stack;
2627
typedef struct ddtrace_span_link ddtrace_span_link;
2728

29+
extern datadog_php_sapi ddtrace_active_sapi;
30+
2831
static inline zend_array *ddtrace_property_array(zval *zv) {
2932
ZVAL_DEREF(zv);
3033
if (Z_TYPE_P(zv) != IS_ARRAY) {

ext/ddtrace.stub.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,11 @@ function get_sanitized_exception_trace(\Exception|\Throwable $exception, int $sk
486486
* Update datadog headers for distributed tracing for new spans. Also applies this information to the current trace,
487487
* if there is one, as well as the future ones if it isn't overwritten
488488
*
489-
* @param array|callable(string):mixed $headersOrCallback Either an array with a lowercase header to value mapping,
490-
* or a callback, which given a header name for distributed tracing, returns the value it should be updated to.
489+
* @param null|array|callable(string):mixed $headersOrCallback Either an array with a lowercase header to value mapping,
490+
* or a callback, which given a header name for distributed tracing, returns the value it should be updated to. If null,
491+
* this reads the headers directly from the $_SERVER superglobal.
491492
*/
492-
function consume_distributed_tracing_headers(array|callable $headersOrCallback): void {}
493+
function consume_distributed_tracing_headers(null|array|callable $headersOrCallback): void {}
493494

494495
/**
495496
* Get information on the key-value pairs of the datadog headers for distributed tracing

ext/ddtrace_arginfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_get_sanitized_exception_
9090
ZEND_END_ARG_INFO()
9191

9292
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_consume_distributed_tracing_headers, 0, 1, IS_VOID, 0)
93-
ZEND_ARG_TYPE_MASK(0, headersOrCallback, MAY_BE_ARRAY|MAY_BE_CALLABLE, NULL)
93+
ZEND_ARG_TYPE_MASK(0, headersOrCallback, MAY_BE_NULL|MAY_BE_ARRAY|MAY_BE_CALLABLE, NULL)
9494
ZEND_END_ARG_INFO()
9595

9696
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_generate_distributed_tracing_headers, 0, 0, IS_ARRAY, 0)

ext/integrations/integrations.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ typedef struct {
5252
} dd_integration_aux;
5353

5454
void dd_integration_aux_free(void *auxiliary) {
55-
dd_integration_aux *aux = auxiliary;
56-
zend_string_release(aux->classname);
57-
free(aux);
55+
free(auxiliary);
5856
}
5957

6058
static void dd_invoke_integration_loader_and_unhook_posthook(zend_ulong invocation, zend_execute_data *execute_data, zval *retval, void *auxiliary, void *dynamic) {
@@ -104,7 +102,7 @@ static bool dd_invoke_integration_loader_and_unhook_prehook(zend_ulong invocatio
104102
static void dd_hook_method_and_unhook_on_first_call(zai_str Class, zai_str method, zai_str callback, ddtrace_integration_name name, bool posthook) {
105103
dd_integration_aux *aux = malloc(sizeof(*aux));
106104
aux->name = name;
107-
aux->classname = zend_string_init(callback.ptr, callback.len, 1);
105+
aux->classname = zend_string_init_interned(callback.ptr, callback.len, 1);
108106
aux->id = zai_hook_install(Class, method,
109107
posthook ? NULL : dd_invoke_integration_loader_and_unhook_prehook,
110108
posthook ? dd_invoke_integration_loader_and_unhook_posthook : NULL,
@@ -194,6 +192,11 @@ void ddtrace_integrations_minit(void) {
194192
DD_SET_UP_DEFERRED_LOADING_BY_METHOD(DDTRACE_INTEGRATION_ELOQUENT, "Illuminate\\Database\\Eloquent\\Model", "destroy",
195193
"DDTrace\\Integrations\\Eloquent\\EloquentIntegration");
196194

195+
#if PHP_VERSION_ID >= 80200
196+
DD_SET_UP_DEFERRED_LOADING_BY_FUNCTION(DDTRACE_INTEGRATION_FRANKENPHP, "frankenphp_handle_request",
197+
"DDTrace\\Integrations\\Frankenphp\\FrankenphpIntegration");
198+
#endif
199+
197200
DD_SET_UP_DEFERRED_LOADING_BY_METHOD(DDTRACE_INTEGRATION_GUZZLE, "GuzzleHttp\\Client", "__construct",
198201
"DDTrace\\Integrations\\Guzzle\\GuzzleIntegration");
199202

0 commit comments

Comments
 (0)