PHP
| Traces | Metrics | App Logs | Custom Logs | Profiling |
|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✖ | ✖ |
This guide walks you through setting up Application Performance Monitoring (APM) on a PHP application. These instructions can also be found on the Installation page in your Middleware Account. View example code here.
- CakePHP isn’t supported today.
- Current support targets Debian-based Linux distributions.
1. Prerequisites
- Middleware Host Agent (see installation guide here) running on the same machine (for host-based installs). In containers, pass
MW_AGENT_SERVICEso your app can reach the agent:- Docker:
MW_AGENT_SERVICE=172.17.0.1 - Kubernetes:
MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local
- Docker:
- PHP: PHP version 8.0 or above. Verify with php -v.
- Composer: Ensure you have the Composer dependency manager installed to install our APM.
- PECL: PECL is required to install the appropriate extension.
2. Vanilla PHP
Install OpenTelemetry auto-instrumentation
Install the extension:
1sudo pecl install channel://pecl.php.net/opentelemetry-1.0.3Enable the extension by adding to your
php.ini:1[opentelemetry] 2extension=opentelemetry.soThe
php.inifile can be found using the following commands based on your Linux distribution:Ubuntu/Debian:
1sudo nano /etc/php/<php_version>/cli/php.iniCentOS/RHEL:
1sudo nano /etc/php.iniArch Linux:
1sudo nano /etc/php/php.iniWeb-Serve:
1sudo nano /etc/php/<php_version>/apache2/php.iniFinally, verify the installation:
1php -m | grep opentelemetryInstall Middleware’s PHP package
1composer update
2composer require middleware/agent-apm-phpThen, add the following at the top of your entry script:
1require 'vendor/autoload.php';
2use Middleware\AgentApmPhp\MwTracker;(Containers) Connectivity to the Host Agent
1MW_AGENT_SERVICE=<DOCKER_BRIDGE_GATEWAY_ADDRESS>The DOCKER_BRIDGE_GATEWAY_ADDRESS is the IP address of the gateway between the Docker host and the bridge network. This is 172.17.0.1 by default. Learn more about Docker bridge networking here.
1MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.localStart/stop the tracing scope + hooks
Start a tracing scope right before your main application code:
1Create your tracker before your application code runs, register hooks, and close the scope:
2$tracker = new MwTracker('<PROJECT-NAME>', '<SERVICE-NAME>');
3$tracker->preTrack();
4
5$tracker->registerHook('<CLASS-NAME-1>', '<FUNCTION-NAME-1>', [
6 'custom.attr1' => 'value1',
7 'custom.attr2' => 'value2',
8]);
9$tracker->registerHook('<CLASS-NAME-2>', '<FUNCTION-NAME-2>');
10
11$tracker->postTrack();Custom logs (optional)
To ingest custom logs, use the following functions based on desired log severity levels:
1$tracker->info("Info Sample");
2$tracker->warn("Warn Sample");
3$tracker->debug("Debug Sample");
4$tracker->error("Error Sample");3. WordPress (zero-touch script)
Get the script (from your WP install dir, e.g., /var/www/localhost/htdocs):
1curl -O https://install.middleware.io/apm/php/wp-instrument.phpYou can also download the script by clicking here.
Run (root/admin):
1sudo -E MW_SERVICE_NAME=<your-service-name> php wp-instrument.phpHere:
MW_SERVICE_NAMEoptional; default isservice-<process id>.- Docker: you can pass the bridge gateway via
MW_TARGET:1sudo -E MW_TARGET=<DOCKER_BRIDGE_GATEWAY_ADDRESS> php wp-instrument.php
4. Laravel
One-command installer
From your Laravel project root:
1curl -O https://install.middleware.io/apm/php/laravel-instrument.php \
2 && sudo php laravel-instrument.php install(Downloads prerequisites, installs, and configures the PHP agent.)
You can also download the script manually by clicking here.
Tracing
Automatically enabled by the script.
Metrics (limited support)
Enable trace-related metrics by adding:
- Service provider in
config/app.php:1'providers' => [ 2 // ... 3 Middleware\LaravelApm\LaravelApmServiceProvider::class, 4], - Middleware in
app/Http/Kernel.php(after tracing middleware if used):1protected $middleware = [ 2 // ... 3 \Middleware\LaravelApm\Middleware\MetricsMiddleware::class, 4 ];
Logging
The package integrates with Laravel’s logging; configure your preferred driver, and it will forward to the Middleware automatically.
Environment
Set the following variables in your environment and restart your app to instrument your app:
1OTEL_PHP_AUTOLOAD_ENABLED=true
2OTEL_SERVICE_NAME=your-service-name
3OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:9320For frontend↔backend correlation:
1OTEL_PROPAGATORS=baggage,tracecontext,b3multi(9320 is the local agent’s OTLP endpoint; same values are used in Forge/Beanstalk guides.)
Alternate package route: middleware/laravel-apm documents equivalent env keys (MW_SERVICE_NAME, MW_TARGET / OTEL_EXPORTER_OTLP_ENDPOINT, protocol) with defaults (e.g., http://localhost:9320).
5. Azure Pipelines
The Azure Pipelines continuous integration and continuous delivery (CI/CD) infrastructure helps you build, deploy, and test your PHP projects. For information on setting up your PHP project with Azure Pipelines and Azure DevOps Services, learn more here.
1 Configure OpenTelemetry Extension
Add the following code to your .ini file located in the /home/html/ini directory of your Azure account:
1extension=opentelemetry.soThe dotnet-plugin release notes confirm .NET 6+ compatibility and the Middleware.Logger.Logger API for custom logs.
2 Add Configuration to Azure
Navigate to Application Settings in your Azure PHP project account and select New application setting. Add the following Name and Value to the New application setting:
1Name: PHP_INI_SCAN_DIR
2Value: /home/html/iniYour configuration should look like the following:

3 Create Your Build Pipelines
Update your build pipeline by adding the following code to the azure-pipelines.yml file:
The below build pipeline includes installation steps for Opentelemetry and the middleware/agent-apm-php
1trigger:
2- master
3
4variables:
5 # Azure Resource Manager connection created during pipeline creation
6 azureSubscription: 'XXXXXXXXXXXXXXXXXXXX'
7
8 # Web app name
9 webAppName: 'php-apm-test'
10
11 # Agent VM image name
12 vmImageName: 'ubuntu-latest'
13
14 # Environment name
15 environmentName: 'php-apm-test'
16
17 # Root folder under which your composer.json file is available.
18 rootFolder: $(System.DefaultWorkingDirectory)
19
20stages:
21- stage: Build
22 displayName: Build stage
23 variables:
24 phpVersion: '8.2'
25 jobs:
26 - job: BuildJob
27 pool:
28 name: Default
29 vmImage: $(vmImageName)
30 steps:
31 - script: |
32 sudo update-alternatives --set php /usr/bin/php$(phpVersion)
33 sudo update-alternatives --set phar /usr/bin/phar$(phpVersion)
34 sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(phpVersion)
35 sudo update-alternatives --set php-cgi /usr/bin/php-cgi$(phpVersion)
36 sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(phpVersion)
37 php -version
38 workingDirectory: $(rootFolder)
39 displayName: 'Use PHP version $(phpVersion)'
40
41 - script: composer install --no-interaction --prefer-dist --ignore-platform-reqs
42 workingDirectory: $(rootFolder)
43 displayName: 'composer install'
44
45 - script: |
46 # Check if the Opentelemetry package is already installed
47 if [ "$(pecl list | grep opentelemetry)" ]; then
48 echo "Opentelemetry package is already installed. Skipping this installation."
49 else
50 sudo pecl install channel://pecl.php.net/opentelemetry-1.0.0beta3
51 fi
52 workingDirectory: $(rootFolder)
53 displayName: 'Install Opentelemetry Extension'
54
55 - script: |
56 # Check if the Opentelemetry package is enabled
57 if php -m | grep opentelemetry; then
58 echo "Opentelemetry extension is enabled."
59 else
60 echo "Opentelemetry extension is not enabled. Please add it to your php.ini file: extension=opentelemetry.so"
61 exit 1
62 fi
63 workingDirectory: $(rootFolder)
64 displayName: 'Verify Opentelemetry Extension'
65
66 - script: composer update
67 workingDirectory: $(rootFolder)
68 displayName: 'Update Composer'
69
70 - script: |
71 # Check if the Middleware PHP APM-Package is already listed in the composer
72 if composer show | grep middleware/agent-apm-php; then
73 echo "Middleware APM-Package is already listed in the composer file. Skipping this installation."
74 else
75 composer require middleware/agent-apm-php
76 fi
77 workingDirectory: $(rootFolder)
78 displayName: 'Install Middleware PHP APM-Package'
79
80 - task: ArchiveFiles@2
81 displayName: 'Archive files'
82 inputs:
83 rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
84 includeRootFolder: false
85 archiveType: zip
86 archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
87 replaceExistingArchive: true
88
89 - task: PublishBuildArtifacts@1
90 inputs:
91 PathtoPublish: '$(Build.ArtifactStagingDirectory)'
92 ArtifactName: 'drop'
93 publishLocation: 'Container'4 Check Your Pipeline
The PHP Agent is now set up to execute a CI/CD approach, following the build pipeline configuration, whenever new code is pushed to the production environment. Your output should look like the following:

6. View your data
After deployment, give it a couple of minutes and check:
- Traces (end-to-end spans, latency, errors)
- Logs (from the PHP tracker and, for Laravel, app logs)
- Continuous Profiling: not available for PHP yet (available for other APMs).
7. Environment variables
| Variable | Scope | Purpose | Example |
|---|---|---|---|
MW_AGENT_SERVICE | Docker/K8s | Address/DNS of Host Agent | 172.17.0.1 (Docker), mw-service.mw-agent-ns.svc.cluster.local (K8s) |
MW_API_KEY | WP/Laravel scripts | OTLP endpoint override (bridge gateway in Docker) | 172.17.0.1:9320 (implicitly used by scripts) |
OTEL_PHP_AUTOLOAD_ENABLED | PHP | Enables OTel PHP auto-loader | true |
OTEL_SERVICE_NAME / MW_SERVICE_NAME | PHP/Laravel | Service name shown in APM | orders-api |
OTEL_EXPORTER_OTLP_ENDPOINT / MW_TARGET | PHP/Laravel | Where to send OTLP data | http://localhost:9320 (Host Agent) |
OTEL_PROPAGATORS | PHP/Laravel | Propagation for cross-service tracing | baggage,tracecontext,b3multi |
8. Troubleshooting
Below we cover a few common errors and their solutions.
pecl: command not found error
If you receive a pecl: command not found error, run the following command:
Shell
1sudo apt-get update
2apt-get install php-pear php8.1-devBroken Dependency Issue
If you receive any broken dependency issues, including errors like libpcre2-dev : Depends: libpcre2-8-0 / libpcre2-16-0 / libpcre2-32-0, run the following command:
Shell
1sudo apt --fix-broken installERROR: ‘phpize’ failed error
If you receive an ERROR: ‘phpize’ failed error, run the following commands:
Shell
1sudo apt-get update
2sudo apt-get install php8.1-dev
3
4sudo apt-get update
5sudo pecl channel-update pecl.php.netNeed assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.