Skip to content

Commit 72632b8

Browse files
iamlucbwoebi
andauthored
Init the new loader extension (#2684)
* Init the dd_library_loader extension for Single Step Instrumentation * Move load of the extension directly in the api_no_check * Check the 'core' ext instead of 'json' * Make the code more robust and PHP 5 compatible * Rename variable for clarity + suppress compiler warning * Init CI jobs * CI try to fix Docke issue with Alpine image * Register ddtrace during the registration of the loader again. To workaround the "Module alreay loaded" issue, register ddtrace under the name "ddtrace_injected", then remame it at starup if "ddtrace" is not loaded * Rename the module key at the bucket level * Remove PHP5 support + cleanup * Fix compat for all PHP 7.x * Cleanup compat code + rework deps handling * Remove custom zend_hash_find_bucket thanks to Bob's trick * Use a weak pointer to use the real implementation of zend_hash_set_bucket_key if it exists * Add defensive barriers * Improve logs by adding log level and allowing variadic args * Fix renaming of the module not working properly * Init tests * Fix zend_string_init/_release compat with PHP <= 7.2 * Reformat code * Init README.md * Add optional dependencies to 'json' and 'standard' modules to make sure ddtrace_injected is loaded after them * Apply suggestions from code review Co-authored-by: Bob Weinand <[email protected]> * Fix some review's comments * Log error when registering module * Make the code generic to load every Datadog extensions * Init telemetry support * Workaround PHP 7.2 segfault * Cleanup .gitignore and config.w32 * Improve telemetry * Retrieve the runtime_version from the engine to work even with future unknown versions * Compile with -Wextra -Werror * Add tests * Merge loader pipeline back into build_packages * Fix typo * Fix zend_error_cb handling * Fix CI * Set 'datadog.trace.sources_path' INI setting when ddtrace_injected is used * Fix coding style (using clang-format) * Don't use symbols that don't exist in PHP5 to avoid a missing symbol error * Fix telemetry_forwarder arguments * Fix segfault on PHP 7.2 when calling zend_string_release * Add test loading using PHP_INI_SCAN_DIR env var * Address Bob's comments * Make DD_LOADER_PACKAGE_PATH env var mandatory --------- Co-authored-by: Bob Weinand <[email protected]>
1 parent 505623f commit 72632b8

24 files changed

+1572
-1
lines changed

.circleci/continue_config.yml

+263-1
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ commands:
534534
-v /tmp/artifacts:/tmp/artifacts \
535535
$(if [ -n "${CARGO_TARGET_DIR:-}" ]; then echo -v ${CARGO_TARGET_DIR}:${CARGO_TARGET_DIR} -e CARGO_TARGET_DIR=${CARGO_TARGET_DIR}; fi) \
536536
$image \
537-
bash -c 'echo Started; sleep 10000' 2>&1 | tee /tmp/docker.out &
537+
sh -c 'echo Started; sleep 10000' 2>&1 | tee /tmp/docker.out &
538538
tail -F /tmp/docker.out | grep -Em1 'Started|Error response from daemon'
539539
if ! grep -q "Error response from daemon" /tmp/docker.out; then
540540
container_name=$(docker ps | grep "$image" | awk '{ print $NF }' | head -1)
@@ -549,6 +549,10 @@ commands:
549549
fi
550550
sleep 1
551551
done
552+
# On Alpine images, make sure bash is installed
553+
if [[ "<< parameters.docker_image >>" == *alpine* ]]; then
554+
docker exec -w /home/circleci/datadog -i "${container_name}" sh -c "test -z bash || apk --no-cache add bash" || true
555+
fi
552556
echo 'if [ -f /usr/bin/docker ]; then pid=$$; IFS= readarray -d "" args < <(cat /proc/$pid/cmdline); exec docker exec -w /home/circleci/datadog -i '"${container_name}"' "${args[@]}"; fi' | tee -a $BASH_ENV
553557
cp $BASH_ENV /tmp/bashenv/bash.sh
554558
chmod 777 /tmp/bashenv/bash.sh
@@ -2941,6 +2945,129 @@ jobs:
29412945
sed -i -e "s/crate-type.*$/crate-type = [\"rlib\"]/g" Cargo.toml
29422946
cargo clippy --all-targets --all-features -- -D warnings -Aunknown-lints
29432947
2948+
"compile_loader":
2949+
working_directory: ~/datadog
2950+
parameters:
2951+
docker_image:
2952+
type: string
2953+
os:
2954+
type: string
2955+
resource_class:
2956+
type: string
2957+
default: medium
2958+
<<: *BARE_DOCKER_MACHINE
2959+
steps:
2960+
- restore_cache:
2961+
keys:
2962+
- source-v1-{{ .Branch }}-{{ .Revision }}
2963+
- <<: *STEP_CHECKOUT
2964+
- <<: *STEP_ATTACH_WORKSPACE
2965+
- setup_docker:
2966+
docker_image: << parameters.docker_image >>
2967+
- run:
2968+
name: Compile the loader extension
2969+
command: |
2970+
set -xeuo pipefail
2971+
2972+
if [[ "<< parameters.os >>" == "linux-musl" ]]; then
2973+
apk add --no-cache \
2974+
autoconf \
2975+
coreutils \
2976+
g++ \
2977+
gcc \
2978+
make
2979+
fi
2980+
2981+
cd loader
2982+
phpize
2983+
./configure
2984+
make clean
2985+
make -j all ECHO_ARG="-e" CFLAGS="-std=gnu11 -O2 -g -Wall -Wextra -Werror"
2986+
cp modules/dd_library_loader.so modules/dd_library_loader-$(uname -m)-<< parameters.os >>.so
2987+
- persist_to_workspace:
2988+
root: '.'
2989+
paths: [ './loader/modules/dd_library_loader-*.so' ]
2990+
- store_artifacts:
2991+
path: ./loader/modules/dd_library_loader.so
2992+
2993+
"test_loader_linux":
2994+
working_directory: ~/datadog
2995+
parameters:
2996+
docker_image:
2997+
type: string
2998+
php_major_minor:
2999+
# Expected in the format: <major>.<minor>, e.g. 8.2
3000+
type: string
3001+
switch_php_version:
3002+
type: string
3003+
default: none
3004+
resource_class:
3005+
type: string
3006+
default: medium
3007+
<<: *BARE_DOCKER_MACHINE
3008+
steps:
3009+
- restore_cache:
3010+
keys:
3011+
- source-v1-{{ .Branch }}-{{ .Revision }}
3012+
- <<: *STEP_CHECKOUT
3013+
- <<: *STEP_ATTACH_WORKSPACE
3014+
- setup_docker:
3015+
docker_image: << parameters.docker_image >>
3016+
- switch_php:
3017+
php_version: << parameters.switch_php_version >>
3018+
- run:
3019+
name: Test the loader
3020+
command: |
3021+
set -xeuo pipefail
3022+
3023+
arch=$(uname -m)
3024+
package=$(find ./build/packages -maxdepth 1 -name "dd-library-php-*-${arch}-linux-gnu.tar.gz")
3025+
rm -rf dd-library-php
3026+
tar -xzf ${package}
3027+
export DD_LOADER_PACKAGE_PATH=${PWD}/dd-library-php
3028+
3029+
cd loader
3030+
cp modules/dd_library_loader-$(uname -m)-linux-gnu.so modules/dd_library_loader.so
3031+
./bin/test.sh
3032+
3033+
"test_loader_alpine":
3034+
working_directory: ~/datadog
3035+
parameters:
3036+
docker_image:
3037+
type: string
3038+
alpine_version:
3039+
type: string
3040+
alpine_packages:
3041+
type: string
3042+
resource_class:
3043+
type: string
3044+
default: medium
3045+
<<: *BARE_DOCKER_MACHINE
3046+
steps:
3047+
- restore_cache:
3048+
keys:
3049+
- source-v1-{{ .Branch }}-{{ .Revision }}
3050+
- <<: *STEP_CHECKOUT
3051+
- <<: *STEP_ATTACH_WORKSPACE
3052+
- setup_docker:
3053+
docker_image: << parameters.docker_image >>
3054+
- run:
3055+
name: Test the loader
3056+
command: |
3057+
set -xeuo pipefail
3058+
3059+
apk add --no-cache curl-dev << parameters.alpine_packages >>
3060+
3061+
arch=$(uname -m)
3062+
package=$(find ./build/packages -maxdepth 1 -name "dd-library-php-*-${arch}-linux-musl.tar.gz")
3063+
rm -rf dd-library-php
3064+
tar -xzf ${package}
3065+
export DD_LOADER_PACKAGE_PATH=${PWD}/dd-library-php
3066+
3067+
cd loader
3068+
cp modules/dd_library_loader-$(uname -m)-linux-musl.so modules/dd_library_loader.so
3069+
./bin/test.sh
3070+
29443071
compile_extension_centos:
29453072
working_directory: ~/datadog
29463073
parameters:
@@ -4418,6 +4545,141 @@ workflows:
44184545
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
44194546
TEST_LIBRARY=php ./run.sh PARAMETRIC
44204547
4548+
- "compile_loader":
4549+
requires: [ 'Prepare Code' ]
4550+
name: "Compile Loader Linux x86_64"
4551+
docker_image: "datadog/dd-trace-ci:php-8.3_buster"
4552+
resource_class: "medium"
4553+
os: "linux-gnu"
4554+
4555+
- "compile_loader":
4556+
requires: [ 'Prepare Code' ]
4557+
name: "Compile Loader Linux aarch64"
4558+
docker_image: "datadog/dd-trace-ci:php-8.3_buster"
4559+
resource_class: "arm.medium"
4560+
os: "linux-gnu"
4561+
4562+
- "compile_loader":
4563+
requires: [ 'Prepare Code' ]
4564+
name: "Compile Loader Alpine x86_64"
4565+
docker_image: "datadog/dd-trace-ci:php-compile-extension-alpine-8.0"
4566+
resource_class: "medium"
4567+
os: "linux-musl"
4568+
4569+
- "compile_loader":
4570+
requires: [ 'Prepare Code' ]
4571+
name: "Compile Loader Alpine aarch64"
4572+
docker_image: "datadog/dd-trace-ci:php-compile-extension-alpine-8.0"
4573+
resource_class: "arm.medium"
4574+
os: "linux-musl"
4575+
4576+
- "test_loader_linux":
4577+
requires:
4578+
- "package extension"
4579+
- "Compile Loader Linux x86_64"
4580+
name: "[Linux/x86_64] Loader PHP << matrix.php_major_minor >>-<< matrix.switch_php_version >>"
4581+
docker_image: "datadog/dd-trace-ci:php-<< matrix.php_major_minor >>_buster"
4582+
resource_class: "medium"
4583+
matrix:
4584+
parameters:
4585+
php_major_minor:
4586+
- "5.6"
4587+
- "7.0"
4588+
- "7.1"
4589+
- "7.2"
4590+
- "7.3"
4591+
switch_php_version:
4592+
- debug
4593+
- nts
4594+
4595+
- "test_loader_linux":
4596+
requires:
4597+
- "package extension"
4598+
- "Compile Loader Linux x86_64"
4599+
name: "[Linux/x86_64] Loader PHP << matrix.php_major_minor >>-<< matrix.switch_php_version >>"
4600+
docker_image: "datadog/dd-trace-ci:php-<< matrix.php_major_minor >>_buster"
4601+
resource_class: "medium"
4602+
matrix:
4603+
parameters:
4604+
php_major_minor:
4605+
- "7.4"
4606+
- "8.0"
4607+
- "8.1"
4608+
- "8.2"
4609+
- "8.3"
4610+
switch_php_version:
4611+
- debug
4612+
- zts
4613+
- nts
4614+
4615+
- "test_loader_linux":
4616+
requires:
4617+
- "package extension"
4618+
- "Compile Loader Linux aarch64"
4619+
name: "[Linux/aarch64] Loader PHP << matrix.php_major_minor >>-<< matrix.switch_php_version >>"
4620+
docker_image: "datadog/dd-trace-ci:php-<< matrix.php_major_minor >>_buster"
4621+
resource_class: "arm.medium"
4622+
matrix:
4623+
parameters:
4624+
php_major_minor:
4625+
- "7.0"
4626+
- "7.1"
4627+
- "7.2"
4628+
- "7.3"
4629+
switch_php_version:
4630+
- debug
4631+
- nts
4632+
4633+
- "test_loader_linux":
4634+
requires:
4635+
- "package extension"
4636+
- "Compile Loader Linux aarch64"
4637+
name: "[Linux/aarch64] Loader PHP << matrix.php_major_minor >>-<< matrix.switch_php_version >>"
4638+
docker_image: "datadog/dd-trace-ci:php-<< matrix.php_major_minor >>_buster"
4639+
resource_class: "arm.medium"
4640+
matrix:
4641+
parameters:
4642+
php_major_minor:
4643+
- "7.4"
4644+
- "8.0"
4645+
- "8.1"
4646+
- "8.2"
4647+
- "8.3"
4648+
switch_php_version:
4649+
- debug
4650+
- zts
4651+
- nts
4652+
4653+
- "test_loader_alpine":
4654+
requires:
4655+
- "package extension"
4656+
- "Compile Loader Alpine x86_64"
4657+
name: "[Alpine/x86_64] Loader PHP Alpine << matrix.alpine_version >>"
4658+
docker_image: "alpine:<< matrix.alpine_version >>"
4659+
resource_class: "medium"
4660+
alpine_packages: "php83 php83-dev"
4661+
matrix:
4662+
parameters:
4663+
alpine_version:
4664+
# - "3.19"
4665+
- "3.20"
4666+
# - "latest"
4667+
4668+
- "test_loader_alpine":
4669+
requires:
4670+
- "package extension"
4671+
- "Compile Loader Alpine aarch64"
4672+
name: "[Alpine/aarch64] Loader PHP Alpine << matrix.alpine_version >>"
4673+
docker_image: "alpine:<< matrix.alpine_version >>"
4674+
resource_class: "arm.medium"
4675+
alpine_packages: "php83 php83-dev"
4676+
matrix:
4677+
parameters:
4678+
alpine_version:
4679+
# - "3.19"
4680+
- "3.20"
4681+
# - "latest"
4682+
44214683
build:
44224684
when: << pipeline.parameters.build >>
44234685
jobs:

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@ composer.lock*
1313
.tmp/
1414
**.code-workspace
1515
/Makefile*
16+
/loader/Makefile*
1617
acinclude.m4
1718
aclocal.m4
1819
autom4te*
1920
build
2021
configure
2122
coverage/
2223
/configure.*
24+
/loader/configure.*
2325
/config.*
26+
/loader/config.*
2427
!config.m4
2528
!config.w32
2629
ddtrace.def
@@ -29,6 +32,8 @@ ext/version.h
2932
*.lo
3033
*.o
3134
*.so
35+
*~
36+
*.dep
3237
install-sh
3338
*.log
3439
nginx.pid
@@ -49,6 +54,7 @@ tests/ext/*.log
4954
tests/ext/*.exp
5055
tests/ext/*.sh
5156
tests/ext/*.mem
57+
phpt.*
5258
tmp-php.ini
5359
tmp/opcache*
5460
*.orig

loader/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# DD Library Loader
2+
3+
## Getting Started
4+
5+
This Zend extension (**dd_library_loader**) is a universal loader for the **ddtrace** extension.
6+
7+
Once compiled (PHP >= 7.4), the same shared object can be loaded on any PHP versions from 7.0 to 8.3,
8+
whatever the PHP flavor (NTS/ZTS, debug or not).
9+
10+
When loaded, it will try to find the right **ddtrace.so** file on the filesystem and load it into PHP.

loader/bin/fake_forwarder.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# 1st argument is always "library_entrypoint", the 2nd is the json payload
5+
echo "${@:2}" >> ${FAKE_FORWARDER_LOG_PATH:="/tmp/fake_forwarder.log"}

loader/bin/test.sh

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
function _exit {
5+
if [[ $? -eq 0 ]]; then
6+
printf "\nSUCCESS\n"
7+
exit 0
8+
else
9+
printf "\nFAILURE\n"
10+
exit 1
11+
fi
12+
}
13+
trap _exit EXIT
14+
15+
if [[ ! -f run-tests.php ]]; then
16+
phpize
17+
fi
18+
19+
if [[ -z "${DD_LOADER_PACKAGE_PATH:-}" ]]; then
20+
DEFAULT="/home/circleci/app/dd-library-php"
21+
echo "Note: env var 'DD_LOADER_PACKAGE_PATH' is required but not defined, using the default value (${DEFAULT})"
22+
export DD_LOADER_PACKAGE_PATH="${DEFAULT}"
23+
fi
24+
25+
printf "PHP version\n\n"
26+
php -n -v
27+
28+
printf "Test load loader\n\n"
29+
DD_TRACE_DEBUG=1 php -n -d zend_extension=${PWD}/modules/dd_library_loader.so -v
30+
31+
printf "\nRunning PHPT tests\n"
32+
php -n run-tests.php -q -p $(which php) -n -d zend_extension=${PWD}/modules/dd_library_loader.so --show-diff
33+
34+
printf "\nRunning functional tests\n\n"
35+
failure=0
36+
for file in $(find tests/functional/ -name 'test_*.php'); do
37+
echo "${file}"
38+
php -n ${file} | sed 's/^/ /' || failure=1
39+
done
40+
41+
if [[ $failure -eq 1 ]]; then
42+
exit 1
43+
fi

0 commit comments

Comments
 (0)