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_SERVICE
so 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.3
Enable the extension by adding to your
php.ini
:1[opentelemetry] 2extension=opentelemetry.so
The
php.ini
file can be found using the following commands based on your Linux distribution:Ubuntu/Debian:
1sudo nano /etc/php/<php_version>/cli/php.ini
CentOS/RHEL:
1sudo nano /etc/php.ini
Arch Linux:
1sudo nano /etc/php/php.ini
Web-Serve:
1sudo nano /etc/php/<php_version>/apache2/php.ini
Finally, verify the installation:
1php -m | grep opentelemetry
Install Middleware’s PHP package
1composer update
2composer require middleware/agent-apm-php
Then, 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.local
Start/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.php
You can also download the script by clicking here.
Run (root/admin):
1sudo -E MW_SERVICE_NAME=<your-service-name> php wp-instrument.php
Here:
MW_SERVICE_NAME
optional; 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:9320
For 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.so
The 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/ini
Your 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-dev
Broken 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 install
ERROR: ‘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.net
Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.