diff --git a/.github/workflows/publish-autoinstrumentation-php.yaml b/.github/workflows/publish-autoinstrumentation-php.yaml new file mode 100644 index 0000000000..dfe3bbbb7d --- /dev/null +++ b/.github/workflows/publish-autoinstrumentation-php.yaml @@ -0,0 +1,78 @@ +name: "Publish PHP Auto-Instrumentation" + +on: + push: + paths: + - 'autoinstrumentation/php/**' + - '.github/workflows/publish-autoinstrumentation-php.yaml' + branches: + - main + pull_request: + paths: + - 'autoinstrumentation/php/**' + - '.github/workflows/publish-autoinstrumentation-php.yaml' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + publish: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + + - name: Read version + run: echo "VERSION=$(cat autoinstrumentation/php/version.txt)" >> $GITHUB_ENV + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + otel/autoinstrumentation-php + ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-php + tags: | + type=match,pattern=v(.*),group=1,value=v${{ env.VERSION }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Cache Docker layers + uses: actions/cache@v4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Log into Docker.io + uses: docker/login-action@v3 + if: ${{ github.event_name == 'push' }} + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Login to GitHub Package Registry + uses: docker/login-action@v3 + if: ${{ github.event_name == 'push' }} + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Prepare files for docker image + run: pushd ./autoinstrumentation/php ; ./prepare_files_for_docker_image.sh --ext-ver ${{ env.VERSION }} --dest-dir ${PWD}/files_for_docker_image ; popd + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: autoinstrumentation/php + push: ${{ github.event_name == 'push' }} + build-args: SUB_DIR_WITH_FILES_FOR_DOCKER_IMAGE=files_for_docker_image + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache diff --git a/autoinstrumentation/php/Dockerfile b/autoinstrumentation/php/Dockerfile new file mode 100644 index 0000000000..77f0d7c09b --- /dev/null +++ b/autoinstrumentation/php/Dockerfile @@ -0,0 +1,15 @@ +# To build one auto-instrumentation image for php, please: +# - Download your php auto-instrumentation artefacts to `/autoinstrumentation` directory. This is required as when instrumenting the pod, +# one init container will be created to copy the files to your app's container. +# - Grant the necessary access to the files in the `/autoinstrumentation` directory. +# - Following environment variables are injected to the application container to enable the auto-instrumentation. +# PHP_INI_SCAN_DIR=:/otel-auto-instrumentation-php/php_ini_scan_dir +# OTEL_PHP_AUTOLOAD_ENABLED=true +# - For auto-instrumentation by container injection, the Linux command cp is +# used and must be availabe in the image. + +FROM busybox + +ARG SUB_DIR_WITH_FILES_FOR_DOCKER_IMAGE + +COPY ${SUB_DIR_WITH_FILES_FOR_DOCKER_IMAGE} /autoinstrumentation/ diff --git a/autoinstrumentation/php/composer_PHP_8.1.json b/autoinstrumentation/php/composer_PHP_8.1.json new file mode 100644 index 0000000000..8ec4b22783 --- /dev/null +++ b/autoinstrumentation/php/composer_PHP_8.1.json @@ -0,0 +1,34 @@ +{ + "name": "open-telemetry/operator-autoinstrumentation-php", + "description": "OpenTelemetry PHP auto-instrumentation packages to include in the image used by OpenTelemetry Operator for Kubernetes", + "type": "project", + "require": { + "open-telemetry/exporter-otlp": "1.1.0", + "open-telemetry/opentelemetry-auto-guzzle": "1.0.1", + "open-telemetry/opentelemetry-auto-http-async": "1.0.1", + "open-telemetry/opentelemetry-auto-laravel": "1.0.1", + "open-telemetry/opentelemetry-auto-psr15": "1.0.6", + "open-telemetry/opentelemetry-auto-psr18": "1.0.4", + "open-telemetry/opentelemetry-auto-slim": "1.0.7", + "open-telemetry/opentelemetry-auto-symfony": "1.0.0beta30", + "open-telemetry/opentelemetry-auto-wordpress": "0.0.16", + "open-telemetry/sdk": "1.1.2", + "php-http/guzzle7-adapter": "1.0.0" + }, + "provide": { + "psr/http-client": "*", + "psr/http-server-middleware": "*", + "laravel/framework": "*", + "slim/slim": "*", + "symfony/http-client-contracts": "*", + "symfony/http-kernel": "*" + }, + "config": { + "process-timeout": 0, + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "php-http/discovery": true + } + } +} diff --git a/autoinstrumentation/php/composer_PHP_8.2.json b/autoinstrumentation/php/composer_PHP_8.2.json new file mode 100644 index 0000000000..be90f9f430 --- /dev/null +++ b/autoinstrumentation/php/composer_PHP_8.2.json @@ -0,0 +1,35 @@ +{ + "name": "open-telemetry/operator-autoinstrumentation-php", + "description": "OpenTelemetry PHP auto-instrumentation packages to include in the image used by OpenTelemetry Operator for Kubernetes", + "type": "project", + "require": { + "open-telemetry/exporter-otlp": "1.1.0", + "open-telemetry/opentelemetry-auto-guzzle": "1.0.1", + "open-telemetry/opentelemetry-auto-http-async": "1.0.1", + "open-telemetry/opentelemetry-auto-laravel": "1.0.1", + "open-telemetry/opentelemetry-auto-pdo": "0.0.16", + "open-telemetry/opentelemetry-auto-psr15": "1.0.6", + "open-telemetry/opentelemetry-auto-psr18": "1.0.4", + "open-telemetry/opentelemetry-auto-slim": "1.0.7", + "open-telemetry/opentelemetry-auto-symfony": "1.0.0beta30", + "open-telemetry/opentelemetry-auto-wordpress": "0.0.16", + "open-telemetry/sdk": "1.1.2", + "php-http/guzzle7-adapter": "1.0.0" + }, + "provide": { + "psr/http-client": "*", + "psr/http-server-middleware": "*", + "laravel/framework": "*", + "slim/slim": "*", + "symfony/http-client-contracts": "*", + "symfony/http-kernel": "*" + }, + "config": { + "process-timeout": 0, + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "php-http/discovery": true + } + } +} diff --git a/autoinstrumentation/php/prepare_files_for_docker_image.sh b/autoinstrumentation/php/prepare_files_for_docker_image.sh new file mode 100755 index 0000000000..941adbdbda --- /dev/null +++ b/autoinstrumentation/php/prepare_files_for_docker_image.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash +set -xe -o pipefail + +PHP_versions=(8.1 8.2 8.3) +libc_variants=(glibc musl) + +show_help() { + echo "Usage: $0 --ext-ver --dest-dir " + echo + echo "Arguments:" + echo " - opentelemetry PHP extension version to use. This argument is mandatory." + echo " - Directory to store files for docker image. All existing files in this directory will be deleted. This argument is mandatory." + echo + echo "Example:" + echo " $0 ./files_for_docker_image" +} + +parse_args() { + while [[ "$#" -gt 0 ]]; do + case $1 in + --ext-ver) + opentelemetry_extension_version="$2" + shift + ;; + --dest-dir) + destination_directory="$2" + shift + ;; + --help) + show_help + exit 0 + ;; + *) + echo "Unknown parameter passed: $1" + show_help + exit 1 + ;; + esac + shift + done + + if [ -z "${opentelemetry_extension_version}" ] ; then + echo " argument is missing" + show_help + exit 1 + fi + if [ -z "${destination_directory}" ] ; then + echo " argument is missing" + show_help + exit 1 + fi +} + +ensure_dir_exists_and_empty() { + local dir_to_clean="${1:?}" + + if [ -d "${dir_to_clean}" ]; then + rm -rf "${dir_to_clean}" + if [ -d "${dir_to_clean}" ]; then + echo "Directory ${dir_to_clean} still exists. Directory content:" + ls -l "${dir_to_clean}" + exit 1 + fi + else + mkdir -p "${dir_to_clean}" + fi +} + +build_native_binaries_for_PHP_version_libc_variant() { + local PHP_version="${1:?}" + local libc_variant="${2:?}" + local dest_dir_for_current_args + dest_dir_for_current_args="${destination_directory}/native_binaries/PHP_${PHP_version}_${libc_variant}" + + echo "Building extension binaries for PHP version: ${PHP_version} and libc variant: ${libc_variant} to ${dest_dir_for_current_args} ..." + + ensure_dir_exists_and_empty "${dest_dir_for_current_args}" + + local PHP_docker_image="php:${PHP_version}-cli" + local install_compiler_command="" + case "${libc_variant}" in + glibc) + ;; + musl) + PHP_docker_image="${PHP_docker_image}-alpine" + install_compiler_command="&& apk update && apk add autoconf build-base" + ;; + *) + echo "Unexpected libc variant: ${libc_variant}" + exit 1 + ;; + esac + + local current_user_id + current_user_id="$(id -u)" + local current_user_group_id + current_user_group_id="$(id -g)" + docker run --rm \ + -v "${dest_dir_for_current_args}:/dest_dir" \ + ${PHP_docker_image} sh -c "\ + mkdir -p /app && cd /app \ + ${install_compiler_command} \ + && pecl install opentelemetry-${opentelemetry_extension_version} \ + && cp /usr/local/lib/php/extensions/no-debug-non-zts-*/opentelemetry.so /dest_dir/ \ + && chown -R ${current_user_id}:${current_user_group_id} /dest_dir/" + + echo "Built extension binaries for PHP version: ${PHP_version} and libc variant: ${libc_variant}" +} + +build_native_binaries() { + echo "Building extension binaries..." + + for PHP_version in "${PHP_versions[@]}" ; do + for libc_variant in "${libc_variants[@]}" ; do + build_native_binaries_for_PHP_version_libc_variant "${PHP_version}" "${libc_variant}" + done + done + + echo "Built extension binaries" +} + +select_composer_json_for_PHP_version() { + local PHP_version="${1:?}" + case "${PHP_version}" in + 8.0|8.1|8.2) + echo "composer_PHP_${PHP_version}.json" + ;; + 8.3) + echo "composer_PHP_8.2.json" + ;; + *) + echo "Unexpected PHP version: ${PHP_version}" + exit 1 + ;; + esac +} + +download_PHP_packages_for_PHP_version() { + local PHP_version="${1:?}" + local dest_dir_for_current_args + dest_dir_for_current_args="${destination_directory}/PHP_packages/PHP_${PHP_version}" + + echo "Downloading PHP packages for PHP version: ${PHP_version} to ${dest_dir_for_current_args} ..." + + ensure_dir_exists_and_empty "${dest_dir_for_current_args}" + local composer_json_file_name + composer_json_file_name=$(select_composer_json_for_PHP_version "${PHP_version}") + local current_user_id + current_user_id="$(id -u)" + local current_user_group_id + current_user_group_id="$(id -g)" + docker run --rm \ + -v "${dest_dir_for_current_args}:/app/vendor" \ + -v "${PWD}/${composer_json_file_name}:/app/composer.json" \ + -w /app \ + php:${PHP_version}-cli sh -c "\ + apt-get update && apt-get install -y unzip \ + && curl -sS https://getcomposer.org/installer | php -- --filename=composer --install-dir=/usr/local/bin \ + && composer --ignore-platform-req=ext-opentelemetry --no-dev install \ + && chown -R ${current_user_id}:${current_user_group_id} ./vendor/" + + echo "Downloaded PHP packages for PHP version: ${PHP_version} to ${dest_dir_for_current_args}" +} + +download_PHP_packages() { + echo "Downloading PHP packages..." + + for PHP_version in "${PHP_versions[@]}" ; do + download_PHP_packages_for_PHP_version "${PHP_version}" + done + + echo "Downloaded PHP packages" +} + +main() { + parse_args "$@" + + echo "Preparing files for docker image into directory ${destination_directory} ..." + + ensure_dir_exists_and_empty "${destination_directory}" + build_native_binaries + download_PHP_packages + + echo "Prepared files for docker image into directory ${destination_directory}" +} + +main "$@" diff --git a/autoinstrumentation/php/version.txt b/autoinstrumentation/php/version.txt new file mode 100644 index 0000000000..9084fa2f71 --- /dev/null +++ b/autoinstrumentation/php/version.txt @@ -0,0 +1 @@ +1.1.0 diff --git a/versions.txt b/versions.txt index 0820a83d2a..04e3c630c6 100644 --- a/versions.txt +++ b/versions.txt @@ -32,6 +32,10 @@ autoinstrumentation-dotnet=1.2.0 # Represents the current release of Go instrumentation. autoinstrumentation-go=v0.17.0-alpha +# Represents the current release of PHP instrumentation. +# Should match autoinstrumentation/php/version.txt +autoinstrumentation-PHP=1.1.0 + # Represents the current release of Apache HTTPD instrumentation. # Should match autoinstrumentation/apache-httpd/version.txt autoinstrumentation-apache-httpd=1.0.4