Skip to content

Commit

Permalink
[chore] Build docker image for PHP auto-intrumentation (#3409)
Browse files Browse the repository at this point in the history
* Build docker image for PHP autointrumentation

* Fixed parts were commented out during debugging

* Fixed path to relative since it's used in Dockerfile

* Marked autoinstrumentation/php/prepare_files_for_docker_image.sh as executable

* Fixed error message in autoinstrumentation/php/prepare_files_for_docker_image.sh

* Build docker image for PHP autointrumentation

* Fixed parts were commented out during debugging

* Fixed path to relative since it's used in Dockerfile

* Marked autoinstrumentation/php/prepare_files_for_docker_image.sh as executable

* Fixed error message in autoinstrumentation/php/prepare_files_for_docker_image.sh

* Added missing autoinstrumentation/php/version.txt

* Removed support for PHP 8.0

Since PHP 8.0 support was removed from OpenTelemetry for PHP SDK (from version 1.1)

* Updated versions of instrumentation packages to the latest

* Fixed publish-autoinstrumentation-php.yaml Prepare files for docker image

* Deleted composer_PHP_8.0.json that was used only for PHP 8.0

* Added PHP to /versions.txt

* Renamed composer*.json files to "before_8.2" and "8.2_and_later"
  • Loading branch information
SergeyKleyman authored Jan 30, 2025
1 parent 2c5d057 commit 99b8d3c
Show file tree
Hide file tree
Showing 7 changed files with 384 additions and 0 deletions.
78 changes: 78 additions & 0 deletions .github/workflows/publish-autoinstrumentation-php.yaml
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions autoinstrumentation/php/Dockerfile
Original file line number Diff line number Diff line change
@@ -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/
35 changes: 35 additions & 0 deletions autoinstrumentation/php/composer_for_PHP_8.2_and_later.json
Original file line number Diff line number Diff line change
@@ -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
}
}
}
34 changes: 34 additions & 0 deletions autoinstrumentation/php/composer_for_PHP_before_8.2.json
Original file line number Diff line number Diff line change
@@ -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
}
}
}
217 changes: 217 additions & 0 deletions autoinstrumentation/php/prepare_files_for_docker_image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#!/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 <opentelemetry extension version> --dest-dir <destination directory>"
echo
echo "Arguments:"
echo " <opentelemetry extension version> - opentelemetry PHP extension version to use. This argument is mandatory."
echo " <destination directory> - 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 "<opentelemetry extension version> argument is missing"
show_help
exit 1
fi
if [ -z "${destination_directory}" ] ; then
echo "<destination directory> 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"
}

is_earlier_major_minor_version() {
local lhs_version="${1:?}"
local rhs_version="${2:?}"
local lhs_version_major
lhs_version_major=$(echo "${lhs_version}" | cut -d. -f1)
local rhs_version_major
rhs_version_major=$(echo "${rhs_version}" | cut -d. -f1)

if [ "${lhs_version_major}" -lt "${rhs_version_major}" ]; then
echo "true"
return
fi

if [ "${lhs_version_major}" -gt "${rhs_version_major}" ]; then
echo "false"
return
fi

local lhs_version_minor
lhs_version_minor=$(echo "${lhs_version}" | cut -d. -f2)
local rhs_version_minor
rhs_version_minor=$(echo "${rhs_version}" | cut -d. -f2)

if [ "${lhs_version_minor}" -lt "${rhs_version_minor}" ]; then
echo "true"
return
fi

echo "false"
}

select_composer_json_for_PHP_version() {
local PHP_version="${1:?}"
#
# Supported instrumentations are different for PHP prior to 8.2 and for PHP 8.2 and later
# because PHP 8.2 added ability to instrument internal functions
#
local is_PHP_version_before_8_2
is_PHP_version_before_8_2=$(is_earlier_major_minor_version "${PHP_version}" "8.2")
if [ "${is_PHP_version_before_8_2}" == "true" ]; then
echo "composer_for_PHP_before_8.2.json"
else
echo "composer_for_PHP_8.2_and_later.json"
fi
}

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 "$@"
1 change: 1 addition & 0 deletions autoinstrumentation/php/version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.1.0
4 changes: 4 additions & 0 deletions versions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ autoinstrumentation-dotnet=1.2.0
# Represents the current release of Go instrumentation.
autoinstrumentation-go=v0.19.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
Expand Down

0 comments on commit 99b8d3c

Please sign in to comment.