PHP

TracesMetricsApp LogsCustom LogsProfiling

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
  • 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

Docker
Kubernetes
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 is service-<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:

Middleware PHP APM Docker and Kubernetes config

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:

Example PHP APM build pipeline output

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

VariableScopePurposeExample
MW_AGENT_SERVICEDocker/K8sAddress/DNS of Host Agent172.17.0.1 (Docker), mw-service.mw-agent-ns.svc.cluster.local (K8s)
MW_API_KEYWP/Laravel scriptsOTLP endpoint override (bridge gateway in Docker)172.17.0.1:9320 (implicitly used by scripts)
OTEL_PHP_AUTOLOAD_ENABLEDPHPEnables OTel PHP auto-loadertrue
OTEL_SERVICE_NAME / MW_SERVICE_NAMEPHP/LaravelService name shown in APMorders-api
OTEL_EXPORTER_OTLP_ENDPOINT / MW_TARGETPHP/LaravelWhere to send OTLP datahttp://localhost:9320 (Host Agent)
OTEL_PROPAGATORSPHP/LaravelPropagation for cross-service tracingbaggage,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:

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:

ERROR: ‘phpize’ failed error

If you receive an ERROR: ‘phpize’ failed error, run the following commands:

Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.