---
title: "PHP"
description: "Configure Middleware APM for PHP applications to gain insights into performance bottlenecks, errors, and system health."
section: "APM"
breadcrumb: "APM > PHP"
canonical: "https://docs.middleware.io/get-started/apm/php"
---
# 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](https://github.com/middleware-labs/demo-apm/tree/master/php).

> **Note:** - CakePHP isn’t supported today.
> - Current support targets Debian-based Linux distributions.

## 1. Prerequisites

- Middleware Host Agent (see [installation guide](/get-started/agent) 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](https://getcomposer.org/) manager installed to install our APM.
- PECL: [PECL](https://pecl.php.net/) is required to install the appropriate extension.

## 2. Vanilla PHP

### Install OpenTelemetry auto-instrumentation

- Install the extension:

  ```bash
    sudo pecl install channel://pecl.php.net/opentelemetry-1.0.3
  ```
- Enable the extension by adding to your `php.ini`:

  ```bash
    [opentelemetry]
  extension=opentelemetry.so
  ```

  The `php.ini` file can be found using the following commands based on your Linux distribution:
- Ubuntu/Debian:

  ```bash
    sudo nano /etc/php/<php_version>/cli/php.ini
  ```
- CentOS/RHEL:

  ```bash
    sudo nano /etc/php.ini
  ```
- Arch Linux:

  ```bash
    sudo nano /etc/php/php.ini
  ```
- Web-Serve:

  ```bash
    sudo nano /etc/php/<php_version>/apache2/php.ini
  ```
- Finally, verify the installation:

```bash
   php -m | grep opentelemetry
```

### Install Middleware’s PHP package

```bash
  composer update
composer require middleware/agent-apm-php
```

Then, add the following at the top of your entry script:

```bash
  require 'vendor/autoload.php';
use Middleware\AgentApmPhp\MwTracker;
```

### (Containers) Connectivity to the Host Agent

#### Docker

```bash
  MW_AGENT_SERVICE=<DOCKER_BRIDGE_GATEWAY_ADDRESS>
```

> **Note:** 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.

#### Kubernetes

```bash
  MW_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:

```php
  Create your tracker before your application code runs, register hooks, and close the scope:
$tracker = new MwTracker('<PROJECT-NAME>', '<SERVICE-NAME>');
$tracker->preTrack();

$tracker->registerHook('<CLASS-NAME-1>', '<FUNCTION-NAME-1>', [
  'custom.attr1' => 'value1',
  'custom.attr2' => 'value2',
]);
$tracker->registerHook('<CLASS-NAME-2>', '<FUNCTION-NAME-2>');

$tracker->postTrack();
```

### Custom logs (optional)

To ingest custom logs, use the following functions based on desired log severity levels:

```php
  $tracker->info("Info Sample");
$tracker->warn("Warn Sample");
$tracker->debug("Debug Sample");
$tracker->error("Error Sample");
```

## 3. WordPress (zero-touch script)

Get the script (from your WP install dir, e.g., `/var/www/localhost/htdocs`):

```bash
  curl -O https://install.middleware.io/apm/php/wp-instrument.php
```

You can also download the script by clicking [here](https://install.middleware.io/apm/php/wp-instrument.php).

Run (root/admin):

```bash
  sudo -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`:

  ```bash
    sudo -E MW_TARGET=<DOCKER_BRIDGE_GATEWAY_ADDRESS> php wp-instrument.php
  ```

## 4. Laravel

### One-command installer

From your Laravel project root:

```bash
  curl -O https://install.middleware.io/apm/php/laravel-instrument.php \
  && sudo php laravel-instrument.php install
```

(Downloads prerequisites, installs, and configures the PHP agent.)

You can also download the script manually by clicking [here](https://install.middleware.io/apm/php/laravel-instrument.php).

### Tracing

Automatically enabled by the script.

### Metrics (limited support)

Enable trace-related metrics by adding:

- Service provider in `config/app.php`:

  ```bash
    'providers' => [
    // ...
    Middleware\LaravelApm\LaravelApmServiceProvider::class,
  ],
  ```
- Middleware in `app/Http/Kernel.php` (after tracing middleware if used):

  ```bash
      protected $middleware = [
    // ...
    \Middleware\LaravelApm\Middleware\MetricsMiddleware::class,
    ];
  ```

### 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:

```php
  OTEL_PHP_AUTOLOAD_ENABLED=true
OTEL_SERVICE_NAME=your-service-name
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:9320
```

For frontend↔backend correlation:

```php
  OTEL_PROPAGATORS=baggage,tracecontext,b3multi
```

(9320 is the local agent’s OTLP endpoint; same values are used in Forge/Beanstalk guides.)

> **Note:** 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](https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/php?view=azure-devops).

#### 1 Configure OpenTelemetry Extension

Add the following code to your .ini file located in the /home/html/ini directory of your Azure account:

```bash
  extension=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:

```bash
  Name: PHP_INI_SCAN_DIR
Value: /home/html/ini
```

Your configuration should look like the following:

![Middleware PHP APM Docker and Kubernetes config](/images/v2/apm/php-apm-azure-config.png)

#### 3 Create Your Build Pipelines

Update your build pipeline by adding the following code to the azure-pipelines.yml file:

> **Note:** The below build pipeline includes installation steps for Opentelemetry and the middleware/agent-apm-php

```yml
  trigger:
- master

variables:
  # Azure Resource Manager connection created during pipeline creation
  azureSubscription: 'XXXXXXXXXXXXXXXXXXXX'

  # Web app name
  webAppName: 'php-apm-test'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

  # Environment name
  environmentName: 'php-apm-test'

  # Root folder under which your composer.json file is available.
  rootFolder: $(System.DefaultWorkingDirectory)

stages:
- stage: Build
  displayName: Build stage
  variables:
    phpVersion: '8.2'
  jobs:
  - job: BuildJob
    pool:
      name: Default
      vmImage: $(vmImageName)
    steps:
    - script: |
        sudo update-alternatives --set php /usr/bin/php$(phpVersion)
        sudo update-alternatives --set phar /usr/bin/phar$(phpVersion)
        sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(phpVersion)
        sudo update-alternatives --set php-cgi /usr/bin/php-cgi$(phpVersion)
        sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(phpVersion)
        php -version
      workingDirectory: $(rootFolder)
      displayName: 'Use PHP version $(phpVersion)'

    - script: composer install --no-interaction --prefer-dist --ignore-platform-reqs
      workingDirectory: $(rootFolder)
      displayName: 'composer install'

    - script: |
        # Check if the Opentelemetry package is already installed
        if [ "$(pecl list | grep opentelemetry)" ]; then
          echo "Opentelemetry package is already installed. Skipping this installation."
        else
          sudo pecl install channel://pecl.php.net/opentelemetry-1.0.0beta3
        fi
      workingDirectory: $(rootFolder)
      displayName: 'Install Opentelemetry Extension'

    - script: |
        # Check if the Opentelemetry package is enabled
        if php -m | grep opentelemetry; then
          echo "Opentelemetry extension is enabled."
        else
          echo "Opentelemetry extension is not enabled. Please add it to your php.ini file: extension=opentelemetry.so"
          exit 1
        fi
      workingDirectory: $(rootFolder)
      displayName: 'Verify Opentelemetry Extension'

    - script: composer update
      workingDirectory: $(rootFolder)
      displayName: 'Update Composer'

    - script: |
        # Check if the Middleware PHP APM-Package is already listed in the composer
        if composer show | grep middleware/agent-apm-php; then
          echo "Middleware APM-Package is already listed in the composer file. Skipping this installation."
        else
          composer require middleware/agent-apm-php
        fi
      workingDirectory: $(rootFolder)
      displayName: 'Install Middleware PHP APM-Package'

    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
        includeRootFolder: false
        archiveType: zip
        archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
        replaceExistingArchive: true

    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: '$(Build.ArtifactStagingDirectory)'
        ArtifactName: 'drop'
        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](/images/v2/apm/agent-apm-php.png)

## 6. Third Party APM support

If you need instrumentation for PHP versions older than 8.0, Middleware also supports Datadog PHP APM.

You can keep your existing instrumentation and send its traces to Middleware through the Middleware Host Agent. See [Datadog PHP APM](/get-started/agent/datadog#datadog-php-apm) for setup steps.

## 7. 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).

## 8. 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` |

## 9. 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:

```bash
sudo apt-get update
apt-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:

```bash
sudo apt --fix-broken install
```

#### ERROR: ‘phpize’ failed error

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

```bash
sudo apt-get update
sudo apt-get install php8.1-dev

sudo apt-get update
sudo pecl channel-update pecl.php.net
```

Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us page or join our Slack channel.
