OpenTelemetry Slim Framework: Instrumentation and Monitoring Guide

Vladimir Mihailenco
March 02, 2026
6 min read

OpenTelemetry Slim instrumentation provides automatic tracing for HTTP requests, routing, and middleware in Slim PHP applications. Using opentelemetry-auto-slim, you can add observability to your PHP microservices and track request latencies, database queries, and errors across distributed systems.

Quick Reference

ComponentPackagePurpose
Slim Auto-Instrumentopen-telemetry/opentelemetry-auto-slimAuto-trace HTTP requests
PDO Instrumentationopen-telemetry/opentelemetry-auto-pdoTrace database queries
Guzzle Instrumentationopen-telemetry/opentelemetry-auto-guzzleTrace outgoing HTTP calls
OpenTelemetry SDKopen-telemetry/sdkCore SDK and exporters

What is OpenTelemetry?

OpenTelemetry is an open-source observability framework that standardizes the collection of telemetry data from applications. It provides three pillars of observability:

  • Distributed Traces: Track requests across services and components
  • Metrics: Collect quantitative measurements of application performance
  • Logs: Capture structured application logs with trace correlation

OpenTelemetry is vendor-neutral, meaning you can export data to any compatible OpenTelemetry backend such as Uptrace, Jaeger, or Grafana. Deploying an OpenTelemetry Collector in your infrastructure provides enhanced telemetry data processing capabilities, including filtering, enrichment, and batching before data reaches your backend.

Prerequisites

  • PHP 8.1+
  • Slim Framework 4.x
  • Composer for dependency management
  • OpenTelemetry PHP extension

Step 1: Install the OpenTelemetry Extension

The OpenTelemetry PHP extension enables auto-instrumentation by hooking into PHP function calls at the runtime level.

Install Build Dependencies

shell Linux (apt)
sudo apt-get install gcc make autoconf php-dev
shell macOS (homebrew)
brew install gcc make autoconf

Install the Extension

shell pecl
pecl install opentelemetry
shell pickle
php pickle.phar install opentelemetry
shell php-extension-installer (Docker)
install-php-extensions opentelemetry

Enable the Extension

Add to your php.ini file (run php --ini to find the location):

ini
[opentelemetry]
extension=opentelemetry.so

Verify Installation

shell
php -m | grep opentelemetry

Step 2: Install Slim Instrumentation

The Slim auto-instrumentation package registers hooks via Composer that automatically create spans for App::handle() and routing middleware.

shell
composer require open-telemetry/opentelemetry-auto-slim

Install the OpenTelemetry SDK and OTLP exporter:

shell
# Core SDK
composer require open-telemetry/sdk

# OTLP exporter (gRPC or HTTP)
composer require open-telemetry/exporter-otlp

# Required transport
composer require php-http/guzzle7-adapter

Step 3: Configure OpenTelemetry

Using Uptrace SDK

The simplest approach is the Uptrace PHP SDK, which bundles the OpenTelemetry SDK with sensible defaults:

shell
composer require uptrace/uptrace

In your public/index.php, add configuration right after the autoloader:

php
<?php

require __DIR__ . '/../vendor/autoload.php';

// Configure OpenTelemetry with Uptrace
$uptrace = Uptrace\Distro::builder()
    // Set DSN here or use UPTRACE_DSN env var
    ->setDsn('<FIXME>')
    ->setServiceName('slim-app')
    ->setServiceVersion('1.0.0')
    ->buildAndRegisterGlobal();

// Create Slim app
$app = Slim\Factory\AppFactory::create();

$app->get('/', function ($request, $response) {
    $response->getBody()->write('Hello, World!');
    return $response;
});

$app->get('/health', function ($request, $response) {
    $response->getBody()->write(json_encode(['status' => 'ok']));
    return $response->withHeader('Content-Type', 'application/json');
});

$app->run();

Using OpenTelemetry SDK Directly

For a vendor-neutral setup, configure the SDK through environment variables:

shell
export OTEL_SERVICE_NAME="slim-app"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.uptrace.dev:4317"
export OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<FIXME>"
export OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
export OTEL_PHP_AUTOLOAD_ENABLED="true"

With OTEL_PHP_AUTOLOAD_ENABLED=true, the SDK initializes automatically via Composer and no code changes are needed. For more details, see the OpenTelemetry PHP guide.

Custom Instrumentation

Add custom spans to trace specific business logic beyond automatic instrumentation:

php
<?php

use OpenTelemetry\API\Globals;
use OpenTelemetry\API\Trace\StatusCode;

$app->post('/api/orders', function ($request, $response) {
    $tracer = Globals::tracerProvider()->getTracer('slim-app');
    $span = $tracer->spanBuilder('create-order')->startSpan();
    $scope = $span->activate();

    try {
        $data = json_decode($request->getBody()->getContents(), true);
        $span->setAttribute('order.customer_id', $data['customer_id'] ?? '');
        $span->setAttribute('order.item_count', count($data['items'] ?? []));

        // Validate order
        $validateSpan = $tracer->spanBuilder('validate-order')->startSpan();
        validateOrder($data);
        $validateSpan->end();

        // Save to database
        $dbSpan = $tracer->spanBuilder('save-order')->startSpan();
        $dbSpan->setAttribute('db.operation', 'INSERT');
        $dbSpan->setAttribute('db.table', 'orders');
        $orderId = saveOrder($data);
        $dbSpan->end();

        $span->setAttribute('order.id', $orderId);
        $response->getBody()->write(json_encode(['order_id' => $orderId]));
        return $response->withHeader('Content-Type', 'application/json');

    } catch (\Exception $e) {
        $span->recordException($e);
        $span->setStatus(StatusCode::STATUS_ERROR, $e->getMessage());
        $response->getBody()->write(json_encode(['error' => $e->getMessage()]));
        return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
    } finally {
        $scope->detach();
        $span->end();
    }
});

Tracing Middleware

Create reusable middleware for cross-cutting tracing concerns:

php
<?php

use OpenTelemetry\API\Globals;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as Handler;
use Slim\Psr7\Response;

$app->add(function (Request $request, Handler $handler) {
    $tracer = Globals::tracerProvider()->getTracer('slim-app');
    $span = $tracer->spanBuilder('request-middleware')->startSpan();
    $scope = $span->activate();

    try {
        // Add request metadata
        $span->setAttribute('http.user_agent', $request->getHeaderLine('User-Agent'));
        $span->setAttribute('client.ip', $request->getServerParams()['REMOTE_ADDR'] ?? '');

        $response = $handler->handle($request);

        $span->setAttribute('http.status_code', $response->getStatusCode());
        return $response;
    } finally {
        $scope->detach();
        $span->end();
    }
});

Database Instrumentation

PDO Auto-Instrumentation

Automatically trace all PDO database queries:

shell
composer require open-telemetry/opentelemetry-auto-pdo

No code changes are needed. All queries executed through PDO will be automatically traced with query text, execution time, and database metadata.

Eloquent (via Illuminate Database)

If you use Illuminate Database (Eloquent) with Slim:

shell
composer require open-telemetry/opentelemetry-auto-laravel

This traces Eloquent queries, model events, and database transactions via the Laravel auto-instrumentation package, which covers the Illuminate database layer.

Environment Variables Configuration

Configure OpenTelemetry through environment variables for production:

VariableDescriptionExample Value
OTEL_SERVICE_NAMEService nameslim-app
OTEL_EXPORTER_OTLP_ENDPOINTOTLP collector endpointhttps://api.uptrace.dev:4317
OTEL_EXPORTER_OTLP_HEADERSAuthentication headersuptrace-dsn=<FIXME>
OTEL_TRACES_SAMPLERSampling strategyparentbased_traceidratio
OTEL_TRACES_SAMPLER_ARGSampling ratio (0.0 to 1.0)0.1
OTEL_PHP_AUTOLOAD_ENABLEDAuto-init via Composertrue
OTEL_EXPORTER_OTLP_COMPRESSIONCompression algorithmgzip

For the full list, see the OpenTelemetry environment variables reference.

Docker Deployment

Deploy a Slim application with OpenTelemetry in Docker:

dockerfile
FROM php:8.3-apache

# Install php-extension-installer, then use it to add the OpenTelemetry extension
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions opentelemetry

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY . .

# Point Apache to Slim's public/ directory
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf && \
    a2enmod rewrite

# Configure OpenTelemetry via environment variables
ENV OTEL_SERVICE_NAME="slim-app"
ENV OTEL_TRACES_EXPORTER="otlp"
ENV OTEL_METRICS_EXPORTER="otlp"
ENV OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
ENV OTEL_PHP_AUTOLOAD_ENABLED="true"

EXPOSE 80

With Docker Compose:

yaml
version: '3.8'

services:
  slim-app:
    build: .
    ports:
      - "80:80"
    environment:
      - OTEL_SERVICE_NAME=slim-app
      - OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317
      - OTEL_EXPORTER_OTLP_HEADERS=uptrace-dsn=${UPTRACE_DSN}
      - OTEL_PHP_AUTOLOAD_ENABLED=true
    depends_on:
      - mysql

  mysql:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: slimapp

For a complete Docker setup with the OpenTelemetry Collector, see the Docker deployment guide.

PHP-FPM Considerations

When running Slim behind PHP-FPM, telemetry is exported at the end of each request. For high-traffic applications, consider:

  • Using the OpenTelemetry Collector as a local relay to batch and forward telemetry
  • Adjusting batch processor settings via environment variables
  • Monitoring PHP-FPM worker pool usage alongside application traces

For PHP-FPM-specific configuration, see the PHP-FPM instrumentation guide.

Troubleshooting

Extension not loading: Verify with php -m | grep opentelemetry. If missing, check that php.ini has the correct extension=opentelemetry.so line and the .so file exists in the extensions directory (php -i | grep extension_dir).

No traces appearing: Confirm OTEL_EXPORTER_OTLP_ENDPOINT is reachable. Check PHP error logs for SDK initialization errors.

Auto-instrumentation not working: Ensure OTEL_PHP_AUTOLOAD_ENABLED=true is set, or verify that Uptrace/SDK initialization happens before $app->run().

High memory usage: Reduce the batch processor queue size:

shell
export OTEL_BSP_MAX_QUEUE_SIZE=512
export OTEL_BSP_MAX_EXPORT_BATCH_SIZE=128

Debug logging: Enable verbose output:

shell
export OTEL_LOG_LEVEL=debug

What is Uptrace?

Uptrace is an OpenTelemetry APM that supports distributed tracing, metrics, and logs. You can use it to monitor applications and troubleshoot issues.

Uptrace Overview

Uptrace comes with an intuitive query builder, rich dashboards, alerting rules with notifications, and integrations for most languages and frameworks.

Uptrace can process billions of spans and metrics on a single server and allows you to monitor your applications at 10x lower cost.

In just a few minutes, you can try Uptrace by visiting the cloud demo (no login required) or running it locally with Docker. The source code is available on GitHub.

What's next?

Your Slim application is now instrumented with OpenTelemetry for comprehensive monitoring. Next steps: