Spitfirev0.71.0 · What's new

Version: 0.71.0This documentation is for Spitfire 0.71.0.

Connecting a PHP service with OTel

The OpenTelemetry PHP extension (opentelemetry) and SDK, with the libraries' automatic instrumentation packages, collect traces and logs without touching the code. PHP records no metrics by itself: the service shows under Towers & metrics → Sources once the application records its own metrics (Metrics API); for the server's metrics use the Collector. Values and general rules: Connecting services with OTel: overview.

Version table

PHP PECL opentelemetry open-telemetry/sdk open-telemetry/exporter-otlp
8.1 and later 1.4.2 1.15.0 1.4.0
8.0 and earlier not supported – Upgrade to PHP 8.1+ or take server metrics only: Collector

Find your version: php --version (for PHP-FPM php-fpm<php-version> --version).

PHP 8.0: the last packages for it need google/protobuf versions with security advisories, and Composer refuses to install them. Upgrade to PHP 8.1+.

Verified: 2026-11-02. Source: PHP zero-code documentation (PHP 8.0+), PECL opentelemetry (lowest PHP per release), Packagist open-telemetry/sdk, Packagist open-telemetry/exporter-otlp.

What you need

  • Spitfire address https://<spitfire> and OTLP receiver token sfotlp_…
  • Tower address http://<tower>:4318 and Collector token sfcol_…
  • Protocol http/protobuf
  • Service name <service-name>, version <service-version>, environment <environment>
  • With a private CA, the CA file /etc/spitfire-otel/ca.pem
  • With a proxy, the Tower and Spitfire in NO_PROXY
  • Sampling parentbased_traceidratio, 0.1
  • Composer in the application (vendor/autoload.php)

Linux (PHP-FPM, systemd)

  1. Build and install the extension (Debian/Ubuntu; on RHEL the php-pecl-opentelemetry package from the Remi repository also works):
bash
sudo apt-get install -y gcc make autoconf php-dev php-pear
sudo pecl install opentelemetry-1.4.2
  1. Turn the extension on: create the file /etc/php/<php-version>/mods-available/opentelemetry.ini, paste this, then run sudo phpenmod opentelemetry:
ini
[opentelemetry]
extension=opentelemetry.so
  1. See that it is on: php --ri opentelemetry (opentelemetry support => enabled).
  2. In the application's folder, install the SDK, the exporter and your framework's instrumentation package (write your framework's in place of opentelemetry-auto-laravel: -auto-symfony, -auto-slim; full list on Packagist):
bash
composer config allow-plugins.php-http/discovery true
composer require open-telemetry/sdk:1.15.0 open-telemetry/exporter-otlp:1.4.0 php-http/guzzle7-adapter \
  open-telemetry/opentelemetry-auto-laravel open-telemetry/opentelemetry-auto-psr3
sudo mkdir -p /opt/spitfire-otel /etc/spitfire-otel
  1. Create the file /etc/spitfire-otel/<service-name>.env and paste this:
bash
IS_OTEL_ENABLED=true
OTEL_SERVICE_NAME=<service-name>
OTEL_RESOURCE_ATTRIBUTES=service.version=<service-version>,deployment.environment=<environment>
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://<spitfire>/otlp/v1/traces
OTEL_EXPORTER_OTLP_TRACES_HEADERS=authorization=sfotlp_…
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<spitfire>/otlp/v1/logs
OTEL_EXPORTER_OTLP_LOGS_HEADERS=authorization=sfotlp_…
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://<tower>:4318/v1/metrics
OTEL_EXPORTER_OTLP_METRICS_HEADERS=authorization=sfcol_…
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=0.1
NO_PROXY=<tower>,<spitfire>
#OTEL_EXPORTER_OTLP_CERTIFICATE=/etc/spitfire-otel/ca.pem
  1. Restrict its permission: sudo chmod 600 /etc/spitfire-otel/<service-name>.env
  2. Create the file /opt/spitfire-otel/otel-run and paste this:
bash
#!/bin/sh
# IS_OTEL_ENABLED=true: OTel loads automatically; any other value: not loaded, SDK off.
if [ "$IS_OTEL_ENABLED" = "true" ]; then
  export OTEL_PHP_AUTOLOAD_ENABLED=true
else
  export OTEL_PHP_AUTOLOAD_ENABLED=false
  export OTEL_SDK_DISABLED=true
fi
exec "$@"
  1. Make it executable: sudo chmod 755 /opt/spitfire-otel/otel-run
  2. So that PHP-FPM passes environment variables to its workers, uncomment or add this line in the pool file (/etc/php/<php-version>/fpm/pool.d/www.conf):
ini
clear_env = no
  1. Find the FPM service's current start command: systemctl cat php<php-version>-fpm | grep ^ExecStart
  2. Open sudo systemctl edit php<php-version>-fpm and paste this (on the last line, replace the command after ExecStart= with the command from step 10):
ini
[Service]
EnvironmentFile=/etc/spitfire-otel/<service-name>.env
ExecStart=
ExecStart=/opt/spitfire-otel/otel-run /usr/sbin/php-fpm8.3 --nodaemonize --fpm-config /etc/php/8.3/fpm/php-fpm.conf
  1. Restart: sudo systemctl daemon-reload && sudo systemctl restart php<php-version>-fpm
Note

For PHP run from the command line (queue worker, cron), apply the same drop-in to that service's <unit>: ExecStart=/opt/spitfire-otel/otel-run /usr/bin/php /srv/app/artisan queue:work.

Docker

  1. Put the otel-run file (Linux step 7) next to the Dockerfile.
  2. In the official php image, add this to the Dockerfile (the Composer step as in Linux step 4); /opt/spitfire-otel/otel-run goes at the start of ENTRYPOINT, the rest is your command:
dockerfile
RUN pecl install opentelemetry-1.4.2 && docker-php-ext-enable opentelemetry
RUN echo "clear_env = no" >> /usr/local/etc/php-fpm.d/www.conf
COPY --chmod=755 otel-run /opt/spitfire-otel/otel-run
ENTRYPOINT ["/opt/spitfire-otel/otel-run", "php-fpm"]
  1. Save the environment file (Linux step 5) on the Docker machine as /etc/spitfire-otel/<service-name>.env.
  2. Run: docker run --env-file /etc/spitfire-otel/<service-name>.env … or, in compose, under the service env_file: /etc/spitfire-otel/<service-name>.env.
  3. When the environment file changes, recreate the container (restart is not enough): docker compose up -d --force-recreate <service>

Kubernetes

  1. Prepare the image as in the Docker section.
  2. Save the environment file (Linux step 5) as <service-name>.env and make it a Secret:
bash
kubectl create secret generic <service-name>-otel --from-env-file=<service-name>.env \
  --dry-run=client -o yaml | kubectl apply -f -
  1. In the Deployment, add this under the container:
yaml
envFrom:
  - secretRef:
      name: <service-name>-otel
  1. Restart: kubectl rollout restart deployment/<deployment>

Windows (IIS)

  1. Find your PHP's version and build: php -i | findstr /C:"PHP Version" /C:"Thread Safety" /C:"Architecture" (IIS runs the NTS build, Thread Safety => disabled).
  2. From the PECL Windows page download the zip for your PHP version, nts and x64 (e.g. https://downloads.php.net/~windows/pecl/releases/opentelemetry/1.4.2/php_opentelemetry-1.4.2-8.3-nts-vs16-x64.zip) and put the php_opentelemetry.dll inside it in PHP's ext folder (e.g. C:\php\ext).
  3. Add this line at the end of php.ini (php --ini shows which file):
ini
extension=opentelemetry
  1. See that it is on: php --ri opentelemetry (opentelemetry support => enabled).
  2. In the application's folder, run the two composer commands of Linux step 4 (the sudo mkdir line is not needed on Windows).
  3. In an administrator PowerShell, write the php-cgi.exe the site uses (IIS Manager → FastCGI Settings → Full Path) in place of C:\php\php-cgi.exe and run (IIS restarts):
powershell
Import-Module WebAdministration
$PhpCgi = "C:\php\php-cgi.exe"
$IS_OTEL_ENABLED = "true"
$Vars = [ordered]@{
  IS_OTEL_ENABLED = $IS_OTEL_ENABLED
  OTEL_SERVICE_NAME = "<service-name>"
  OTEL_RESOURCE_ATTRIBUTES = "service.version=<service-version>,deployment.environment=<environment>"
  OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
  OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = "https://<spitfire>/otlp/v1/traces"
  OTEL_EXPORTER_OTLP_TRACES_HEADERS = "authorization=sfotlp_…"
  OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = "https://<spitfire>/otlp/v1/logs"
  OTEL_EXPORTER_OTLP_LOGS_HEADERS = "authorization=sfotlp_…"
  OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = "http://<tower>:4318/v1/metrics"
  OTEL_EXPORTER_OTLP_METRICS_HEADERS = "authorization=sfcol_…"
  OTEL_TRACES_EXPORTER = "otlp"
  OTEL_METRICS_EXPORTER = "otlp"
  OTEL_LOGS_EXPORTER = "otlp"
  OTEL_TRACES_SAMPLER = "parentbased_traceidratio"
  OTEL_TRACES_SAMPLER_ARG = "0.1"
  NO_PROXY = "<tower>,<spitfire>"
}
# Private CA: $Vars.OTEL_EXPORTER_OTLP_CERTIFICATE = "C:\spitfire-otel\ca.pem"
if ($IS_OTEL_ENABLED -eq "true") {
  $Vars.OTEL_PHP_AUTOLOAD_ENABLED = "true"
} else {
  $Vars.OTEL_PHP_AUTOLOAD_ENABLED = "false"
  $Vars.OTEL_SDK_DISABLED = "true"
}
$Filter = "system.webServer/fastCgi/application[@fullPath='$PhpCgi']/environmentVariables"
foreach ($Name in @($Vars.Keys) + @("OTEL_SDK_DISABLED")) {
  Remove-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter $Filter -Name "." -AtElement @{ name = $Name } -ErrorAction SilentlyContinue
}
foreach ($Name in $Vars.Keys) {
  Add-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter $Filter -Name "." -Value @{ name = $Name; value = $Vars[$Name] }
}
iisreset /restart
  1. Open a few pages of the site and follow the Verifying steps.
Note

IIS passes these variables to php-cgi.exe when it starts it (IIS documentation).

Turning off and removing

  1. Turning off: set IS_OTEL_ENABLED=false in the environment file (in the script on Windows) and restart the service (Linux step 12, Docker step 5, Kubernetes step 4, or run the Windows script again).
  2. Removing: sudo systemctl revert php<php-version>-fpm, sudo phpdismod opentelemetry, sudo rm -r /opt/spitfire-otel /etc/spitfire-otel, and remove the open-telemetry/ packages with composer remove; in Docker, delete the lines added to the Dockerfile; on Windows, delete the extension=opentelemetry line from php.ini and the OTel variables in IIS Manager → FastCGI Settings → Environment Variables.

Common problems

Symptom Cause Fix
php --ri opentelemetry says "not present" The extension is not on or was installed for another PHP Repeat the phpenmod step; for FPM check with php-fpm<php-version> -m
The extension is on but there are no traces clear_env = no is missing or the framework's instrumentation package is not installed Check steps 9 and 4
pecl install fails on the PHP version The PHP version is outside the band Upgrade to PHP 8.1+
Composer version conflict The package versions do not fit your PHP Check PHP 8.1+ with php --version; write no version for the framework package
No traces or metrics arrive Address, token or network Follow the Verifying steps